鸟语天空
xLua——LuaBehaviour
post by:追风剑情 2021-8-19 11:28

第一版设计

using System;
using UnityEngine;
using XLua;
/// <summary>
/// 集成Lua功能的行为类
/// 将Lua table中的函数 映射到 delegate
/// 这种是建议的方式,性能好很多,而且类型安全。缺点是要生成代码(如果没生成代码会抛InvalidCastException异常)。
/// </summary>
[LuaCallCSharp]
public class LuaBehaviour : MonoBehaviour
{
    [SerializeField]
    private Injection[] injections;
    private Action<LuaTable> luaAwake;
    private Action<LuaTable> luaOnEnable;
    private Action<LuaTable> luaOnDisable;
    private Action<LuaTable> luaStart;
    private Action<LuaTable> luaUpdate;
    private Action<LuaTable> luaLateUpdate;
    private Action<LuaTable> luaOnDestroy;
    private LuaTable scriptEnv;

    //关联 Lua Script
    public void AttachLuaScript(LuaTable scriptEnv)
    {
        if (scriptEnv == null)
        {
            DisposeLuaReference();
            return;
        }

        this.scriptEnv = scriptEnv;
        scriptEnv.Set("gameObject", gameObject);
        scriptEnv.Set("transform", transform);
        //如果是UGUI
        RectTransform rectTransform = this.GetComponent<RectTransform>();
        if (rectTransform != null)
            scriptEnv.Set("rectTransform", rectTransform);

        if (injections != null)
        {
            foreach (var injection in injections)
                scriptEnv.Set(injection.name, injection.value);
        }

        //调用构造函数
        var ctor = scriptEnv.Get<LuaClassCtor>("ctor");
        if (ctor != null)
            ctor(scriptEnv, this);

        /*
        //LuaFunction有装箱、拆箱操作,性能较低
        var ctor = scriptEnv.Get<LuaFunction>("ctor");
        if (ctor != null)
            ctor.Call(scriptEnv, this);
        */

        scriptEnv.Get("Awake", out luaAwake);
        scriptEnv.Get("OnEnable", out luaOnEnable);
        scriptEnv.Get("OnDisable", out luaOnDisable);
        scriptEnv.Get("Start", out luaStart);
        scriptEnv.Get("Update", out luaUpdate);
        scriptEnv.Get("LateUpdate", out luaLateUpdate);
        scriptEnv.Get("OnDestroy", out luaOnDestroy);

        if (luaAwake != null)
            luaAwake(scriptEnv);

        if (luaOnEnable != null)
            luaOnEnable(scriptEnv);
    }

    //Awake()会在AttachLuaScript()之前执行
    private void Awake()
    {
        OnAwake();
    }

    //OnEnable()会在AttachLuaScript()之前执行
    private void OnEnable()
    {
        if (luaOnEnable != null)
            luaOnEnable(scriptEnv);
        else
            OnIEnable();
    }

    private void OnDisable()
    {
        if (luaOnDisable != null)
            luaOnDisable(scriptEnv);
        else
            OnIDisable();
    }

    private void Start()
    {
        if (luaStart != null)
            luaStart(scriptEnv);
        else
            OnStart();
    }

    private void Update()
    {
        if (luaUpdate != null)
            luaUpdate(scriptEnv);
        else
            OnUpdate();
    }

    private void LateUpdate()
    {
        if (luaLateUpdate != null)
            luaLateUpdate(scriptEnv);
        else
            OnLateUpdate();
    }

    private void OnDestroy()
    {
        DisposeLuaReference();
        OnIDestroy();
    }

    //释放Lua相关的引用
    public void DisposeLuaReference()
    {
        if (luaOnDestroy != null)
            luaOnDestroy(scriptEnv);
        if (scriptEnv != null)
            scriptEnv.Dispose();
        scriptEnv = null;
        luaOnDestroy = null;
        luaUpdate = null;
        luaLateUpdate = null;
        luaStart = null;
        luaOnEnable = null;
        luaOnDisable = null;
        luaAwake = null;
    }

    protected virtual void OnAwake() { }
    protected virtual void OnIEnable() { }
    protected virtual void OnIDisable() { }
    protected virtual void OnStart() { }
    protected virtual void OnUpdate() { }
    protected virtual void OnLateUpdate() { }
    protected virtual void OnIDestroy() { }
}

[CSharpCallLua]
public delegate void LuaClassCtor(LuaTable self, LuaBehaviour luaBehaviour);

[Serializable]
public class Injection
{
    public string name;
    public GameObject value;
}


第二版设计


using System;
using UnityEngine;
using XLua;
/// <summary>
/// 集成Lua功能的行为类
/// 将Lua table中的函数 映射到 interface
/// 这种是建议的方式,性能好很多,而且类型安全。缺点是要生成代码(如果没生成代码会抛InvalidCastException异常)。
/// </summary>
[LuaCallCSharp]
public class LuaBehaviour : MonoBehaviour
{
    [SerializeField]
    private Injection[] injections;
    private LuaTable scriptEnv;
    private ILuaTableBehaviour luaBehaviour;

    //关联 Lua Script
    public void AttachLuaScript(LuaTable scriptEnv)
    {
        if (scriptEnv == null)
        {
            DisposeLuaReference();
            return;
        }

        this.scriptEnv = scriptEnv;
        scriptEnv.Set("this", this);
        scriptEnv.Set("gameObject", gameObject);
        scriptEnv.Set("transform", transform);
        //如果是UGUI
        RectTransform rectTransform = this.GetComponent<RectTransform>();
        if (rectTransform != null)
            scriptEnv.Set("rectTransform", rectTransform);

        if (injections != null)
        {
            foreach (var injection in injections)
                scriptEnv.Set(injection.name, injection.value);
        }

        //LuaTable映射成interface
        luaBehaviour = scriptEnv.Cast<ILuaTableBehaviour>();
        luaBehaviour.ctor(this);
        luaBehaviour.Awake();
        luaBehaviour.OnEnable();
    }

    //Awake()会在AttachLuaScript()之前执行
    private void Awake()
    {
        
    }

    //OnEnable()会在AttachLuaScript()之前执行
    private void OnEnable()
    {
        if (luaBehaviour != null)
            luaBehaviour.OnEnable();
    }

    private void OnDisable()
    {
        if (luaBehaviour != null)
            luaBehaviour.OnDisable();
    }

    private void Start()
    {
        if (luaBehaviour != null)
            luaBehaviour.Start();
    }

    private void Update()
    {
        if (luaBehaviour != null)
            luaBehaviour.Update();
    }

    private void LateUpdate()
    {
        if (luaBehaviour != null)
            luaBehaviour.LateUpdate();
    }

    private void OnDestroy()
    {
        DisposeLuaReference();
    }

    //释放Lua相关的引用
    public void DisposeLuaReference()
    {
        if (luaBehaviour != null)
            luaBehaviour.OnDestroy();
        if (scriptEnv != null)
            scriptEnv.Dispose();

        luaBehaviour = null;
        scriptEnv = null;
    }
}

[Serializable]
public class Injection
{
    public string name;
    public GameObject value;
}

[CSharpCallLua]
public interface ILuaTableBehaviour
{
    //接口方法无需将table作为第1个参数回传,lua侧也能拿到self
    void ctor(LuaBehaviour luaBehaviour);
    void Awake();
    void OnEnable();
    void OnDisable();
    void Start();
    void Update();
    void LateUpdate();
    void OnDestroy();
}


评论:
发表评论:
昵称

邮件地址 (选填)

个人主页 (选填)

内容