找回密码
 立即注册
查看: 300|回复: 0

ToLua使用笔记(中)

[复制链接]
发表于 2021-10-16 07:33 | 显示全部楼层 |阅读模式
继续看例子
目录
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.先运行编辑器脚本,看到在StreamingAssetsWin下是否生成了多个.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

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-11-24 20:45 , Processed in 0.087823 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表