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)[];
}
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;
}
}