LUA框架说明与使用
Unity热更新就会需要使用LUA,但是有些开发者在项目开发中对LUA框架的使用不是很清楚,为此,下面就给大家介绍下LUA框架的说明和使用。
· 类和实例,面向对象
· 组件(Component)化
· 事件化
· 类似MonoBehaviour,减少学习成本
详见Framework/LuaBehaviour.lua
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | local classic = require 'classic' local UIUtil = require 'Framework.UIUtil' local LuaBehaviour = classic. class ( "LuaBehaviour" ) function LuaBehaviour:_init(target, setting) self._target = target self._targetID = target:GetInstanceID() self._luaOperation = target:GetComponent( "LuaOperation" ) self._setting = setting self._visibleScope = GScope.Scope.Create( "globe.ui." .. self._targetID .. ".visible" ) UIUtil.BindElements(self) end return LuaBehaviour |
注意点:
A class system for Lua.
实现了Lua端的类,继承, 虚函数的概念
使用LuaBehaviour的代码,不要添加在GamePath.lua
必须要return,要把脚本中定义的class的原型return出来,以供BehaviourManager来进行实例化
BehaviourManager中的相关代码:
1 2 3 4 5 | function BehaviourManager:CreateBehaviour(typename, go) local path = typename local Class = require(path) local lb = Class(go) |
1 2 | this -> self base -> super |
根C#/C++中的概念是一致的
脚本中定义的是类,而我们实际使用时,使用的实例。这个是和老的Lua代码的本质的区别
由于我们在使用时,使用的是实例,就可以实现组件的概念,可以在一个Prefab上挂一个脚本,而这个Prefab可以实例化(GameObject.Instantiate)出很多个
示例:
每一个ExampleListItem(Clone)都有一个Lua那边定义ExampleListItem类的一个实例,是完全独立的,和MonoBehaviour的概念是一致的
有了组件化的支持后,我们就可以把一个复杂的界面,拆解成多个组件,以方便管理和重用
· OnAwake
· OnStart
· OnEnable
· OnVisible
· OnDisable
· OnDestroy
这些事件的调用时机和MonoBehaviour一致
OnVisible是一个特殊的自己加的一个函数,用于规避Unity无法控制Awake的顺序的问题
在Prefab第一次实例化的时候,OnVisible会在MonoBehaviour的Start调用时调用,当一个实例被SetActive时,OnVisible会在MonoBehaviour的OnEnable时调用
这种调用次序,可以保证Setting中所有的Elements和Behaviours都被绑定上了
如果你使用了FrameMediator的UsePool参数,或者自己的类似的Pool的实现,你应该在OnVisible中做UI的Refresh操作
如果没有使用池/Pool,直接在OnStart中Refresh就好了
绑定指定的C#端定义的MonoBehaviour以及GameObject自身
1 2 3 4 5 6 7 8 | -- Element支持的参数: -- Name GameObject的Path -- Alias 便利访问的名字 -- Count 一次绑定多个控件,从1开始 -- Type 需要的MonoBehaviour类型, 不指定则绑定GameObject -- Necessary 是否必须找到,Necessary = false 时可以不报错 -- Handles 回调函数 -- Hide 是否默认隐藏掉 |
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | Elements = { -- 一次注册多个控件,自动通过数字下标去查找 -- Item1, Item2, Item3 { Name = "Item" , Count = 3, Type = CS.UIButton, Handles = { onClick = "OnCloseButtonClick" , } }, }, |
提供了一个编辑器扩展,可以自动获取到GameObject的Path,获取到的Path保存在剪切板中,粘贴到Lua脚本中即可
绑定Lua端定义的LuaBehaviour
1 2 3 | -- Behaviour支持的参数: -- Name GameObject的Path -- Alias 便利访问的名字 |
示例:
1 2 3 4 5 6 | Behaviours = { { Name = "PlayerInfo" , }, }, |
Events
预定义,直接绑定的事件,通过FireEvent来触发LuaBehaviour中的成员函数
1 2 3 4 | Events = { [ "Event1" ] = "OnEvent1" }, |
预定的Timer绑定,回调也是成员函数
1 2 3 4 5 6 7 8 | Timers = { { Name = "SceneLoadedTimer" , Timer = Timer:Always(1), Handler = "CheckSceneLoaded" } }, |
提供便利地绑定方式,可以自动绑定C#端的static的event
1 | public static event Action TeammateNumChange; |
示例
1 2 3 4 | StaticActions = { BagModel.InfoRefreshEvent = "OnInfoRefreshEvent" } |
也是成员函数
C#中,我们可以使用Unity提供的Coroutine来方便的执行异步逻辑,Lua中也提供了一个Coroutine的机制,但是,要和Unity配合起来方便使用,还需要做些工作
1 2 3 4 5 6 7 8 9 10 | local co = self:StartCoroutine(function() local s = os.time() print( 'start to wait' ) yield_return(CS.UnityEngine.WaitForSeconds(3)) print( 'wait interval:' , os.time() - s) yield_return(www) print(www.bytes) end) |
1 2 3 4 5 6 7 8 | function LuaBehaviour:StartCoroutine(func) end function LuaBehaviour:StopCoroutine(co) end function LuaBehaviour:StopAllCoroutine() end |
实现:
自动封装掉Lua的coroutine.yield和coroutine.resume两个函数调用,IEnumerator的实际等待行为,在LuaOperation上执行
在Lua端和LuaOperation中,要维护一个完整的正在等待的东西的列表,这样才可以追踪执行状态,并顺利地执行Stop行为
在Prefab中,AddComponent, 添加LuaOperation这个组件即可
Class Path需要填写Lua脚本的具体路径,从LuaScripts目录开始,不需要填写LuaScripts
示例:
BehaviourManager是Lua端管理LuaBehaviour的管理器,所有的LuaBehaviour都是由它创建和销毁的
1 | __BehaviourManager:GetBehaviour(behaviour_go:GetInstanceID()) |
通过这个接口,可以获取到LuaBehaviour的实例,并直接调用它的接口等
__BehaviourManager是一个全局变量
behaviour_go是一个GameObject
通过这个接口,可以查找到挂在指定的GameObject上的LuaBehaviour的实例