生活随笔
收集整理的這篇文章主要介紹了
Pun2插件结合Xlua热更新开发 一、在lua中自定义PunRpc方法
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
需求
近有一個需求是在pun2聯網項目中結合純lua實現項目熱更新(這里使用的是xlua),起初在NetworkMgr框架搭建,房間搭建等非游戲操作邏輯中使用純lua開發一切正常,沒有發現什么問題。但是進入游戲角色邏輯開發時,就遇到了難題,眾所周知,pun2中有一個很好用的attribute,叫做[PunRpc]。 具體可看官方文檔:PunRpc標簽官方描述 但是lua中貌似并不支持給lua方法添加Attribute,既然官方不支持,網上也幾乎沒有看到有人使用pun2結合xlua開發的,那我們只能選擇自力更生,曲線救國的方式了。
初次嘗試
我這里想到的方法一開始是使用委托結合事件中心的方式去實現,但是報了一個錯誤**(LuaException: c# exception:Exception has been thrown by the target of an…)** 經過百度,谷歌,必應的搜索,都沒有解決,也許是我使用方式不對,其中還發現了一篇文章,可以在C#中不用頻繁添加PunRpc標簽,有興趣的可以跳轉去看:使用委托調用PunRpc
第二種方法
于是我想到了官方例子中的第二個例子,在Lua中實現UnityMono,這里解釋一下大概的原理就是在Lua中注冊委托,再讓C#繼承Mono的腳本調用改委托 詳情可以到官方例子中名為《02_U3DScripting》的文件夾去看。 代碼詳情:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using XLua;
using System;namespace XLuaTest
{[System.Serializable]public class Injection{public string name;public GameObject value;}[LuaCallCSharp]public class LuaBehaviour : MonoBehaviour{public TextAsset luaScript;public Injection[] injections;internal static LuaEnv luaEnv = new LuaEnv(); //all lua behaviour shared one luaenv only!internal static float lastGCTime = 0;internal const float GCInterval = 1;//1 second private Action luaStart;private Action luaUpdate;private Action luaOnDestroy;private LuaTable scriptEnv;void Awake(){scriptEnv = luaEnv.NewTable();// 為每個腳本設置一個獨立的環境,可一定程度上防止腳本間全局變量、函數沖突LuaTable meta = luaEnv.NewTable();meta.Set("__index", luaEnv.Global);scriptEnv.SetMetaTable(meta);meta.Dispose();scriptEnv.Set("self", this);foreach (var injection in injections){scriptEnv.Set(injection.name, injection.value);}luaEnv.DoString(luaScript.text, "LuaTestScript", scriptEnv);Action luaAwake = scriptEnv.Get<Action>("awake");scriptEnv.Get("start", out luaStart);scriptEnv.Get("update", out luaUpdate);scriptEnv.Get("ondestroy", out luaOnDestroy);if (luaAwake != null){luaAwake();}}// Use this for initializationvoid Start(){if (luaStart != null){luaStart();}}// Update is called once per framevoid Update(){if (luaUpdate != null){luaUpdate();}if (Time.time - LuaBehaviour.lastGCTime > GCInterval){luaEnv.Tick();LuaBehaviour.lastGCTime = Time.time;}}void OnDestroy(){if (luaOnDestroy != null){luaOnDestroy();}luaOnDestroy = null;luaUpdate = null;luaStart = null;scriptEnv.Dispose();injections = null;}}
}
理論可行,開始實踐
首先既然是Photon項目,那么游戲角色的腳本肯定是要繼承MonoBehaviourPun這個類的,于是仿照LuaBehaviour這個類,改造成LuaBehaviourPun,我也是剛學xlua沒多久的小白,寫的有點繁瑣,也請大家指證和優化。
using Photon.Pun;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;public class LuaBehaviourPun : MonoBehaviourPun
{
//由于改造LuaBehaviour不是重點,且篇幅太長,這里省略其他實現代碼,如果需要可以私聊我
.......public Action<string> punRpcAction;public void SetRpcAction(Action<string> action) => punRpcAction = action;public void ExecuteRpc(string key){this.photonView.RPC("RpcAction", RpcTarget.All, key);}[PunRPC]public void RpcAction(string key){punRpcAction?.Invoke(key);}
.......
}
重點其實就是一個Action變量punRpcAction,一個注冊委托方法SetRpcAction,以及最后兩個方法,一個方法加上[PunRPC]屬性,再使用另外一個方法調用photonView上的Rpc方法去調用我們自定義的Rpc方法,這部分是C#中的邏輯,而在lua中則直接為punRpcAction添加委托事件即可。 lua中的業務邏輯為:
--通過鍵名區分要調用什么方法,這里的例子是顯示或隱藏武器
--注冊RpcAction,編寫委托內邏輯self:SetRpcAction(function(key)if key=="ShowWeapon" thenlocal go=self.transform:GetChild(0).gameObjectgo:SetActive(not go.activeSelf)endend)
--調用Rpc方法,重點為Input.GetKeyDown下的邏輯self:SetAction("update",function()if self.photonView.IsMine and PhotonNetwork.IsConnected thenself.transform:Rotate(Vector3.up*Input.GetAxis("Horizontal")*Time.deltaTime*50)if Input.GetKeyDown(KeyCode.Space) thenself:ExecuteRpc("ShowWeapon")endendend)
最后效果,完美實現兩邊武器的顯隱同步,正確接收房主和玩家的Rpc請求。 實現了需求,但是肯定有正確的方法實現該功能,只是由于我還夠了解Lua工作流程,沒有想到方便快捷的方法。
總結
以上是生活随笔 為你收集整理的Pun2插件结合Xlua热更新开发 一、在lua中自定义PunRpc方法 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。