整个框架的目的就是把Lua脚本当C#脚本使用,包括但不限于将Lua脚本挂到GameObject上、Lua的面向对象、将C#的命名规范用在Lua上等等。
本框架在Unity2021.3.29版本上开发,在Unity2019.4.37版本上测试通过,如果需要运行在其他版本上,请尽量自行解决可能出现的版本兼容问题。

- 支持注入的嵌套层数: 8层
- 支持注入的数据类型: string、int、enum、float、bool、Color、Vector2/3/4、AnimationCurve、Object、GameObject、Transform、Behaviour、其他Component,另外还支持把另一个LuaBehaviour做成table注入进来。
- 支持的生命周期函数:
Awake、Start、Update、FixedUpdate、LateUpdate、OnEnable、OnDisable、OnDestroy、OnGUI
OnBecameVisible、OnBecameInvisible、OnApplicationFocus、OnApplicationPause、OnApplicationQuit
OnTriggerEnter/Stay/Exit、OnCollisionEnter/Stay/Exit、OnTriggerEnter2D/Stay2D/Exit2D、OnCollisionEnter2D/Stay2D/Exit2D
OnDrag、OnDrop、OnInitializePotentialDrag、OnBeginDrag、OnEndDrag
OnPointerClick、OnPointerDown、OnPointerUp、OnPointerEnter、OnPointerExit、OnScroll
OnSelect、OnDeselect、OnUpdateSelected、OnMove、OnSubmit、OnCancel
- XLua: 本框架是基于XLua开发的。
- EmmyLua:
- 本框架的Lua部分,是通过Rider+EmmyLua插件写的(VSCode也有,去对应的插件市场安装即可),EmmyLua用于代码提示与补全,不需要该功能可以不装EmmyLua插件。
- 本框架的成员变量结构生成是基于 EmmyLua的注解语法 的,请稍微浏览一下该文档。
- 最近EmmyLua有更新,新增了对namespace的支持,还支持了partial关键字等,如果项目里用到这些特性,则 DllToLuaLib功能 和 成员变量结构生成功能 会受到影响,暂时请自行修改相关逻辑。
- DOTween: 框架本身并没有用到DOTween,不过示例中用到了,这里的DOTween只是用来学习交流,如果需要在今后的开发中用到DOTween,请购买正版。
框架所有内容都在 Assets/Tools/LuaBehaviour/Scripts 目录下
- Lua的面向对象的封装、Property(get/set)的封装、Lua枚举的封装。
- LuaBehaviour相关功能: 包括Lua环境的初始化与释放、Unity各生命周期函数的调用、成员变量注入、Inspector面板绘制、成员变量结构生成等。
- 配合LuaBehaviour使用,用于储存数据的容器: LuaInjectionData、LuaScriptableData。
- 查看Lua表达式的值、重新载入某个脚本、执行任意Lua代码的小工具: LuaDataViewer。
示例所有内容都在 Assets/Tools/LuaBehaviour/Demo 目录下。
- 展示LuaBehaviour在UI方面的一种用法,包含一套简单的UI管理框架。
- 展示LuaBehaviour在3D方面的一种用法。
- 一些示例需要用到的封装,如一些扩展、AsyncTask、CoroutineManager、EventManager等。
- CSharpCallLua/LuaCallCSharp的配置,以及将其涉及到的程序集按 EmmyLua的注解语法 导出成注解的工具。
本工程内容可大致分为XLua、本框架、示例、DOTween插件四个部分。
- Assets/Plugins和Assets/XLua: XLua的内容,没有做任何修改。
- Assets/Tools/LuaBehaviour/Scripts: 本框架内容
- Assets/Tools/LuaBehaviour/Demo: 示例内容
- Assets/Tools/Demigiant: DOTween插件,没有做任何修改。
在原工程中配置好XLua的环境,将 Assets/Tools/LuaBehaviour/Scripts 整个文件夹拷贝到工程中即可。
- 将框架中的LuaMain进行自定义改造,以符合项目需要。(参考 Assets/Tools/LuaBehaviour/Demo/Scripts/LuaMain.cs )
- 示例中两个场景分别展示了LuaMain的两种用法:
- 在“UI”场景中,LuaMain被挂在了场景里的某个GameObject上,然后配置了作为入口的Lua脚本路径,推荐用此方法进行项目Lua环境的正式启动方式。
- 在“3D”场景中,LuaMain没有挂在任何GameObject上,靠LuaBehaviour调用LuaMain单例来启动Lua环境,比较适合测试场景。
- 打开ProjectSettings窗口,找到LuaBehaviour标签,设置Lua脚本的根目录和扩展名。(这里的设置只用于编辑器环境Lua脚本的拖放,运行环境的加载请用LuaEnv.AddLoader自己写逻辑。)

- 类似C#那样写Lua脚本,参考示例里的Lua脚本,继承Lua里的LuaBehaviour类。
- 在目标GameObject上挂上C#脚本LuaBehaviourWithPath。

如果看到了上面图片中的“LuaSrcPathSetting”按钮,说明第3步没有做,那么左边的文本框内需要自己填入require的路径,但不影响运行。

如果设置Lua脚本的根目录,那么左边的文本框会变成上面图片中的对象拖放框。

拖入某个Lua脚本后,右边会出现一个按钮,用于自动生成成员变量的结构。当然,也可以点击上面的“+”按钮手动添加成员变量。

