【Unity/XLua】xlua自带教程示例分析(二)—— 使用C#控制Lua生命周期函数并为其注入Unity物体依赖

文章目录

第一步 创建C#类LuaBehaviour,负责控制Lua的生命周期函数,创建Lua文件,内部提供所需生命周期函数和局部变量

lua 复制代码
local speed = 10
local lightCpnt = nil

function start()
	print("lua start...")
	print("injected object", lightObject)
	lightCpnt = lightObject:GetComponent(typeof(CS.UnityEngine.Light))
end

function update()
	local r = CS.UnityEngine.Vector3.up * CS.UnityEngine.Time.deltaTime * speed
	self.transform:Rotate(r)
	lightCpnt.color = CS.UnityEngine.Color(CS.UnityEngine.Mathf.Sin(CS.UnityEngine.Time.time) / 2 + 0.5, 0, 0, 1)
end

function ondestroy()
    print("lua destroy")
end

lua脚本中,访问了注入的lightObject,并由其成员函数获得该GameObject上的灯光组件

使用CS.UnityEngine访问Unity的变量和函数,设置自身(self在后续C#中被设为了this)的旋转,以及灯光组件的颜色

第二步 准备C#变量

cs 复制代码
[System.Serializable]
public class Injection
{
    public string name;
    public GameObject value;
}
cs 复制代码
public TextAsset luaScript;
public Injection[] injections;

声明一个TextAsset接收一个需要运行的lua的文本文件,声明一个injections数组用于为lua表注入全局依赖

cs 复制代码
internal static LuaEnv luaEnv = new LuaEnv(); //all lua behaviour shared one luaenv only!
internal static float lastGCTime = 0;
internal const float GCInterval = 1;//1 second 

声明一个LuaEnv用于运行Lua环境,lastGCTime和GCInterval负责定时进行手动GC操作

cs 复制代码
private Action luaStart;
private Action luaUpdate;
private Action luaOnDestroy;

private LuaTable scriptScopeTable;

三个委托负责用于接收Lua表的对应生命周期函数,LuaTable则代表着一个独立的脚本域,可有效防止脚本间的全局变量,函数的名称冲突

第三步 Awake函数初始化

cs 复制代码
// 为每个脚本设置一个独立的脚本域,可一定程度上防止脚本间全局变量、函数冲突
scriptScopeTable = luaEnv.NewTable();

// 设置其元表的 __index, 使其能够访问全局变量
using (LuaTable meta = luaEnv.NewTable())
{
    meta.Set("__index", luaEnv.Global);
    scriptScopeTable.SetMetaTable(meta);
}
     

使用luaEnv的NewTable函数创建一个新的LuaTable提供给局部脚本域scriptScopeTable

之后创建一个临时的NewTable,将其__index指向lua的全局G表,然后设置为scriptScopeTable的元表,保证了scriptScopeTable可以访问全局变量

cs 复制代码
// 将所需值注入到 Lua 脚本域中
scriptScopeTable.Set("self", this);
foreach (var injection in injections)
{
    scriptScopeTable.Set(injection.name, injection.value);
}

将该表的self设置为本C#类,并向其中增加依赖的名称与值

cs 复制代码
// 如果你希望在脚本内能够设置全局变量, 也可以直接将全局脚本域注入到当前脚本的脚本域中
// 这样, 你就可以在 Lua 脚本中通过 Global.XXX 来访问全局变量
// scriptScopeTable.Set("Global", luaEnv.Global);
cs 复制代码
// 执行脚本
luaEnv.DoString(luaScript.text, luaScript.name, scriptScopeTable);
     
// 从 Lua 脚本域中获取定义的函数
Action luaAwake = scriptScopeTable.Get<Action>("awake");
scriptScopeTable.Get("start", out luaStart);
scriptScopeTable.Get("update", out luaUpdate);
scriptScopeTable.Get("ondestroy", out luaOnDestroy);

if (luaAwake != null)
{
    luaAwake();
}

使用luaEnv的DoString进行脚本执行,参数分别是脚本内容,脚本名称,需要存储到的LuaTable

之后从该脚本中拿出声明周期函数,并绑定到对应的C#委托中,并进行调用

cs 复制代码
// Use this for initialization
void Start()
{
    if (luaStart != null)
    {
        luaStart();
    }
}

// Update is called once per frame
void Update()
{
    if (luaUpdate != null)
    {
        luaUpdate();
    }

    if (Time.time - LuaBehaviour.lastGCTime > GCInterval)
    {
        luaEnv.Tick();
        LuaBehaviour.lastGCTime = Time.time;
    }
}

void OnDestroy()
{
    if (luaOnDestroy != null)
    {
        luaOnDestroy();
    }

    scriptScopeTable.Dispose();
    luaOnDestroy = null;
    luaUpdate = null;
    luaStart = null;
    injections = null;
}
相关推荐
Envyᥫᩣ3 小时前
C#语言:从入门到精通
开发语言·c#
小春熙子7 小时前
Unity图形学之Shader结构
unity·游戏引擎·技术美术
IT技术分享社区9 小时前
C#实战:使用腾讯云识别服务轻松提取火车票信息
开发语言·c#·云计算·腾讯云·共识算法
Sitarrrr10 小时前
【Unity】ScriptableObject的应用和3D物体跟随鼠标移动:鼠标放置物体在场景中
3d·unity
极梦网络无忧10 小时前
Unity中IK动画与布偶死亡动画切换的实现
unity·游戏引擎·lucene
△曉風殘月〆16 小时前
WPF MVVM入门系列教程(二、依赖属性)
c#·wpf·mvvm
逐·風18 小时前
unity关于自定义渲染、内存管理、性能调优、复杂物理模拟、并行计算以及插件开发
前端·unity·c#
_oP_i19 小时前
Unity Addressables 系统处理 WebGL 打包本地资源的一种高效方式
unity·游戏引擎·webgl
m0_6569747421 小时前
C#中的集合类及其使用
开发语言·c#
九鼎科技-Leo21 小时前
了解 .NET 运行时与 .NET 框架:基础概念与相互关系
windows·c#·.net