Unity XLua 相关
转自:https://www.cnblogs.com/coderJiebao/p/unity3d23.html
1. Helloworld
1 using UnityEngine;2 using XLua;3 4 public class Helloworld : MonoBehaviour {5 // Use this for initialization6 void Start () {7 LuaEnv luaenv = new LuaEnv();8 // 执行代码块,输出 hello world9 luaenv.DoString("CS.UnityEngine.Debug.Log('hello world')"); 10 // 释放资源 11 luaenv.Dispose(); 12 } 13 }
该案例实现了在 Unity 控制台输出 hello world。
2. U3DScripting
lua 代码如下:
1 local speed = 102 local lightCpnt = nil3 4 function start()5 print("lua start...")6 -- 访问环境变量7 print("injected object", lightObject)8 -- 查找 Light 组件9 lightCpnt= lightObject:GetComponent(typeof(CS.UnityEngine.Light)) 10 end 11 12 function update() 13 local r = CS.UnityEngine.Vector3.up * CS.UnityEngine.Time.deltaTime * speed 14 -- 绕y轴旋转 15 self.transform:Rotate(r) 16 -- 修改光线颜色 17 lightCpnt.color = CS.UnityEngine.Color(CS.UnityEngine.Mathf.Sin(CS.UnityEngine.Time.time) / 2 + 0.5, 0, 0, 1) 18 end 19 20 function ondestroy() 21 print("lua destroy") 22 end
注意,如果要插入中文注释,需要将 txt 编码格式改为 UTF-8,否则无法执行。
C# 代码如下:
1 using UnityEngine;2 using XLua;3 using System;4 5 [System.Serializable]6 public class Injection7 {8 public string name;9 public GameObject value; 10 } 11 12 [LuaCallCSharp] 13 public class LuaBehaviour : MonoBehaviour { 14 public TextAsset luaScript; // lua脚本文件 15 public Injection[] injections; // 需要注入到环境变量的物体 16 17 internal static LuaEnv luaEnv = new LuaEnv(); //all lua behaviour shared one luaenv only! 18 internal static float lastGCTime = 0; 19 internal const float GCInterval = 1;//1 second 20 21 private Action luaStart; 22 private Action luaUpdate; 23 private Action luaOnDestroy; 24 25 private LuaTable scriptEnv; 26 27 void Awake() 28 { 29 scriptEnv = luaEnv.NewTable(); 30 31 LuaTable meta = luaEnv.NewTable(); 32 meta.Set("__index", luaEnv.Global); 33 scriptEnv.SetMetaTable(meta); 34 meta.Dispose(); 35 36 // 配置环境变量,在lua代码里能直接调用 37 scriptEnv.Set("self", this); 38 foreach (var injection in injections) 39 { 40 scriptEnv.Set(injection.name, injection.value); 41 } 42 // 参数1:Lua代码的字符串 43 // 参数2:发生error时的debug显示信息时使用 44 // 参数3:代码块的环境变量 45 luaEnv.DoString(luaScript.text, "LuaBehaviour", scriptEnv); 46 47 // 访问函数 48 Action luaAwake = scriptEnv.Get<Action>("awake"); 49 scriptEnv.Get("start", out luaStart); 50 scriptEnv.Get("update", out luaUpdate); 51 scriptEnv.Get("ondestroy", out luaOnDestroy); 52 53 // 执行事件 54 if (luaAwake != null) 55 { 56 luaAwake(); 57 } 58 } 59 60 // Use this for initialization 61 void Start () 62 { 63 if (luaStart != null) 64 { 65 luaStart(); 66 } 67 } 68 69 // Update is called once per frame 70 void Update () 71 { 72 if (luaUpdate != null) 73 { 74 luaUpdate(); 75 } 76 if (Time.time - LuaBehaviour.lastGCTime > GCInterval) 77 { 78 // 清楚lua未手动释放的LuaBase对象,需定期调用,这里是1s调用一次 79 luaEnv.Tick(); 80 LuaBehaviour.lastGCTime = Time.time; 81 } 82 } 83 84 void OnDestroy() 85 { 86 if (luaOnDestroy != null) 87 { 88 luaOnDestroy(); 89 } 90 luaOnDestroy = null; 91 luaUpdate = null; 92 luaStart = null; 93 scriptEnv.Dispose(); 94 injections = null; 95 } 96 }
该场景实现了 lua 代码控制 U3D 物体,以实现物体的旋转和颜色变化。
三、UIEvent
lua 代码如下:
1 function start() 2 print("lua start...") 3 -- 给button添加事件 4 -- 点击输出 input 输入内容 5 self:GetComponent("Button").onClick:AddListener(function() 6 print("clicked, you input is '" ..input:GetComponent("InputField").text .."'") 7 end) 8 end
该场景实现了 lua 代码为 button 添加事件响应函数,以实现点击按钮输出输入框内容。
注意,lua 中 . 和 : 的区别:
- 定义的时候:Class:test() 与 Class.test(self) 是等价的
调用的时候:
object
:test() 与
object
.test(
object
) 等价
在这里,调用类的方法使用 :,调用属性用 . 。
C# 代码还是上一场景的 LuaBehaviour.cs。
四、InvokeLua
C# 代码如下:
1 using UnityEngine;2 using XLua;3 4 public class InvokeLua : MonoBehaviour5 {6 [CSharpCallLua]7 public interface ICalc8 {9 int Add(int a, int b); 10 int Mult { get; set; } 11 } 12 13 [CSharpCallLua] 14 public delegate ICalc CalcNew(int mult, params string[] args); 15 16 private string script = @" 17 local calc_mt = { 18 __index = { 19 Add = function(self, a, b) 20 return (a + b) * self.Mult 21 end 22 } 23 } 24 25 Calc = { 26 -- 多参数函数 27 New = function (mult, ...) 28 print(...) 29 return setmetatable({Mult = mult}, calc_mt) 30 end 31 } 32 "; 33 // Use this for initialization 34 void Start() 35 { 36 LuaEnv luaenv = new LuaEnv(); 37 Test(luaenv);//调用了带可变参数的delegate,函数结束都不会释放delegate,即使置空并调用GC 38 luaenv.Dispose(); 39 } 40 41 void Test(LuaEnv luaenv) 42 { 43 luaenv.DoString(script); 44 // 访问 lua 函数 45 CalcNew calc_new = luaenv.Global.GetInPath<CalcNew>("Calc.New"); 46 ICalc calc = calc_new(10, "hi", "john"); //constructor 47 Debug.Log("sum(*10) =" + calc.Add(1, 2)); // (1+2)*10 48 calc.Mult = 100; 49 Debug.Log("sum(*100)=" + calc.Add(1, 2)); // (1+2)*100 50 } 51 }
该场景实现了 C# 调用 lua 代码的函数,table。注意要加上 [CSharpCallLua] 。
五、NoGc
看不懂。
六、Coroutine
总共有四个代码文件,关键代码如下。
1. CoroutineTest.cs
1 LuaEnv luaenv = null; 2 // Use this for initialization 3 void Start() 4 { 5 luaenv = new LuaEnv(); 6 // 执行 coruntine_test 7 luaenv.DoString("require 'coruntine_test'"); 8 }
2. coruntine_test.lua
1 local util = require 'xlua.util'2 3 local yield_return = (require 'cs_coroutine').yield_return4 5 local co = coroutine.create(function()6 print('coroutine start!')7 local s = os.time()8 -- 协程等待3秒9 yield_return(CS.UnityEngine.WaitForSeconds(3)) 10 print('wait interval:', os.time() - s) 11 12 local www = CS.UnityEngine.WWW('http://www.cnblogs.com/coderJiebao/p/unity3d22.html') 13 -- 协程加载网页 14 yield_return(www) 15 if not www.error then 16 print(www.bytes) 17 else 18 print('error:', www.error) 19 end 20 end) 21 22 assert(coroutine.resume(co))
3. cs_coroutine.lua
1 local util = require 'xlua.util'2 3 -- 新建物体4 local gameobject = CS.UnityEngine.GameObject('Coroutine_Runner')5 -- 设置不自动销毁6 CS.UnityEngine.Object.DontDestroyOnLoad(gameobject)7 -- 添加组件8 local cs_coroutine_runner = gameobject:AddComponent(typeof(CS.Coroutine_Runner))9 10 local function async_yield_return(to_yield, cb) 11 cs_coroutine_runner:YieldAndCallback(to_yield, cb) -- 调用 C# 函数 12 end 13 14 return { 15 yield_return = util.async_to_sync(async_yield_return) 16 }
4. Coroutine_Runner.cs
1 [LuaCallCSharp]2 public class Coroutine_Runner : MonoBehaviour3 {4 public void YieldAndCallback(object to_yield, Action callback)5 {6 // 开启协程,回调callback7 StartCoroutine(CoBody(to_yield, callback));8 }9 10 private IEnumerator CoBody(object to_yield, Action callback) 11 { 12 if (to_yield is IEnumerator) 13 yield return StartCoroutine((IEnumerator)to_yield); 14 else 15 yield return to_yield; 16 callback(); 17 } 18 }
该场景实现了协程等待3s和加载网页的功能。
调用流程为:CoroutineTest.Start -> coruntine_test(创建协程,调用 yield_return 方法)-> cs+coroutine.async_yield_return -> Coroutine_Runner.YieldAndCallback。
七、AsyncTest
继续看不懂,后期补上。
八、Hotfix
1. 使用方式
(1) 在 github 上下载 xlua 源码后,将 Asserts 文件夹内的文件以及 Tools 文件夹直接拖到工程,这时候会报错,删除 Tools 文件夹下的 System.dll 和 System.core.dll 即可。
(2) 添加 HOTFIX_ENABLE 和 INJECT_WITHOUT_TOOL 两个宏(在 File->Build Setting->Player Setting->Scripting Define Symbols)
(3) 执行XLua/Generate Code菜单
(4) 编写代码,注意在需要热更新的地方添加[Hotfix]标签
(5) 注入,构建手机包这个步骤会在构建时自动进行,编辑器下开发补丁需要手动执行"XLua/Hotfix Inject In Editor"菜单。注入成功会打印“hotfix inject finish!”或者“had injected!”。
2. 常用函数
xlua.hotfix(class, [method_name], fix)
- 描述 : 注入lua补丁
- class : C#类,两种表示方法,CS.Namespace.TypeName或者字符串方式"Namespace.TypeName",字符串格式和C#的Type.GetType要求一致,如果是内嵌类型(Nested Type)是非Public类型的话,只能用字符串方式表示"Namespace.TypeName+NestedTypeName";
- method_name : 方法名,可选;
- fix : 如果传了method_name,fix将会是一个function,否则通过table提供一组函数。table的组织按key是method_name,value是function的方式。
xlua.private_accessible(class)
- 描述 : 让一个类的私有字段,属性,方法等可用
- class : 同xlua.hotfix的class参数
util.hotfix_ex(class, method_name, fix)
- 描述 : xlua.hotfix的增强版本,可以在fix函数里头执行原来的函数,缺点是fix的执行会略慢。
- method_name : 方法名;
- fix : 用来替换C#方法的lua function。
base(csobj)
- 描述:子类 override 函数通过 base 调用父类实现
- csobj:对象
- 返回值:新对象
3. 打补丁
xlua 可以用 lua 函数替换 C# 的构造函数,函数,属性,事件的替换。
(1) 函数
可以指定一个函数,也可以传递由多个函数组成的 table。
1 -- 注入lua补丁,替换HotfixCalc.Add 2 xlua.hotfix(CS.HotfixCalc, 'Add', function(self, a, b) 3 -- 原来为 a-b 4 return a + b 5 end)
1 -- 通过table提供一组函数2 -- table的组织按key是methodname,value是function的方式3 xlua.hotfix(CS.HotfixCalc, {4 Test1 = function(self)5 print('Test1', self)6 return 17 end;8 Test2 = function(self, a, b)9 print('Test2', self, a, b) 10 return a + 10, 1024, b 11 end; 12 -- static 函数不需要加self 13 Test3 = function(a) 14 print(a) 15 return 10 16 end; 17 Test4 = function(a) 18 print(a) 19 end; 20 -- 多参数 21 Test5 = function(self, a, ...) 22 print('Test4', self, a, ...) 23 end 24 })
(2) 构造函数
构造函数对应的 method_name 是 ".ctor",和普通函数不一样的是,构造函数的热补丁并不是替换,而是执行原有逻辑后调用 lua。
1 -- 构造函数 2 ['.ctor'] = function(csobj) 3 return {evt = {}, start = 0} 4 end;
(3) 属性
每一个属性都对应一个get,set函数。
1 -- 属性AProp的赋值和取值 2 set_AProp = function(self, v) 3 print('set_AProp', v) 4 self.AProp = v 5 end; 6 get_AProp = function(self) 7 return self.AProp 8 end;
(4) [] 操作符
赋值对应 set_Item,取值对应 set_Item。
1 -- []操作符,赋值和取值 2 get_Item = function(self, k) 3 print('get_Item', k) 4 return 1024 5 end; 6 set_Item = function(self, k, v) 7 print('set_Item', k, v) 8 end;
对于其他操作符,C#的操作符都有一套内部表示,比如+号的操作符函数名是op_Addition。
(5) 事件
+= 操作符是 add_...,-= 操作符是 remove_... ,函数第一个参数是自身,第二个参数是操作符右边的 delegate。
1 -- 事件AEvent +=2 add_AEvent = function(self, cb)3 print('add_AEvent', cb)4 table.insert(self.evt, cb)5 end;6 -- 事件AEvent -=7 remove_AEvent = function(self, cb)8 print('remove_AEvent', cb)9 for i, v in ipairs(self.evt) do 10 if v == cb then 11 table.remove(self.evt, i) 12 break 13 end 14 end 15 end;
(6) 析构函数
函数名是 Finalize,传一个 self 参数。和普通函数不一样的是,析构函数的热补丁并不是替换,而是开头调用 lua 函数后继续原有逻辑。
1 -- 析构函数 2 Finalize = function(self) 3 print('Finalize', self) 4 end
(7) 泛化类型
每个泛化类型都是一个独立的类型,需要对实例化后的类型分别打补丁。
1 xlua.hotfix(CS['GenericClass`1[System.Double]'], {2 ['.ctor'] = function(obj, a)3 print('GenericClass<double>', obj, a)4 end;5 Func1 = function(obj)6 print('GenericClass<double>.Func1', obj)7 end;8 Func2 = function(obj)9 print('GenericClass<double>.Func2', obj) 10 return 1314 11 end 12 })
(8) 子类调用父类
1 -- 子类调用父类的方法 2 xlua.hotfix(CS.BaseTest, 'Foo', function(self, p) 3 print('BaseTest', p) 4 base(self):Foo(p) 5 end) 6 xlua.hotfix(CS.BaseTest, 'ToString', function(self) 7 return '>>>' .. base(self):ToString() 8 end)
Unity XLua 相关相关推荐
- Unity 面试题汇总(三)Unity 基础相关
Unity 面试题汇总(三)Unity 基础相关 目录 Unity 面试题汇总(三)Unity 基础相关 0.FSM(状态机).HFSM(分层状态机).BT(行为树)的区别 1.什么是协同程序? 2. ...
- Unity Xlua之Hotfix热补丁 (一)
Unity Xlua之Hotfix热补丁 (一) 一.第一个热补丁 想要打热补丁的类前需要加上[Hotfix]特性 第一次打热补丁需要加上宏HOTFIX_ENABLE 点击生成代码 点击注入热补丁 例 ...
- Unity Xlua 之 C#调用Lua(一)
Unity Xlua 之 C#调用Lua(一) 一.Lua解析器(LuaEnv) 执行Lua代码,加载Lua文件执行 public class Lesson01_LuaEnv : MonoBehavi ...
- Unity Xlua 之 Lua调用C#(三)
Unity Xlua 之 Lua调用C#(三) 一.Lua使用C#委托和事件 public class Lesson7 {public UnityAction action;public event ...
- unity fixedupdate_unity相关
会频繁更新 主要给自己看 性能优化总结:成本和分析 工具:Memory Profiler/Unity Editor Profiler/Frame Debugger/RenderDoc/ VS / AD ...
- YDLIDAR G4雷达的unity使用相关+北阳雷达
业务需求用到了G4激光雷达,需要对接雷达的sdk,最方便的是直接找unitypackage包来用,网上要么收费要么没用.所以还是自己对接吧 准备 先找相关文档,官网,sdk样例等.官网里各种文档和sd ...
- unity android输入法,Unity输入法相关(IME)
在UI上的InputField中, 中文输入法的备选框不会跟随在光标旁边, 造成输入不方便. 看到有一个相似的, 可是是WebGL的 : https://blog.csdn.net/Rowley123 ...
- Unity XLua 官方教程学习
一.Lua 文件加载 1. 执行字符串 using UnityEngine; using XLua;public class ByString : MonoBehaviour {XLua.LuaEnv ...
- Unity+XLua+阿里云热更代码
Unity+AssetsBundel+XLua+阿里云 Unity热更新的步骤:AssetsBundle打包好资源--上传到服务器--运行项目--检测是否需要更新--1.需要更新2.不需要更新--1. ...
最新文章
- Python数据挖掘:数据探索,数据清洗,异常值处理
- 大雁塔为什么七层_西安旅游的打卡景点,大雁塔是干嘛的?怎么来的?
- 如何在Ubuntu上使用ssh-add永久添加私钥? [关闭]
- java实现数字(摘要)签名,生成签名文件,防止文件被人篡改内容,分析和实现
- mysql如何开启远程链接_mysql怎么开启远程连接
- CVPR 2021 速览 | 旷视研究院入选学术成果盘点
- PowerManager.WakeLock使用(屏幕恒亮)
- FastNetMon 使用笔记
- 对于利用blender获取谷歌地图3D模型的补充
- jdk目录详解及其使用方法
- 中学生科技节活动计算机,2018年学校科技节活动
- hdoj 瞬间移动 5698(逆元)
- 绝对不可错过的圣诞节H5游戏
- STM32通过串口控制LED闪烁或者呼吸效果
- 同样取整,TRUNC函数与INT函数的有什么区别?
- 【数据恢复】【傲梅分区助手】
- [乡土民间故事_徐苟三传奇]第十六回_差狗子认输吃大粪
- 均州古城(走遍中国08.10.27)
- Android股票查询系统计算机程序
- 误删回收站文件怎么恢复?小技巧来啦!
热门文章
- 菜菜学paddle第六篇:利用LeNet卷积神经网络识别手写数字
- 刷步数作弊成了朋友圈必备技能
- 文件末尾eof_什么是EOF(文件末尾)? PHP,C ++,C,Python,Java的示例
- 前端开发是做什么的?工作职责有哪些?
- 各保险公司所使用的业务系统
- OpenCV视频质量诊断----视频遮挡诊断
- Flask、sqlite3、pipenv实现用户注册和登录(HandBook,菜鸟都会的)
- 现在为什么很多企业都在使用终端安全管理系统?有什么好处...
- 团队公司地点拍照打卡签到活动小程序 document.forms[“myForm“][“fname“]
- Qt5 学习之路及嵌入式开发教程21:QML基础