|
继续看例子
目录
13.CustomLoader:自定义加载器Loader的使用
14.Out:out修饰输入参数
15.ProtoBuffer:编码、解码protobuff消息
16.Int64:在lua中使用int64类
17.Inherit:在Lua中扩展C#对象
18.Bundle:用编辑器脚本将lua脚本打包成assetbundle以及加载使用
19.cjson:待看
20.utf8:lua中,利用utf8类对中文、日文等东方文字进行操作
21.String:在Lua中,对C#String类的操作
?
22.Reflection:待看, lua中的反射
23.List:操作C#List类型
24.Struct:待看
13.CustomLoader:自定义加载器Loader的使用
【需要修改:在TestCustomLoader中加上一个方法
void Start()
{
StartMain();
}
】
1.关键表达式:new LuaResLoader();
2.通过自定义的加载器(LuaResLoader),可以使用特定的方式(LuaResLoader.ReadResourceFile)加载lua文件
这个例子中的TestLoader.lua就是通过 Resource.Load来加载的。具体请看LuaResLoader.cs。
所以尽管没有加入搜索的目标路径(像例子02那样),也能加载 TestLoader.lua ,只要在Resources文件夹下即可。
// LuaClient 继承自 MonoBehavior, 有 Awake Start 和 Update 等函数public class TestCustomLoader : LuaClient { string tips = "Test custom loader"; // 定义了一个新的加载器 LuaResLoader ,其继承自 LuaFileUtils, 重写了 ReadFile 函数。 protected override LuaFileUtils InitLoader() { return new LuaResLoader(); } protected override void CallMain() { LuaFunction func = luaState.GetFunction("Test"); func.Call(); func.Dispose(); } protected override void StartMain() { // 最终会调用 LuaFileUtils.Instance.ReadFile(fileName); 调用的是 LuaResLoader.ReadFile; // 即会通过 Resource.Load 来调用这个 lua 脚本。 luaState.DoFile("TestLoader.lua"); CallMain(); } // new 关键字 重写基类的方法 new void Awake() {#if UNITY_5 || UNITY_2017 || UNITY_2018 Application.logMessageReceived += Logger;#else Application.RegisterLogCallback(Logger);#endif base.Awake(); } void Start() { StartMain(); } 14.Out:out修饰输入参数
C#中碰撞检测代码:
void Update() { if (Input.GetMouseButtonDown(0)) { Camera camera = Camera.main; Ray ray = camera.ScreenPointToRay(Input.mousePosition); RaycastHit hit; bool flag = Physics.Raycast(ray, out hit, 5000, 1 << LayerMask.NameToLayer("Default")); if (flag) { Debugger.Log("pick from c#, point: [{0}, {1}, {2}]", hit.point.x, hit.point.y, hit.point.z); } func.BeginPCall(); func.Push(ray); func.PCall(); func.EndPCall(); } state.CheckTop(); state.Collect(); }lua中碰撞检测代码:
string script = @" -- 如果不加下面这句话: 会提示warning register PreLoad type UnityEngine.BoxCollider to lua 。疑问 local box = UnityEngine.BoxCollider function TestPick(ray) local _layer = 2 ^ LayerMask.NameToLayer('Default') local time = os.clock() local flag, hit = UnityEngine.Physics.Raycast(ray, nil, 5000, _layer) --local flag, hit = UnityEngine.Physics.Raycast(ray, RaycastHit.out, 5000, _layer) if flag then print('pick from lua, point: '..tostring(hit.point)) end end ";对比Lua中和C#中实现碰撞检的输出,结果一致:
具体 lua中调用 Raycast 函数的时候在C#段如何调用的:
UnityEngine_PhysicsWrap.Raycast.try.if 中 count =4 输入参数为4 的时候 (例子09)
15.ProtoBuffer:编码、解码protobuff消息
这里涉及到protobuf 的应用,没有接触的可以先看一下这篇文章。
两个原始proto文件为:
common.proto
person.proto
使用了 protoc-gen-lua 工具编译lua以后的文件,并且放入unity的Resources文件夹下中:
person_pb.lua.bytes
common_pb.lua.bytes
然后在C#中的执行lua脚本内容如下:
private string script = @" -- 引入两个模块 也就是加上 由proto文件编译的lua文件 local common_pb = require 'Protol.common_pb' local person_pb = require 'Protol.person_pb' -- C#端 再调用的 Decoder 函数 function Decoder() local msg = person_pb.Person() -- data: 一个LuaByteBuffer特性的byte[]类型变量 为了传递c#与lua间的序列化后的数据 -- 从字符串解析 msg:ParseFromString(TestProtol.data) --tostring 不会打印默认值 print('person_pb decoder:\n '..tostring(msg)..'\nage: '..msg.age..'\nemail: '..msg.email) end -- C#端 先调用的 Encoder 函数 function Encoder() -- 直接看 person.proto 进行赋值就行了 不要看 person_pb.lua -- 对 required 字段必须赋值 local msg = person_pb.Person() msg.header.cmd = 10010 msg.header.seq = 1 msg.id = '1223372036854775807' msg.name = 'foo' -- 对 option 字段可以选择性赋值 -- 对 repeat 字段:数组添加 msg.array:append(1) msg.array:append(2) --extensions 添加 local phone = msg.Extensions[person_pb.Phone.phones]:add() phone.num = '13788888888' phone.type = person_pb.Phone.MOBILE -- 调用序列化为字符串 local pb_data = msg:SerializeToString() -- 写入静态类TestProtol中 TestProtol.data = pb_data end ";输出为:
其中C#中的TestProtol类暴露给Lua使用:
public static class TestProtol{ [LuaByteBufferAttribute] public static byte[] data; } 16.Int64:在lua中使用int64类
lua5.1.x都是不支持int64和uint64的。Lua5.3已经支持了这两种数据类型
旧版本中使用tolua库,就可以使用int64和uint64。
例子中调用的方法:
int64.tonum2(x) tonum2会返回两个数,第二个数高位是右移32位的值,第一个数低位是剩下的值(&0xFFFFFFFF)。
int64.new(low,high) 创建一个int64的使用高位+低位的方式
int64.new(x) 创建一个int64
int64.equals(x,y)
string script = @" function TestInt64(x) x = 789 + x assert(tostring(x) == '9223372036854775807') local low, high = int64.tonum2(x) print('x value is: '..tostring(x)..' low is: '.. low .. ' high is: '..high.. ' type is: '.. tolua.typename(x)) // y 和 z 都是 userdata类型 // 可以像正常的数一样加减乘除、取余、取相反数、乘方等 local y = int64.new(1,2) local z = int64.new(1,2) if y == z then print('int64 equals is ok, value: '..int64.tostring(y)) end x = int64.new(123) if int64.equals(x, 123) then print('int64 equals to number ok') else print('int64 equals to number failed') end x = int64.new('78962871035984074') print('int64 is: '..tostring(x)) local str = tostring(int64.new(3605690779, 30459971)) local n2 = int64.new(str) local l, h = int64.tonum2(n2) print(str..':'..tostring(n2)..' low:'..l..' high:'..h) print('----------------------------uint64-----------------------------') x = uint64.new('18446744073709551615') print('uint64 max is: '..tostring(x)) l, h = uint64.tonum2(x) str = tostring(uint64.new(l, h)) print(str..':'..tostring(x)..' low:'..l..' high:'..h) return y end "; 17.Inherit:在Lua中扩展C#对象
主要接口:
tolua.setpeerr(csobj, peer) | 设置替身
csobj: C#对象在lua中对应的userdata
peer: 一个lua table
https://www.cnblogs.com/xsxjin/p/6854584.html
| tolua.getpeer | 获取替身 | settab= tolua.initset(tbl) | 初始化tbl的set“访问器”,settab是一个table类型。
settab.XXX = function(self)
……
end
| gettab = tolua.initget(tbl) | 初始化tbl的get“访问器”,gettab 是一个table类型。
gettab .XXX = function(self, v)
……
end
| 例子中扩展了 Transform类,重写了一些方法,扩展了一个字段。
在没有扩展之前,当我们访问或设置userdata不存在的成员的时候,程序就会出错,但是在扩展之后,我们便可以扩展对象的成员。
private string script = @" LuaTransform = { } function LuaTransform.Extend(u) print(type(u)) local t = {} tolua.setpeer(u, t) t.__index = t print(type(u)) local get = tolua.initget(t) local set = tolua.initset(t) -- u.base是什么 local _base = u.base local _position = u.position --重写同名属性获取 get.position = function(self) return _position end --重写同名属性设置 set.position = function(self, v) if _position ~= v then _position = v _base.position = v end end --重写同名函数 多打印一句话 function t:Translate(...) print('child Translate') _base:Translate(...) end return u end function Test(node) -- 返回扩展过的,有替身的 local transform = LuaTransform.Extend(node) -- 使用重写的set get函数 ,记录所需时间 与C#中对比 local t = os.clock() for i = 1, 200000 do transform.position = transform.position end print('LuaTransform get set cost', os.clock() - t) -- 调用重写方法 transform:Translate(1,1,1) -- 调用原有方法 local child = transform:Find('child') print('child is: ', tostring(child)) -- 支持go.transform == transform 这样的比较 if child.parent == transform then print('LuaTransform compare to userdata transform is ok') end -- 扩展了字段 没有报错 transform.xyz = 456 print('extern field xyz is: '.. transform.xyz) end "; 18.Bundle:用编辑器脚本将lua脚本打包成assetbundle以及加载使用
对于assetbundle没有接触的可以看下这篇。
1.先运行编辑器脚本,看到在StreamingAssets的Win下是否生成了多个.unity3d的assetbundle包。
( 具体实现查看 BuildNotJitBundles 函数)
2.代码中演示了 使用协程 先将AB资源包加载内存完毕,然后再通过AB包中加载相应的lua脚本的过程。
(把断点打入 LuaInterface.LuaFileUtils.ReadZipFile 函数,查看具体如何查找和加载)
(可以测试下原始lua脚本删除也是正常运行的 Assets\LuaFramework\ToLua)
19.cjson:待看
通过cjson组件读取json文件,等有遇到再看
20.utf8:lua中,利用utf8类对中文、日文等东方文字进行操作
string script =@" local utf8 = utf8 function Test() local l1 = utf8.len('你好')--2 local l2 = utf8.len('こんにちは')--5 print('chinese string len is: '..l1..' japanese sting len: '..l2) local s = '遍历字符串' for i in utf8.byte_indices(s) do local next = utf8.next(s, i) print(s:sub(i, next and next -1)) end local s1 = '天下风云出我辈' print('风云 count is: '..utf8.count(s1, '风云')) s1 = s1:gsub('风云', '風雲') local function replace(s, i, j, repl_char) if s:sub(i, j) == '辈' then return repl_char end end print(utf8.replace(s1, replace, '輩')) end"; 21.String:在Lua中,对C#String类的操作
string script =@" function Test() local str = System.String.New('男儿当自强') local index = str:IndexOfAny('儿自') -- C# String类型 在lua中是 userdata类型 print('and index is: '..index) print(str) print('str type is: '..type(str)..'\n') -- C#函数ToCharArray 返回char[] userdata类型 local buffer = str:ToCharArray() print(buffer) print('buffer type is: '..type(buffer)..' buffer[0] is ' .. buffer[0]..'\n') -- str 转化为 lua基本类型 string local luastr = tolua.tolstring(str) print('lua string is: '..luastr..'type is: '..type(luastr)..'\n') -- buffer 也可以转化为 lua基本类型 string luastr = tolua.tolstring(buffer) print('lua string is: '..luastr..'\n') end";
22.Reflection:待看, lua中的反射
23.List:操作C#List<T>类型
在lua中对C#List<int> 的操作。
//需要导出委托类型如下:
//System.Predicate<int>
//System.Action<int>
//System.Comparison<int>
24.Struct:待看
总结一下最重要的在lua中用C#类
1. 准备工作,使用插件自带的Wrap功能生成 lua需要调用的 C#类
(通过 配置 CustomSetting.cs, 运行编辑器脚本)
2. 同时 Bind 函数的更新(会调用 Wrap.Register)
3. 在lua中 调用其中的静态方法和成员变量的时候都是 类.成员 或 类.静态方法,而调用类中的非静态私有成员方法时则是需要这样写:类:方法,
http://doc.ulua.org/default.asp?cateID=3 |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|