• xLua热更新插件


    一.xLua插件下载安装

    1.从GitHub上搜索并下载插件

     2.将文件复制到unity中

     

     3.检查是否有错误

    二.在unity中调用lua

    1.简单调用

    在c#脚本中使用LuaEnv类可以运行lua,建议LuaEnv实例全局唯一。

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    //引入命名空间
    using XLua;
    
    public class HelloLua01 : MonoBehaviour
    {
        //声明luaenv变量
        private LuaEnv luaenv;
    
        void Start()
        {
            //实例化luaenv变量
            luaenv = new LuaEnv();
            //调用DoString方法执行lua代码
            luaenv.DoString("print('hello world!')");
        }
    
        private void OnDestroy()
        {
            //释放luaenv
            luaenv.Dispose();
        }
    
    }

     2.lua文件的读取执行

    using UnityEngine;
    //引入命名空间
    using XLua;
    
    public class HelloLua : MonoBehaviour
    {
        private LuaEnv luaenv;
    
        void Start()
        {
            luaenv = new LuaEnv();
            //将lua代码文件放在Resources文件夹下,并添加后缀.txt
            //通过Resources.Load方法读取这个文件,声明类型为TextAsset,这样读取的过程中就会自动添加后缀.txt
            //读取到文件的内容后转化为byte数组(使用tostring方法或者text方法转化为字符串或文本也都可以),并交给DoString方法执行这段代码
            luaenv.DoString(Resources.Load<TextAsset>("helloLua.lua").bytes);
        }
    
        private void OnDestroy()
        {
            luaenv.Dispose();
        }
    
    }

    using UnityEngine;
    //引入命名空间
    using XLua;
    
    public class HelloLua : MonoBehaviour
    {
        private LuaEnv luaenv;
    
        void Start()
        {
            luaenv = new LuaEnv();
            //使用系统内置的方法加载文件并执行代码,文件名是helloLua.lua.txt
            luaenv.DoString("require 'helloLua'");
        }
    
        private void OnDestroy()
        {
            luaenv.Dispose();
        }
    
    }

     3.自定义Loader:针对文件后缀不是.lua.txt的类型

    public class HelloLua : MonoBehaviour
    {
        private LuaEnv luaenv;
    
        void Start()
        {
            luaenv = new LuaEnv();
    
            //通过AddLoader方法自定义Loader程序,实际上是将自定义的Loader方法添加到一个委托中
            luaenv.AddLoader(MyLoader);
            //执行DoString方法,会首先调用自定义的Loader方法,如果返回值为空,再调用系统定义的Loader方法
            luaenv.DoString("require 'helloLua'");
        }
    
        //自定义的Loader方法,这个方法返回值必须是byte数组,参数是ref的string类型,传入文件地址
        private byte[] MyLoader(ref string filePath)
        {
            print(filePath);
            return null;
        }
    
        private void OnDestroy()
        {
            luaenv.Dispose();
        }
    
    }

    public class HelloLua : MonoBehaviour
    {
        private LuaEnv luaenv;
    
        void Start()
        {
            luaenv = new LuaEnv();
    
            luaenv.AddLoader(MyLoader);
            luaenv.DoString("require 'helloLua'");
        }
    
        private byte[] MyLoader(ref string filePath)
        {
            //打印文字说明这个loader函数被调用
            print("调用了自定义的loader");
            //将lua文件放入streaMingAssetsPath文件夹内,拼接好文件的完整绝对路径
            string path = Application.streamingAssetsPath + "/" + filePath + ".lua.txt";
            //读取文件,获得byte数组并返回
            return System.Text.Encoding.UTF8.GetBytes(File.ReadAllText(path));
        }
    
        private void OnDestroy()
        {
            luaenv.Dispose();
        }
    }

     4.访问lua中的变量

    1)访问值类型变量

    public class HelloLua : MonoBehaviour
    {
        private LuaEnv luaenv;
    
        void Start()
        {
            luaenv = new LuaEnv();
            luaenv.DoString("require 'helloLua'");
    
            //访问文件中的全局int类型变量a
            print(luaenv.Global.Get<int>("a"));
        }
    
        private void OnDestroy()
        {
            luaenv.Dispose();
        }
    }

    2)访问table形式的变量,可以定义一个对应table的类进行,Get方法会自动new出这个类,并将变量值拷贝进去。

    public class HelloLua : MonoBehaviour
    {
        private LuaEnv luaenv;
    
        void Start()
        {
            luaenv = new LuaEnv();
            luaenv.DoString("require 'helloLua'");
    
            //获取表person的内容,存储为Person类
            Person p = luaenv.Global.Get<Person>("person");
            print(p.name + p.age);
        }
    
        private void OnDestroy()
        {
            luaenv.Dispose();
        }
    
        //定义一个和表对应好属性和方法的类
        class Person
        {
            public string name;
            public int age;
        }
    }
    person = {
     name = 'movin',age = 18
    }

     3)也可以定义一个对应table属性和方法的接口,但是接口需要加上[CSharpCallLua]特性,同时lua中定义函数时第一个参数必须是self或者使用冒号定义

    public class HelloLua : MonoBehaviour
    {
        private LuaEnv luaenv;
    
        void Start()
        {
            luaenv = new LuaEnv();
            luaenv.DoString("require 'helloLua'");
            
            IPerson p = luaenv.Global.Get<IPerson>("person");
            print(p.name + p.age);
        }
    
        private void OnDestroy()
        {
            luaenv.Dispose();
        }
    
        //如果使用接口定义接收的table,必须加上[CSharpCallLua]特性自动生成代码
        [CSharpCallLua]
        interface IPerson
        {
            string name { get; set; }
            int age { get; set; }
        }
    }

    这里注意:目前xlua没有支持unity2019版本,这里代码没有问题,但是运行始终会报错。

     4)使用字典或者链表对应table

    public class HelloLua : MonoBehaviour
    {
        private LuaEnv luaenv;
    
        void Start()
        {
            luaenv = new LuaEnv();
            luaenv.DoString("require 'helloLua'");
    
            //将table转化为字典
            Dictionary<string,object> dict = luaenv.Global.Get<Dictionary<string, object>>("person");
            //遍历输出
            foreach(KeyValuePair<string,object> pair in dict)
            {
                print(pair.Key + pair.Value);
            }
        }
    
        private void OnDestroy()
        {
            luaenv.Dispose();
        }
    }

     5)使用列表对应table,只能存储table中没有键的value值

    public class HelloLua : MonoBehaviour
    {
        private LuaEnv luaenv;
    
        void Start()
        {
            luaenv = new LuaEnv();
            luaenv.DoString("require 'helloLua'");
    
            //将table转化为list,list只能储存没有键的table值
            List<object> list = luaenv.Global.Get<List<object>>("person");
            //遍历输出
            foreach(Object o in list)
            {
                print(o);
            }
        }
    
        private void OnDestroy()
        {
            luaenv.Dispose();
        }
    }

    6)使用LuaTable类对应table

    public class HelloLua : MonoBehaviour
    {
        private LuaEnv luaenv;
    
        void Start()
        {
            luaenv = new LuaEnv();
            luaenv.DoString("require 'helloLua'");
    
            //将table存储为luatable类的对象
            LuaTable tab = luaenv.Global.Get<LuaTable>("person");
            //取得其中的键对应的值,需要声明值类型
            print(tab.Get<string>("name"));
        }
    
        private void OnDestroy()
        {
            luaenv.Dispose();
        }
    }

     7)使用委托对应lua中的函数

    public class HelloLua : MonoBehaviour
    {
        private LuaEnv luaenv;
    
        void Start()
        {
            luaenv = new LuaEnv();
            luaenv.DoString("require 'helloLua'");
    
            //使用委托存储lua中的函数,函数名称为add
            Add add = luaenv.Global.Get<Add>("add");
            add(1,3);
        }
    
        //自定义一个委托对应lua中相应的函数,一定要加上[CSharpCallLua]特性
        [CSharpCallLua]
        delegate void Add(int a, int b);
        private void OnDestroy()
        {
            luaenv.Dispose();
        }
    }

     2019版本的unity和xlua不兼容,使用更低版本解决问题。

    如果lua有不止一个返回值,可以使用out参数或ref参数接收其他的返回值。

    8)使用LuaFunction对应lua中的函数

    public class HelloLua : MonoBehaviour
    {
        private LuaEnv luaenv;
    
        void Start()
        {
            luaenv = new LuaEnv();
            luaenv.DoString("require 'helloLua'");
    
            //xlua提供了LuaFunction对应lua中的函数,使用Call方法调用函数,返回值为一个objec类型的数组
            LuaFunction func = luaenv.Global.Get<LuaFunction>("add");
            object[] objs = func.Call(1, 3);
            foreach(object o in objs)
            {
                print(o.ToString());
            }
        }
    
        private void OnDestroy()
        {
            luaenv.Dispose();
        }
    }

     三.在lua中调用C#

    1.简单实现调用

    1)首先在空物体上挂载脚本,脚本调用lua代码

    public class LuaCallCSharp : MonoBehaviour
    {
        private LuaEnv luaEnv;
    
        void Start()
        {
            luaEnv = new LuaEnv();
    
            luaEnv.DoString("require 'LuaCallCSharp'");
        }
    
        private void OnDestroy()
        {
            luaEnv.Dispose();
        }
    }

    2)然后在lua代码中实例化一个游戏物体

    --创建游戏物体,对应C#中的new UnityEngine.GameObject()代码
    CS.UnityEngine.GameObject()

    3)最后看运行结果

     4)注意事项:lua中没有new关键字,所有C#相关的内容都放在了CS下,包括函数、属性和方法等。对于经常访问的类,可以先使用局部变量存储起来,然后再进行调用,减少代码量也提高性能。

    2.访问静态属性和方法

    --对应的C#代码:print(UnityEngine.Time.deltaTime);
    print(CS.UnityEngine.Time.deltaTime)
    
    --对应的C#代码:UnityEngine.GameObject.Find("Main Camera").name = "fixed by lua"
    CS.UnityEngine.GameObject.Find("Main Camera").name = "fixed by lua"

     3.访问成员属性和方法,使用冒号语法糖

    local gameObject = CS.UnityEngine.GameObject
    local camera = gameObject.Find("Main Camera")
    
    --调用成员方法使用冒号语法糖(推荐),或者将自身作为第一个参数传递(不推荐)
    local cameraComponent = camera:GetComponent("Camera")
    gameObject.Destroy(cameraComponent)

    4.其他

    1)C#中的out参数映射到lua中时不算参数,C#中的out和ref返回值映射到lua中对应多返回值。

    2)xlua支持方法的重载

    3)支持可变参数

    4)lua不支持泛型,但是可以通过Extension methods功能进行封装后使用

    5)C#的委托的调用和普通方法相同,注册或者移除委托中的方法时需要将“+”或者“-”号作为第一个参数传递

  • 相关阅读:
    试图加载格式不正确的程序。 (异常来自 HRESULT:0x8007000B)
    git 撤销刚提交的 commint
    At least one cache should be provided per cache operation.
    @Primary注解
    怎么把sql server数据导入mysql本地数据库?
    应用程序已预编译,因此不允许使用目录“/App_Code/”
    SpringBoot学习笔记15——Dozer的使用用来两个对象之间属性转换的工具
    Invalid packaging for parent POM (pom.xml), must be "pom" but is "jar" @ pom.xml
    浏览器调试console的多种用法
    bug本天成,妙手偶得之。
  • 原文地址:https://www.cnblogs.com/movin2333/p/14364536.html
Copyright © 2020-2023  润新知