生成出来的结构需要手动填入数据或拖入对象。 - 填入数据或拖入对象。运行时,这些数据会在Lua脚本的Awake函数执行之前,成为Lua类实例的成员变量。
- 如果想要在运行时动态给某个GameObject挂上LuaBehaviour,则可以挂上一个C#脚本LuaBehaviourDynamicAdd,然后传入一个Lua类Table。(参考 Assets/Tools/LuaBehaviour/Demo/Resources/Lua/Utils/BehaviourUtility.lua )
- 除了LuaBehaviour,还有LuaInjectionData和LuaScriptableData也是带数据的,后两者是单纯的只储存数据,使用方式有两种:
- 把LuaInjectionData或LuaScriptableData作为一个C#对象进行引用,然后通过调用实例.Data获取到table。
- 在LuaBehaviour的变量结构中新增一个类型为“Lua Table”的变量,那么LuaInjectionData或LuaScriptableData的数据将会以table的形式储存在LuaBehaviour的成员变量中。
- LuaInjectionData和LuaScriptableData没有拖放Lua脚本的地方,如果需要自动生成变量的结构,可以填入Lua类的类名。
- 注入数据每一行大致可分为操作按钮、类型、变量名、数据、类型约束5个部分。为了更清晰地展示,当Inspector界面宽度较窄时,会选择性地隐藏一部分内容。
- 操作按钮:
- 类型:
- “Space”用于分隔变量,无任何意义。
- “Int”用于填入整型或枚举。
- 当类型约束为某个C#枚举的名称时,数据会显示成枚举下拉框。由于涉及热更问题,可以在C#和Lua分别声明相同名称的枚举,C#的枚举用于Inspector显示,Lua的枚举用于实际运行。
- 当没有类型约束或者类型约束找不到对应名称的枚举时,数据会显示成整型输入框。由于Lua语言不区分整数和小数,需要在工程内任意位置写一行:
然后以“int”声明成员变量,以自动生成“Int”类型的变量结构。
---@alias int number
- “Lua Table”用于拖放LuaInjectionData、LuaScriptableData和另一个LuaBehaviour,自动转化为LuaTable。
- “List”和“Dict”用于注入复杂数据,也会自动转化为LuaTable。

- 变量名:“List”中的变量名不可用,显示成序号。
- 数据:不同的类型会显示不同的数据,如果类型是Component的派生类,则还会显示下拉框用于选择挂在同一GameObject上的不同组件实例。如果类型是Int,则会根据类型约束确定是否显示成枚举下拉框。
- 类型约束:用于更细致地约束数据类型。
- 用于将“Int”类型显示成枚举。
- 当类型为“Object”、“Behaviour”或“Other Comp”时,可以精确指定拖入对象的类型,也可以约束为多个派生类的基类。
- 由于Unity序列化的限制,被序列化的结构不能嵌套自身,所以每一层做成了不同的类型,最多支持8层。
这里的结构是根据Lua脚本里的注释生成的,使用的是 EmmyLua的注解语法。
另外我自定义了一些规则:
LuaBehaviour的Inspector面板在运行时还提供了查看Lua实例数据和临时执行Lua代码功能。
- 红色区域展示了Lua实例内部的数据,其中LuaFunction会带有两个按钮,一个是静态调用,一个是实例调用,后面跟着的是参数输入框,可以直接以写Lua代码的形式将多个参数传入,如“
1, "str", true”。 - 黄色区域提供了一个写Lua代码的输入框,可以以当前Lua实例作为self执行Lua代码。

从Window/LuaDataViewer菜单项可以打开一个工具窗口。
- 如何初始化Lua环境并调用Lua入口函数: 参考 Demo里的UI场景 和 Demo里的LuaMain脚本。
- 如何在测试场景中随意使用LuaBehaviour(自动初始化Lua环境但不调用Lua入口函数): 直接使用即可,参考 Demo里的3D场景。
- 如何使用EmmyLua进行Lua代码的提示:
- VSCode或者IDEA或者Rider里在插件市场搜索EmmyLua并安装
- 根据自己自己的IDE,Unity编辑器里分别点击“Xlua/EmmyLua/DllToLuaLib”和“Xlua/EmmyLua/GenerateNameSpaceMap”下的对应菜单项,等待生成完成后引入项目。具体细节请看 DllToLuaLib使用说明。
- 有什么疑问可以在QQ上搜EmmyLua群,去QQ群里问,插件相关的问题我也不太懂。
- XLua的LuaCallCSharp和CSharpCallLua是否需要修改: 不需要修改,示例中有一份 配置,是在XLua的ExampleConfig.cs的基础上根据经验添加了一点东西,可以作为参考。
- 示例还提供了一些基础的封装:
- GlobalExtension: pairs和ipairs支持遍历C#对象,log内容附上堆栈信息等。
- BehaviourUtility: 单例封装,用于外部监听Unity脚本生命周期函数的匿名LuaBehaviour类。
- AsyncTask: 方便执行异步任务的封装,有点像JavaScript的Promise。
- EventManager: 事件分发管理器。
- CoroutineManager: 协程管理器。
- UIManager: 简单手游的UI管理框架,对了,设计分辨率需要在 UIManager.lua) 文件开头修改。
- 最近EmmyLua有更新,新增了对namespace的支持,还支持了partial关键字等,如果项目里用到这些特性,则 DllToLuaLib功能 和 成员变量结构生成功能 会受到影响,暂时请自行修改相关逻辑。



