xLua热更新框架笔记

流程

  1. 游戏对象上挂C#对接脚本,可以拖对象,C#对接脚本继承一个基类,使用xLua的Global.Get<LuaTable>("table名字")得到lua表,luaTable.Set给表注入成员,xLua还有新建表、设置元表、得到lua函数等操作。C#对接脚本用UnityAction<LuaTable>存从lua得到的生命周期函数,用luaTable.Get<UnityAction<LuaTable>>("Awake")等得到lua函数,在C#生命周期函数里执行;
  2. luaEnv.AddLoader增加从AB包加载lua脚本的方法,如果是安卓平台必须用UnityWebRequest异步加载则进入游戏先异步加载lua AB包在回调函数里和之后执行任何执行lua代码;
  3. 程序写好后把所有lua脚本后缀替换成.txt,打AB包。把从项目文件夹加载lua的方法注释掉验证从AB包加载lua成功。在编辑器里使用Android AB包加载lua没问题,只有某些粒子效果会变粉色,到Android平台就会正常;
  4. 测试时能明显看到初始显示的面板有一个延迟。

传递C#对象给Lua

不能在编辑器拖对象,根对象使用GameObject.Find(),子对象使用transform.Find()寻找。

function PanelMain:Open()--使用Find获得控件的笨方法
    if self.obj==nil then
        prefab=ABManager:LoadRes(uiAB,"PanelMain",typeof(GameObject))
        self.obj=GameObject.Instantiate(prefab)
        self.obj.transform:SetParent(Canvas.transform,false)
        self.buttonPlay=self.obj.transform:Find("ButtonPlay"):GetComponent(typeof(Button))
        self.buttonSettings=self.obj.transform:Find("ButtonSettings"):GetComponent(typeof(Button))
        self.buttonRank=self.obj.transform:Find("ButtonRank"):GetComponent(typeof(Button))
        self.buttonPlay.onClick:AddListener(function()
            self:ClickPlay()
        end)
        self.buttonSettings.onClick:AddListener(function()
            self:ClickSettings()
        end)
        self.buttonRank.onClick:AddListener(function()
            self:ClickRank()
        end)
    else
        self.obj:SetActive(true)
    end
end

除此还有什么方法吗?一个C#脚本可以用luaTable.Set()给表写入成员。

luaTable = MyXLuaManager.Instance.Global.Get<LuaTable>(luaTableName);
        luaTable.Set("obj",gameObject);

传递面板的控件给Lua

对于一个面板,有Image、Text、Button等组件。如果一个面板有专用的C#脚本,那么每个面板都有一个C#脚本,脚本数量增加了一倍。我尝试使用UGUI控件的共同父类UIBehaviour列表,结果lua得到的都是UIBehaviour对象,根本没有按钮的onClick这些各种控件独有的成员。

那么还想用列表注入,就还需要把具体类型传过去,但是Type不能序列化到检查器,无法在编辑器配置类型。

然后懒得设计,就给每个面板专用一个C#脚本。这些脚本的共同点是获取Lua的生命周期函数,在生命周期函数里执行,所以它们继承这样的基类。

//得到一个lua表,注入一些成员,执行它的生命周期函数
public class LuaSingleton : MonoBehaviour{
    public string luaScriptName;
    public string luaTableName;
    protected LuaTable luaTable;
    protected UnityAction awake, start, update, onDestroy;
    protected void InitTable()
    {
        if (luaScriptName != null && luaScriptName != "")
        {
            MyXLuaManager.Instance.DoLuaFile(luaScriptName);
        }
        luaTable = MyXLuaManager.Instance.Global.Get<LuaTable>(luaTableName);
        luaTable.Set("obj", gameObject);
    }
    protected virtual void InjectTable()
    {
        
    }
    protected virtual void Awake()
    {
        InitTable();
        awake = luaTable.Get<UnityAction>("Awake");
        start = luaTable.Get<UnityAction>("Start");
        update = luaTable.Get<UnityAction>("Update");
        onDestroy = luaTable.Get<UnityAction>("OnDestroy");
        awake?.Invoke();
    }
    void Start()
    {
        start?.Invoke();
    }
    void Update(){
        update?.Invoke();
    }
    void OnDestroy()
    {
        onDestroy?.Invoke();
        luaTable.Dispose();
    }
}

各面板和基类只有注入的成员不同

public class PanelMainLua : LuaSingleton{
    public Button buttonPlay,buttonSettings,buttonRank;
    protected override void InjectTable()
    {
        base.InjectTable();
        luaTable.Set(nameof(buttonPlay), buttonPlay);
        luaTable.Set(nameof(buttonSettings), buttonSettings);
        luaTable.Set(nameof(buttonRank), buttonRank);
    }
}

然后如果加载面板由Lua完成,就变成Lua加载面板>C#脚本执行Awake()>执行Lua Awake(),里面执行初始化。这种踢皮球的流程,省去了找控件的代码,可以继续用拖拽控件,也可以执行生命周期函数。

function PanelMain:Load()
    local prefab=ABManager:LoadRes(uiAB,"PanelMain",typeof(GameObject))
    self.obj=GameObject.Instantiate(prefab,Canvas.transform)
end
function PanelMain:Init()
        
        -- self.obj.transform:SetParent(,false)
        self.buttonPlay.onClick:AddListener(function()
            self:ClickPlay()
        end)
        self.buttonSettings.onClick:AddListener(function()
            self:ClickSettings()
        end)
        self.buttonRank.onClick:AddListener(function()
            self:ClickRank()
        end)
end
function PanelMain.Awake()
    PanelMain:Init()
end

传递多实例对象给Lua

有一个“类表”,创建一个新表,设置类表为元表。和写面板一样的思想,原来每个C#类现在充当到Lua的桥接器,C#脚本数不变,增加Lua脚本,总脚本数增加一倍。

public class LuaInstance : MonoBehaviour
{
    public string luaScriptName;
    public string luaClassTableName;
    protected LuaTable luaClassTable, luaTable;
    UnityAction awake, start, update, onDestroy;
    UnityAction<LuaTable,GameObject>onTriggerEnter;
    protected virtual void InjectObjects()
    {
        
    }
    void Awake()
    {
        if (luaScriptName != null && luaScriptName != "")
        {
            MyXLuaManager.Instance.DoLuaFile(luaScriptName);
        }
        luaClassTable = MyXLuaManager.Instance.Global.Get<LuaTable>(luaClassTableName);
        luaTable = MyXLuaManager.Instance.luaEnv.NewTable();
        luaTable.SetMetaTable(luaClassTable);
        luaTable.Set("obj",gameObject);
        InjectObjects();
        awake = luaClassTable.Get<UnityAction>("Awake");
        start = luaClassTable.Get<UnityAction>("Start");
        update = luaClassTable.Get<UnityAction>("Update");
        onTriggerEnter=luaClassTable.Get<UnityAction<LuaTable,GameObject>>("OnTriggerEnter");
        onDestroy = luaC
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值