• xlua游戏热更新(C#访问lua)


    xlua作为Unity资源热更新的重要解决方案api,在Tecent重多游戏中被采用,本文通过案例去讲解xlua代码结构层次。

    /*
     * Tencent is pleased to support the open source community by making xLua available.
     * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
     * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
     * http://opensource.org/licenses/MIT
     * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
    */
    
    using UnityEngine;
    using XLua;
    
    namespace XLuaTest
    {
        public class Helloworld : MonoBehaviour
        {
            // Use this for initialization
            void Start()
            {
                //创建xlua虚拟机
                LuaEnv luaenv = new LuaEnv();
                luaenv.DoString("print('hello xlua!')");
                luaenv.DoString("CS.UnityEngine.Debug.Log('hello world')");
                //释放资源
                luaenv.Dispose();
            }
    
            // Update is called once per frame
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    image.png

    加载lua文件

    Resources.Load(“xlua/xx.lua”) 加载

    创建Resources 目录下xx.lua.txt文件

    //创建xlua虚拟机【建议全局唯一】
    LuaEnv luaenv = new LuaEnv();
    //加载lua脚本资源
    TextAsset textAsset = Resources.Load<TextAsset>("xlua/hello.lua");
    luaenv.DoString(textAsset.ToString());
    
    • 1
    • 2
    • 3
    • 4
    • 5

    loader加载

    luaenv.DoString("require 'xlua/hello'"); //require + 'lua文件名称不加扩展名'
    //require 实际上是逐个查找loader文件 是否存在指定文件
    
    • 1
    • 2

    自定义loader

    挨个查找loader,若某个loader返回了字节数组,那么便不继续查找了

      //加载loader
                luaenv.AddLoader(Myloader);
                
                luaenv.DoString("require 'xlua/hello'");
                //挨个查找loader,若某个loader返回了字节数组,那么便不继续查找了
                //释放资源
                luaenv.Dispose();
    
    		/// 
            /// 自定义loader
            /// 
            /// 
            /// 
            private byte[] Myloader(ref string filePath)
            {
                print(filePath);
                string s = "print(123)";
                return Encoding.UTF8.GetBytes(s);
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    image.png

    构建Assets/StreamingAssets文件夹

      private byte[] Myloader(ref string filePath)
            {
                //print(filePath);
                string absPath = Application.streamingAssetsPath + "/" + filePath + ".lua.txt";
                return Encoding.UTF8.GetBytes(File.ReadAllText(absPath));
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    C#访问lua文件

    全局变量

    加载文件成功后,访问lua文件中的全局变量
    –number 可以对应int float double

               //通过luaenv 访问变量
                int integer_Lua = luaenv.Global.Get<int>("Integer");
                string name_Lua = luaenv.Global.Get<string>("Name");
                
                Debug.Log(integer_Lua + name_Lua);
    
    • 1
    • 2
    • 3
    • 4
    • 5

    //lua文件中
    
    person = {
        Name = "James",
        Sno = 23,
        
        eat = function()
            print("i'm eating!")
        end
        
    }
    //
    //C#
    class Person
            {
                public string _name;
                public int _sno;
            }
     Person luaPerson = luaenv.Global.Get<Person>("person");
                print(luaPerson._sno + ":" + luaPerson._name);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    接口

    IPerson luaPerson = luaenv.Global.Get<IPerson>("person");
     print(luaPerson.sno + ":" + luaPerson.name);
    
    
    [CSharpCallLua]
            interface IPerson
            {
                string name { get; set; }
                int sno { get; set; }
                void eat();
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    字典

    dic = {
        china = 1,
        america = 2,
        uk  = 3,
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
     //通过字典遍历
                Dictionary<string,int> dic =  luaenv.Global.Get<Dictionary<string, int>>("dic");
                foreach (var key in dic.Keys)
                {
                    print(key + ":" + dic[key]);
                }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    image.png

    列表

    list = {'sdahjk',12,123,'12'}
    
    • 1
      //通过list访问
                List<object> list =  luaenv.Global.Get<List<object>>("list");
                foreach (var target in list)
                {
                    print(target.ToString());
                }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    再将上述数据通过List读取一次
    image.png

    LuaTable

    LuaTable table = luaenv.Global.Get<LuaTable>("person");
                table.Get<string>("name");
    
    • 1
    • 2

    函数

     [CSharpCallLua]
            delegate int Add(int a, int b);
    
    //函数
                Add add = luaenv.Global.Get<Add>("add");
                print(add(3,5));
                add = null;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    lua多返回值通过,out 变量接受

    add = function(a,b)
        return a + b,a,b
    end
    
    • 1
    • 2
    • 3
     delegate int Add2(int a, int b, out int resa, out int resb);
    
    • 1

    使用LuaFunction (性能差)

    LuaFunction add = luaenv.Global.Get<LuaFunction>("add");
                object[] objects = add.Call(3, 5);
                print(objects[0]);
    
    • 1
    • 2
    • 3
  • 相关阅读:
    php——三篇夯实根基第一篇
    记一次fineBI的增量删除更新BUG
    【Verilog基础】【计算机体系架构】CPU发生中断要做哪些事?什么是中断向量表?(面试常问)
    2024年,在风云际会的编程世界里,窥探Java的前世今生,都说它穷途末路,我认为是柳暗花明!
    BMS中的绝缘电阻测量方法
    圆桌式开发是什么?如何实现?
    ##51单片机实验之简易验证码发生器
    改名Meta,杀死Oculus,Facebook是押注元宇宙还是“金蝉脱壳”?
    阿里巴巴全球数学竞赛
    有趣的 Go HttpClient 超时机制
  • 原文地址:https://blog.csdn.net/Mr_PEaSutBUtteR/article/details/134322871