第一版设计
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();
}