zoukankan      html  css  js  c++  java
  • 第53天XLua插件使用

    配置XLua

    本日内容unity创建的物体名、c#脚本名和lua脚本名保持一致

     

    配置文件

    1.解压压缩包

     2.选中所有文件

    3.复制到unity项目里,不是Assets文件夹里

    4.不要动XLua的路径,不要把Xlua放到Plugins里面

    测试XLua运行

     1.创建空物体

    2.挂载DoHelloWorldLua.cs文件

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    //引用命名空间XLua
    using XLua;
    
    public class DoHelloWorldLua : MonoBehaviour
    {
        void Start ()
        {
            string lua = "print('Hello World')";
    
            //需要要创建一个执行Lua的虚拟机(解析器), 通常该解析器只需要一个即可
            LuaEnv luaenv = new LuaEnv();
    
            //执行lua语句
            luaenv.DoString(lua);
    
            //如果判断解析器不再需要,可以释放掉
            luaenv.Dispose();
        }
        
    }

    配置自定义路径

    1.XLua默认的lua文件加载路径及格式

    lua问价格式是 xxx.lua.txt

    DoLuaFile.cs

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using XLua;
    
    public class DoLuaFile : MonoBehaviour
    {
    
        void Start ()
        {
            //DoLuaFile lua的文件命名
            string lua = "require('DoLuaFile')";
    
            LuaEnv luaenv = new LuaEnv();
    
            //一旦使用xLua去执行require语句时,是通过xLua的 “加载器” 去加载Lua文件
            //xLua默认有一个加载器, 默认加载器的加载路径是  Assets/Resources,
            //也就是默认加载器只能加载Resources文件夹的lua文件,并且其子文件是不可以的
    
            //默认加载器对于文件的命名有规范, 文件的后缀必须是.txt, 文件名必须是  lua的文件名.lua
            //最终文件的全部名字为:  xxx.lua.txt   例如:DoLuaFile.lua.txt
    
            //注意: xLua执行的Lua文件必须是UTF8编码格式
    
            luaenv.DoString(lua);
    
        }
        
    }

    对应lua文件地址

    格式

    DoLuaFile.lua.txt内容

    print('DO Lua File.....');

    2.自定义加载路径

    DoLuaLoader.cs

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using XLua;
    using System.IO;
    
    public class DoLuaLoader : MonoBehaviour
    {
        void Start ()
        {
            LuaEnv luaenv = new LuaEnv();
    
            //自定义加载器的加载方式
            //可以对解析器添加自定义的加载器
    
            //参数是CustomLoader类型
            //delegate byte[] CustomLoader(ref string filepath);
            //AddLoader方法能传入 返回值为byte[]  参数为ref 字符串类型的参数的方法
            luaenv.AddLoader(FolderLoader);
            luaenv.AddLoader(FolderLoader1);
    
            //当xLua执行require语句时,会首先调用自定义加载器去加载Lua文件,
            //如果一个加载器加载到了文件,那么后续加载器不再调用
            //如果所有的自定义加载器未找到,那么再调用默认加载器
            //如果默认加载器也未找到,那么则报错
            luaenv.DoString("require('DoFolderLua')");
        }
    
        //如果自定义加载器的返回值为null,表示该加载器未找到文件
        //需要将lua语言的字符串转使用UTF8换成字节数组
        byte[] FolderLoader(ref string fileName)
        {
            Debug.Log("执行 Folder Loader的加载器方法: " + fileName);
            string path = Application.dataPath + "/Lua/" + fileName + ".lua";
    
            //判断文件是否存在
            if (File.Exists(path))
            {
                return File.ReadAllBytes(path);
            }
    
            return null;
        }
    
        byte[] FolderLoader1(ref string fileName)
        {
            Debug.Log("执行 Folder1 Loader的加载器方法: " + fileName);
            return null;
        }
    
    }

    Lua文件统一放到Lua文件夹下

    DoLuaLoader.lua

    print("Do Folder Lua ......")

    XLua的管理类XLuaMgr

     XLuaMgr.cs

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using XLua;
    using System.IO;
    
    public class XLuaMgr 
    {
        #region 单例
        private static XLuaMgr instance;
    
        public static XLuaMgr Instance
        {
            get {
                if (instance == null)
                {
                    instance = new XLuaMgr();
                }
                return instance;
            }
        }
    
        private XLuaMgr()
        {
            luaenv = new LuaEnv();
    
            //添加自定义的加载器
            luaenv.AddLoader(FolderLoader);
        }
        #endregion
    
        //管理Lua解析器
        private LuaEnv luaenv;
    
        public LuaEnv LuaEnv
        {
            get { return luaenv; }
        }
    
    
        //Assets目录下的Lua文件夹路径及其子文件夹路径
        private List<string> folders;
        //该加载器只在Editor下有意义
        byte[] FolderLoader(ref string fileName)
        {
    #if UNITY_EDITOR
            if (folders == null)
            {
                folders = new List<string>();
                string luaPath = Application.dataPath + "/Lua/";
                folders.Add(luaPath);
                //所有的子文件夹路径
                string[] dirs = Directory.GetDirectories(luaPath);
                foreach (var child in dirs)
                {
                    folders.Add(child + "/");
                }
            }
    
            //依次判断每个文件夹是否有该文件
            string name = fileName + ".lua";
    
            for (int i = 0; i < folders.Count; i++)
            {
                if (File.Exists(folders[i] + name))
                {
                    return File.ReadAllBytes(folders[i] + name);
                }
            }
    
    #endif
            return null;
        }
    
    
    }

    c#调用Lua文件

    获取lua文件内的变量

    GlobalDataLua.lua

    print("Do Global Data Lua ... ...")
    
    --全局变量
    a = 10
    
    b = 2.6
    
    c = true
    
    d = "string"

    GlobalDataLua.cs

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using XLua;
    
    public class GlobalDataLua : MonoBehaviour
    {
    
        void Start () {
    
            XLuaMgr.Instance.LuaEnv.DoString("require('GlobalDataLua')");
    
            //访问Lua文件中的全局变量
            //xLua在执行Lua文件是, 会将Lua文件中的全局变量存储在一个Global
            //Global可以通过LuaEnv获取,类型是LuaTable类型
            LuaTable global = XLuaMgr.Instance.LuaEnv.Global;
    
            //通过LuaTable的Get方法获取
            //泛型为Lua变量的数据类型对应的C#类型, 参数就是Lua变量名
            int a = global.Get<int>("a");
            Debug.Log(a);
    
            float b = global.Get<float>("b");
            Debug.Log(b);
    
            bool c = global.Get<bool>("c");
            Debug.Log(c);
    
            string d = global.Get<string>("d");
            Debug.Log(d);
        }
    }

    获取lua的table

    GlobalTableLua.lua

    print("Global Table Lua ......")
    tab1 = 
    { 
        [1] = 12,
        name = "小明",
        age = 18,
        isMan = true,
    }
    
    
    tab2 = 
    { 
        name = "小刘",
        age = 30,
        isMan = true,
        Func = function ()
            print("执行Lua Func的方法")
        end
    }
    
    tab3 = {"123", "456", "789", 12}

    GlobalTableLua.cs

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using XLua;
    
    public class GlobalTableLua : MonoBehaviour
    {
        void Start ()
        {
            XLuaMgr.Instance.LuaEnv.DoString("require('GlobalTableLua')");
    
            //TableToClass();
            //TableToInterface();
            //TableToDictionary();
            //TableToList();
            TableToLuaTable();
        }
    
        #region Class
        //第一种映射Table的方式,通过class或struct,  值类型复制
        public class Tab1Class
        {
            //table中的有哪些键, 类中就有哪些变量
            //变量名要与table中的键名保持一致,类型也要保持一致
            public string name;
            public int age;
            public bool isMan;
            //类中使用委托类映射table的方法
        }
    
        void TableToClass()
        {
            LuaTable global = XLuaMgr.Instance.LuaEnv.Global;
    
            //通过Get方法获取
            Tab1Class t1 = global.Get<Tab1Class>("tab1");
            Debug.Log(t1.name);
            Debug.Log(t1.age);
            Debug.Log(t1.isMan);
        }
        #endregion
    
    
        #region Interface
        //第二种映射Table的方式, 通过interface, 引用类型复制
        //接口前必须加[CSharpCallLua]特性, 使用接口映射需要自动生成一些代码
        //添加[CSharpCallLua]特性后,xlua会识别到自动生成一些配置的代码
        //如果没有自动生成, 需要手动的执行XLua -> Generate Code
    
        [CSharpCallLua]
        public interface ITab2Interface
        {
            //接口中不允许定义变量的, 但是可以定义属性
            //使用属性来映射table中的键值对
            string name { set; get; }
            int age { set; get; }
            bool isMan { set; get; }
            //接口中使用方法来映射Table的方法
            void Func();
        }
    
        void TableToInterface()
        {
            LuaTable global = XLuaMgr.Instance.LuaEnv.Global;
    
            ITab2Interface t2 = global.Get<ITab2Interface>("tab2");
            Debug.Log(t2.name);
            Debug.Log(t2.age);
            Debug.Log(t2.isMan);
            t2.Func();
        }
        #endregion
    
    
        #region Dictionary List
        //第3种映射Table的方式, 通过Dictionary和List  值拷贝
        void TableToDictionary()
        {
            LuaTable global = XLuaMgr.Instance.LuaEnv.Global;
    
            //使用字典进行映射, 只能映射到与字典的键相同类型,字典值相同类型的数据
            Dictionary<string, object> t1 = global.Get<Dictionary<string, object>>("tab1");
    
            foreach (var item in t1)
            {
                Debug.Log(item.Key + " --  "+ item.Value);
            }
        }
    
        void TableToList()
        {
            LuaTable global = XLuaMgr.Instance.LuaEnv.Global;
    
            //只能映射Table作为数组时的数据, 并且只能映射值与指定List的类型相同的值
            List<string> t3 = global.Get<List<string>>("tab3");
    
            for (int i = 0; i < t3.Count; i++)
            {
                Debug.Log(t3[i]);
            }
        }
        #endregion
    
        #region LuaTable
        //第四种方式, 通过LuaTable, 引用传递
        void TableToLuaTable()
        {
            LuaTable global = XLuaMgr.Instance.LuaEnv.Global;
    
            LuaTable lt = global.Get<LuaTable>("tab1");
            //获取name, age, isMan
            string name = lt.Get<string>("name");
            Debug.Log(name);
            int age = lt.Get<int>("age");
            Debug.Log(age);
            bool isMan = lt.Get<bool>("isMan");
            Debug.Log(isMan);
        }
    
        #endregion
    }

    获取lua的function

    GlobalFunctionLua.lua

    print("Global Function Lua ......")
    
    function Func1()
        print("Lua Func1")
    end
    
    function Func2(a, b)
        print("Lua Func2")
        return a + b
    end
    
    
    function Func3()
        return 12, true, "string"
    end

    GlobalFunctionLua.cs

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using XLua;
    
    public class GlobalFunctionLua : MonoBehaviour
    {
    
        
        void Start ()
        {
            XLuaMgr.Instance.LuaEnv.DoString("require('GlobalFunctionLua')");
    
            //FunctionToDelegate1();
            //FunctionToLuaFunction();
    
            //FunctionToDelegate2();
            FunctionToDelegate3();
        }
    
        #region 通过委托进行映射
        //定义委托类型, 返回值与参数与Lua中的要映射的方法一致
        [CSharpCallLua] //注意: 定义委托要加特性
        public delegate void Function1();
        [CSharpCallLua]
        public delegate int Function2(int a, int b);
    
        void FunctionToDelegate1()
        {
            LuaTable global = XLuaMgr.Instance.LuaEnv.Global;
    
            Function1 f1 = global.Get<Function1>("Func1");
            f1();
    
            Function2 f2 = global.Get<Function2>("Func2");
            int num = f2(10, 20);
            Debug.Log(num);
        }
    
        //映射多返回指的Lua方法
        //多返回值的映射, 通过委托的 返回值、输出参数(out、ref)返回
        //委托有返回值,Lua的第一个返回值对应委托的返回值, 从第二个返回值开始,依次对应委托的输出参数(out、ref)
        //委托没有返回值,Lua的从第一个返回值开始,依次对应委托的输出参数(out、ref)
        /*
        function Func3()
            return 12, true, "string"
        end 
         * */
        [CSharpCallLua]
        public delegate int Function3(out bool a, ref string str);
    
        [CSharpCallLua]
        public delegate void Function4(out int num, out bool a, ref string str);
    
        void FunctionToDelegate2()
        {
            LuaTable global = XLuaMgr.Instance.LuaEnv.Global;
    
            Function3 f3 = global.Get<Function3>("Func3");
            bool outTwo;
            string outThree = "";
            int outOne = f3(out outTwo, ref outThree);
            Debug.Log(outOne);
            Debug.Log(outTwo);
            Debug.Log(outThree);
        }
    
        void FunctionToDelegate3()
        {
            LuaTable global = XLuaMgr.Instance.LuaEnv.Global;
    
            Function4 f4 = global.Get<Function4>("Func3");
            int outOne;
            bool outTwo;
            string outThree = "";
            f4(out outOne,out outTwo, ref outThree);
            Debug.Log(outOne);
            Debug.Log(outTwo);
            Debug.Log(outThree);
        }
    
        #endregion
    
    
        #region 通过LuaFunction映射
    
        void FunctionToLuaFunction()
        {
            LuaTable global = XLuaMgr.Instance.LuaEnv.Global;
    
            LuaFunction lf1 = global.Get<LuaFunction>("Func1");
            //通过LuaFunction的Call方法调用
            lf1.Call();
    
            LuaFunction lf2 = global.Get<LuaFunction>("Func2");
            object[] arr = lf2.Call(10, 21);
            Debug.Log(arr[0]);
        }
    
        #endregion
    }

    Lua调用C#文件

    lua创建新的unity物体

    LuaNewObject.lua

    print("Lua New Object ......")
    
    --C#  UnityEngine.GameObject obj = new UnityEngine.GameObject();
    
    --Lua 调用GameObject类的构造函数, 变量不需要定义类型,没有new关键字
    --xLua 是支持C#的重载函数的,有局限性
    --格式:   CS.命名空间.类名(参数列表)
    local obj1 = CS.UnityEngine.GameObject("obj1")
    
    --简写方式
    --使用一个变量来存储C#的类, GameObject就是C#的UnityEngine.GameObject类
    --GameObject = CS.UnityEngine.GameObject
    --通常使用一个单独文件,来定义所有的Unity的常用类
    require('UnityAPI')
    
    local obj2 = GameObject("obj2")
    local obj3 = GameObject("obj3")

    此处可以引用一个定义好的UnityAPI的lua文件,就不用那么繁琐的调用了

    例:UnityAPI.lua

    GameObject = CS.UnityEngine.GameObject

    LuaNewObject.cs

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class LuaNewObject : MonoBehaviour
    {
    
        void Start ()
        {
            XLuaMgr.Instance.LuaEnv.DoString("require('LuaNewObject')");
    
            //UnityEngine.GameObject obj = new UnityEngine.GameObject();
    
        }
        
    }

    lua调用c#的静态方法

    LuaCallStaticMember.lua

    print("Lua Call Static Member ......")
    
    --调用C#的静态成员
    
    --静态变量,静态属性
    --C# UnityEngine.Time.deltaTime
    --Lua 调用静态变量与属性: CS.命名空间.类名.变量名或属性名 或  CS.类名.变量名或属性名
    --print(CS.UnityEngine.Time.deltaTime)
    
    Time = CS.UnityEngine.Time
    print(Time.deltaTime)
    
    
    --静态方法
    --C#  UnityEngine.GameObject obj = UnityEngine.GameObject.Find("")
    --Lua 调用静态方法:CS.命名空间.类名.方法名(参数)  或 CS.类名.方法名(参数)
    --local obj = CS.UnityEngine.GameObject.Find("Main Camera")
    
    GameObject = CS.UnityEngine.GameObject
    local obj = GameObject.Find("Main Camera")
    
    --判断是否查找到
    --[[
    if obj ~= nil then
        print("找到了Main Camera")
    else
        print("未找到了Main Camera")
    end
    ]]
    --简写, lua认为除了false与nil,其余全是真(true)
    --obj不为nil, lua认为是true,证明找到了
    if obj then
        print("找到了Main Camera")
    else
        print("未找到了Main Camera")
    end

    LuaCallStaticMember.cs

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class LuaCallStaticMember : MonoBehaviour
    {
    
        void Start ()
        {
            XLuaMgr.Instance.LuaEnv.DoString("require('LuaCallStaticMember')");
        }
        
    }

    lua调用c#非静态成员和内部类

    LuaCallUnStaticMember.lua

    print("Lua Call Un Static Member ......")
    
    --Lua访问非静态(实例)成员
    --C# 调用实例成员  对象.成员名
    
    --实例化一个对象,实例化的过程是调用构造函数的过程
    local member = CS.UnStaticMemberClass()
    
    --实例变量、实例属性
    --Lua 调用实例变量与属性  对象名.变量名或属性名
    member.name = "小小名"
    print(member.name)
    print(member.Age)
    
    --实例方法
    --Lua 调用实例方法   对象名:方法名()
    member:Function()
    
    --mebmer 是 UnStaticMemberClass 的对象
    --BaseFunction 是 BaseClass 的方法
    --UnStaticMemberClass 继承 BaseFunction
    --Lua支持通过子类对象 mebmer 调用父类的方法 BaseFunction lua支持继承
    member:BaseFunction()
    
    --实例化内部类
    --Lua 调用内部类   CS.命名空间.类名.内部类名 或  CS.类名.内部类名
    local t = CS.LuaCallUnStaticMember.Test()
    print(t.name)

    LuaCallUnStaticMember.cs

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using XLua;
    
    public class LuaCallUnStaticMember : MonoBehaviour
    {
        void Start ()
        {
            XLuaMgr.Instance.LuaEnv.DoString("require('LuaCallUnStaticMember')");
        }
        //内部类
        [LuaCallCSharp]
        public class Test
        {
            public string name = "Test";
        }
    }
    
    //如果Lua要调用自定义的类时,定义类的最好加[LuaCallCSharp]
    //有了该特性, 会生成对应的配置代码
    //如果没有该特性, Lua调用该类时, 会采用反射的方式, 反射的效率比直接调用要低, 有些平台上不支持
    [LuaCallCSharp] 
    public class UnStaticMemberClass : BaseClass
    {
        public string name = "小明";
    
        public int Age
        {
            get { return 18; }
        }
    
        public void Function()
        {
            Debug.Log("执行C# UnStaticMemberClass类中的Function方法");
        }
    }
    
    
    public class BaseClass
    {
        public void BaseFunction()
        {
            Debug.Log("执行C# BaseClass基类中的BaseFunction方法");
        }
    }

    lua支持部分c#的重载方法

    LuaCallOverloadFunction.lua

    print("Lua Call Overload Function ......")
    
    --xLua是支持C#的重载函数的
    OverloadClass = CS.OverloadClass
    
    --[[
    OverloadClass.Function()
    
    OverloadClass.Function(10)
    
    OverloadClass.Function("10")
    
    OverloadClass.Function(1, 2)
    ]]
    --xLua虽然支持重载,但是有局限, 
    --当两个重载的参数个数相同,为int和float时,xLua区分不开
    --因为Lua中只有number类型
    OverloadClass.Function(10.2)
    
    OverloadClass.Func(10)    //c#中该方法不需要参数,传参不报错,可以正常调用
    
    OverloadClass.Func2()    //c#的该方法需要参数,不传也不报错,也可以正常调用

    LuaCallOverloadFunction.cs

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class LuaCallOverloadFunction : MonoBehaviour
    {
        void Start ()
        {
            XLuaMgr.Instance.LuaEnv.DoString("require('LuaCallOverloadFunction')");
        }
    }
    
    [XLua.LuaCallCSharp]
    public class OverloadClass
    {
        public static void Func()
        {
            Debug.Log("Func");
        }
    
        public static void Func2(string str)
        {
            Debug.Log("Func: " + str);
        }
        public static void Function()
        {
            Debug.Log("无参数的方法");
        }
    
        public static void Function(int a)
        {
            Debug.Log("有一个 int 参数的方法: " + a);
        }
    
        public static void Function(float a)         
        {
            Debug.Log("有一个 float 参数的方法: " + a);
        }
    
        public static void Function(int a, int b)
        {
            Debug.Log("有二个 int 参数的方法: " + a + " --  " + b);
        }
    
        public static void Function(string a)
        {
            Debug.Log("有一个 string 参数的方法: " + a);
        }
    }
  • 相关阅读:
    React简介
    webpack处理项目中的资源文件
    ajax
    DOW
    webpack-css单独打包配置
    SSH配置
    html-webpack
    常用ui
    git命令备忘
    关于git的一些使用
  • 原文地址:https://www.cnblogs.com/yifengs/p/14548189.html
Copyright © 2011-2022 走看看