XLua實現基於MVC框架的熱更新架構
阿新 • • 發佈:2019-02-03
1、將XLua的包匯入工程
2 -1、編寫程式的主入口指令碼GameMgr、用於啟動Lua程式
`public class GameMgr : MonoBehaviour {
private void Awake()
{
gameObject.AddComponent<LuaMgr>();
}
private void Start()
{
LuaMgr.Instance.DoString("require 'Script/Xlua/XLuaFrame/Common/Main'");
}
}`
2 - 2 編寫LuaMgr指令碼、用於例項化全域性唯一的Lua環境變數、並且載入所有的lua指令碼
`
public class LuaMgr : MonoBehaviour {
public static LuaMgr Instance; public static LuaEnv luaEnv; private void Awake() { DontDestroyOnLoad(this); Instance = this; luaEnv = new LuaEnv(); //設定xlua指令碼的路徑 路徑根據實際需求修改 luaEnv.DoString(string.Format("package.path = '{0}/?.lua'", Application.dataPath)); } public void DoString(string str) { luaEnv.DoString(str); }
}
`
3、Main.lua — 尋找到GameInit的指令碼、執行初始化Init操作。開始初始化lua指令碼
require "Script/Xlua/XLuaFrame/Common/GameInit" -- require 尋找到GameInit.lua指令碼的引用
GameInit.Init();
4-1 GameInit.Lua 指令碼、初始化所有的View指令碼、同事提供載入Ctrl指令碼的方法
require "Script/Xlua/XLuaFrame/Common/CtrlMgr";
-- CtrlMgr.lua 管理控制器指令碼、裡面table 表儲存其名字及其對應的ctrl指令碼的例項 --
GameInit = {};
local this = GameInit;
-- 將View的指令碼一一註冊進去
function GameInit.InitViews()
require('Script/Xlua/XLuaFrame/Modules/UIRoot/UIRootView');
end
--初始化方法 ctrl 和 view 同時載入root介面
function GameInit.Init()
this.InitViews();
CtrlMgr.Init();
GameInit.loadView(CtrlNames.UIRootCtrl);
end
--從控制器中拿出一個來呼叫它的Awake方法 載入窗體--
function GameInit.loadView(type)
local ctrl = CtrlMgr.GetCtrl(type);
if ctrl ~= nil then
ctrl.Awake();
end
end
4-2 CtrlMgr.lua 指令碼 初始化所有的控制器指令碼、儲存到table表中
require "Script/Xlua/XLuaFrame/Common/Define"
--註冊UI控制器 (動態新增)------------------
require "Script/Xlua/XLuaFrame/Modules/UIRoot/UIRootCtrl"
CtrlMgr = {};
local this = CtrlMgr;
local ctrlList = {};
--初始化方法 往列表中新增所有的控制器
function CtrlMgr.Init()
-- 註冊控制器到table表中(動態新增)------------------
ctrlList[CtrlNames.UIRootCtrl] = UIRootCtrl.New();
return this;
end
--根據控制器的名稱 獲取控制器
function CtrlMgr.GetCtrl(ctrlName)
return ctrlList[ctrlName];
end
5、Define.lua 提供公共的變數、及其反射unity中的api到Lua中`print(‘啟動了Define.lua’)
-- 沒新加一個視窗、要在該指令碼新增該視窗的引用 同事在CtrlMgr.lua中註冊該視窗 GameInit.lua中註冊它對應的View檢視指令碼
CtrlNames=
{
UIRootCtrl = "UIRootCtrl"
}
--這裡要把常用的引擎型別加起來
WWW = CS.UnityEngine.WWW;
GameObject = CS.UnityEngine.GameObject;
Color = CS.UnityEngine.Color;
Vector3 = CS.UnityEngine.Vector3;`
6 提供Lua中Ctrl 和 View的兩個模板例項、所有指令碼都應該已此為模板
View 指令碼主要用於查詢元件、反射Unity中的指令碼生命週期方法
UIRootView = {};
local this = UIRootView;
local transform; -- 自身的transform引用
local gameobject; -- 自身的gameobject引用
function UIRootView.awake(obj)
gameobject = obj;
transform = obj.transform;
this.InitView();
end
--初始化面板 找到UI元件
function UIRootView.InitView()
--尋找元件
this.btnOpenTask = transform:FindChild("Bg/btnOpenTask"):GetComponent("UnityEngine.UI.Button");
end
function UIRootView.start()
end
function UIRootView.update()
end
function UIRootView.ondestory()
end
Ctrl指令碼 主要用於控制UI的載入、顯示、事件的點選回撥
UIRootCtrl = {};
local this = UIRootCtrl;
local root;
local transform;
local gameobject;
function UIRootCtrl.New()
return this;
end
function UIRootCtrl.Awake()
print('主介面、啟動了');
--這裡的方法就是負責把UI給克隆出來 遇到方法時 使用 : 加上後面的方法
CS.LuaHelperManager.Instance:LoadUI("XluaPrefab/UIRootView",this.OnCreate);
--CS.LuaHelperManager 去呼叫Unity中的LuaHelperManager指令碼中的方法載入UI及其回撥
end
-- Awake載入UI的回撥(返回克隆的obj物件)
function UIRootCtrl.OnCreate(obj)
print('UI克隆完畢的回撥');
local btnOpenTask = UIRootView.btnOpenTask;
btnOpenTask.onClick:AddListener(UIRootCtrl.OnBtnOpenTaskClick);
end
-- 按鈕點選的方法
function UIRootCtrl.OnBtnOpenTaskClick()
end
以上已經說了怎麼Lua中的架構搭建、那麼怎麼將Unity中的生命週期給lua呼叫呢?
7、Lua呼叫C#中的方法載入UI窗體
//Lua中呼叫該C#指令碼 執行前XLua Generate Code 執行一下
[LuaCallCSharp]
public class LuaHelperManager
{
protected static LuaHelperManager mInstance;
protected LuaHelperManager(){ }
public static LuaHelperManager Instance
{
get
{
if (mInstance == null)
{
mInstance = new LuaHelperManager();
}
return mInstance;
}
}
/// <summary>
/// Xlua層載入UI面板
/// </summary>
/// <param name="path"> 路徑 </param>
/// <param name="OnCreate"> 創建出來的委託回撥 </param>
public void LoadUI(string path,XLuaCustomExport.OnCreate OnCreate)
{
Debug.Log("載入UI窗體 ==" + path);
GameObject obj = GameObject.Instantiate(Resources.Load<GameObject>(path));
if (OnCreate != null)
{
obj.GetOrAddCompent<LuaViewBehaviour>();
OnCreate(obj);
}
}
}
/// <summary>
/// XLua的自定義拓展
/// </summary>
public static class XLuaCustomExport {
[CSharpCallLua]
public delegate void OnCreate(GameObject obj);
}
8 加載出來的UI窗體Panel掛載上LuaViewBehaviour指令碼、同事將Unity中的指令碼生命週期方法回撥給Unity
public class LuaViewBehaviour:MonoBehaviour {
[CSharpCallLua]
public delegate void delLuaAwake(GameObject obj);
LuaViewBehaviour.delLuaAwake luaAwake;
[CSharpCallLua]
public delegate void delLuaStart();
LuaViewBehaviour.delLuaStart luaStart;
[CSharpCallLua]
public delegate void delLuaUpdate();
LuaViewBehaviour.delLuaUpdate luaUpdate;
[CSharpCallLua]
public delegate void delLuaOnDestroy();
LuaViewBehaviour.delLuaOnDestroy luaOnDestroy;
private LuaTable scriptEnv;
private LuaEnv luaEnv;
private void Awake()
{
//獲取全域性的Lua環境變數
luaEnv = LuaMgr.luaEnv;
scriptEnv = luaEnv.NewTable();
LuaTable meta = luaEnv.NewTable();
meta.Set("__index",luaEnv.Global);
scriptEnv.SetMetaTable(meta);
meta.Dispose();
string prefabName = name;
//去掉克隆的關鍵字
if (prefabName.Contains("(Clone)"))
{
prefabName = prefabName.Split(new string[] { "(Clone)" }, StringSplitOptions.RemoveEmptyEntries)[0];
}
prefabName = prefabName.Replace("pan_", "");
// prefabName + ".awake" 要對應Lua指令碼中View的方法
luaAwake = scriptEnv.GetInPath<LuaViewBehaviour.delLuaAwake>(prefabName + ".awake");
luaStart = scriptEnv.GetInPath<LuaViewBehaviour.delLuaStart>(prefabName + ".start");
luaUpdate = scriptEnv.GetInPath<LuaViewBehaviour.delLuaUpdate>(prefabName + ".update");
luaOnDestroy = scriptEnv.GetInPath<LuaViewBehaviour.delLuaOnDestroy>(prefabName + ".ondestroy");
scriptEnv.Set("self", this);
if (luaAwake != null)
{
luaAwake(this.gameObject);
}
}
private void Start()
{
if (luaStart != null)
{
luaStart();
}
}
private void OnDestroy()
{
if (luaOnDestroy != null)
{
luaOnDestroy();
}
luaAwake = null;
luaOnDestroy = null;
luaUpdate = null;
luaStart = null;
}
}