ULUA的简洁用法(二)
来源:互联网 发布:手机处理数据软件 编辑:程序博客网 时间:2024/06/04 08:08
《ULUA的简洁用法(二)》
作者: 游蓝海
文章链接:http://blog.csdn.net/you_lan_hai/article/details/70554237
转载请注明出处
写上一篇文章《ULUA简洁用法》的时候,我对ULUA的认识还不是很深,经过一段时间的摸索后,我又整理了另一种更简单的方式,不需要修改ULUA源码,一个代码文件就能容纳下所有需要的内容。
1.原理
给GameObject添加上一个C#脚本组件作为中间层,在中间层上绑定上一个LUA脚本,将Unity的所有回调接口通过中间层传递到LUA。同时,LUA脚本也可以通过中间层操作GameObject。
2.实现中间层LuaBehaviour
中间层从MonoBehaviour
派生
添加public变量ScriptName
,用于在编辑器属性界面中输入Lua的模块名。当中间层Awake
的时候,根据ScriptName
加载Lua文件,并实例化出Lua类对象。
实例化LuaClient
LuaClient
在整个工程中应当只存在一个实例对象,我们可以把他绑定到一个不随关卡销毁的GameObject
对象上(调用了DontDestroyOnLoad
的GameObject
)。我们可以把实例化步骤也放到中间层脚本上,如此一来,只要场景中挂载了中间层脚本,LuaClient
也就会被自动初始化。
调用成员方法
对于只调用一次的Lua层方法,我们没必要在C#端去记录这个成员变量,比如Lua层面的Awake
和Start
方法。为了方便使用,我们在需要自动将self
作为第一个参数,传递给Lua方法。
object[] CallMethod(string func, params object[] args)
中间层关键代码
using UnityEngine;using System;using System.Collections;using LuaInterface;public class LuaBehaviour : MonoBehaviour{ public string ScriptName; protected LuaState luaState_; protected LuaTable self_; public LuaTable script { get{ return self_; } } protected void Awake() { // 这一步会触发LuaClient实例化。 luaState_ = GetMainLuaState(); if (ScriptName != null && ScriptName != null) { loadScript(ScriptName); //尝试调用脚本对象的Awake函数 CallMethod("Awake"); } } // 根据Lua模块名,加载Lua脚本 public bool loadScript(string scriptName) { if (scriptName == null) { Debug.LogError("The ScriptName must be set."); return false; } ScriptName = scriptName; // require lua文件,得到返回的类 LuaTable metatable = (LuaTable)require(ScriptName); if (metatable == null) { Debug.LogError("Invalid script file '" + ScriptName + "', metatable needed as a result."); return false; } // 从类中找到New函数 LuaFunction lnew = (LuaFunction)metatable["New"]; if (lnew == null) { Debug.LogError("Invalid metatable of script '" + ScriptName + "', function 'New' needed."); return false; } //执行New函数生成脚本对象 object[] results = lnew.Call(metatable); if (results == null || results.Length == 0) { Debug.LogError("Invalid 'New' method of script '" + ScriptName + "', a return value needed."); return false; } //存贮脚本对象 bindScript((LuaTable)results[0]); return true; } // 将一个已经存在的Lua对象绑定到当前组件中。 // 用于在脚本中动态创建对象,并手动挂接Lua对象。 public void bindScript(LuaTable script) { self_ = script; //给脚本对象设置上常用的属性 self_["transform"] = transform; self_["gameObject"] = gameObject; self_["behaviour"] = this; } // 调用Lua端的成员方法。会自动将self作为第一个参数,传递到Lua。 protected object[] CallMethod(string func, params object[] args) { if (self_ == null) { return null; } LuaFunction lfunc = (LuaFunction)self_[func]; if (lfunc == null) { return null; } //等价于lua语句: self:func(...) int oldTop = lfunc.BeginPCall(); lfunc.Push(self_); lfunc.PushArgs(args); lfunc.PCall(); object[] objs = luaState_.CheckObjects(oldTop); lfunc.EndPCall(); return objs; } // 自己实现一个lua require函数,可以得到require的返回值。 public object require(string fileName); // 这个函数是实例化LuaClient的入口。代码中获取LuaClient都调用这个静态函数。 public static LuaClient GetLuaClient() { if (LuaClient.Instance == null) { Debug.Log("LuaBehaviour create LuaClient"); GameObject obj = new GameObject(); obj.name = "LuaClient"; // 绑定LuaClient组件 obj.AddComponent<LuaClient>(); // 让obj常驻内存,不自动卸载 DontDestroyOnLoad(obj); } return LuaClient.Instance; } public static LuaState GetMainLuaState() { GetLuaClient(); return LuaClient.GetMainState(); }}
完整代码看这里
3.添加LUA脚本层
在Assets/Lua目录下新建LUA脚本Test.lua,核心代码如下:
--构造Test类local Test = {}Test.__index = Test --让实例对象的__get方法指向Test类--给Test类实例化一个对象function Test.New(cls) local self = {} setmetatable(self, cls) return selfend--Awake方法function Test:Awake() print("Test:Awake", self)end--将类Test返回。通过require函数的返回值就可以获取到此值了。return Test
4.测试
完整代码地址:https://github.com/youlanhai/tolua
下载代码后,用Unity打开Test2.unity
工程,执行一次菜单Lua/Generate All
。然后点击运行,会看到一个上下运动的立方体。
5.总结
相比于上一篇文章,这一次只手动实现了一个C#类,不需要额外的辅助代码,也不需要修改ToLua的源码。代码更容易集成到最新的ToLua源码中。
- ULUA的简洁用法(二)
- ULUA的简洁用法
- Java语言中Timer类的简洁用法(二)
- uLua使用总结(二)
- 神临的uLua学习(二)
- Java语言中Timer类的简洁用法(二)
- Java语言中Timer类的简洁用法(二)
- DataBinding的用法(简洁易懂)
- 一个简洁的分页实现(二)
- eventbus的使用(二)简洁易懂
- ulua对于unity的例子的理解 二
- Java语言中Timer类的简洁用法(一)
- 超简洁的下拉刷新(二)用srcoller实现
- Nmap比较简洁明了的用法
- ulua(一)上手
- uLua
- ulua
- ulua
- 修改页面滚动条样式CSS代码!(待修改兼容性)
- 分书问题(搜索)
- LintCode 38 搜索二维矩阵 II
- stmp协议以及邮件的发送
- 1649
- ULUA的简洁用法(二)
- Lucene教程--Analyzer分析器详解
- js判断鼠标移入的方向并触发事件
- Golang 学习之路四:类型
- 转:kafka数据可靠性深度解读
- InitInstance中创建CWnd派生的窗口对象,内存泄漏
- 第十周:( Sicily1091) Maximum Sum(c++)
- 开启子线程的方法
- java语言基础(42)——package关键字概述和使用