首先在Lua脚本中定义一个table
xLua(五)——C#访问Lua的table_热更新

一:映射到Class/Struct

新建映射类/结构体中的字段名必须与Lua中table的键名相同(Lua中键为name,那么映射类中字段名也要是name)

using UnityEngine;
using XLua;

public class CsCallLua : MonoBehaviour
{
    private void Start()
    {
        LuaEnv luaenv = new LuaEnv();

        luaenv.DoString("require '1'");

        Person p = luaenv.Global.Get<Person>("person");
        print(p.name + "-" + p.age);    //liu-10

        luaenv.Dispose();
    }

    class Person
    {
        public string name;
        public int age;
    }
}

 


二:映射到Interface(推荐使用)

注意以下几点:
——接口中不能包含字段,只能使用属性和方法
——新建的映射接口中的属性名必须与Lua的table键名相同(Lua中键为name,那么映射接口中的属性名也要是name)
——接口需要用[CSharpCallLua]特性去修饰,如果添加了特性仍然报This type must add to CSharpCallLua的错误,则清除一下生成代码即可(菜单栏XLua——Clear Generated Code)

using XLua;
using UnityEngine;

public class CsCallLua : MonoBehaviour
{
    private void Start()
    {
        LuaEnv luaenv = new LuaEnv();

        luaenv.DoString("require '1'");

        IPerson p = luaenv.Global.Get<IPerson>("person");
        print(p.name + "-" + p.age);        //liu-10
        p.eat();                            //LUA:在吃饭

        luaenv.Dispose();
    }

    [CSharpCallLua]
    interface IPerson
    {
        int age { get; set; }
        string name { get; set; }
        void eat();
    }
}

那么如果Lua表中的函数带参数呢?
xLua(五)——C#访问Lua的table_热更新_02
在CS中:
xLua(五)——C#访问Lua的table_热更新_03
运行后发现报错
xLua(五)——C#访问Lua的table_C#_04
报错内容为:尝试将一个数字赋给一个表。这是因为在C#调用Lua的函数时,函数有一个隐藏参数,指向自身
当我们定义function(a,b)时,其实内部的参数有三个:表名(person),a,b,第一个参数为默认的参数:表名(person),后面的参数才是自己定义的参数
在调用eat(1,2)时相当于我们把数字1赋给了一个表类型person,所以会报错
 

有以下两种写法避免这个错误:
——在Lua中定义函数时增加一个代表自身的参数
xLua(五)——C#访问Lua的table_C#_05

 


——在Lua中定义函数时用冒号去定义,这样C#调用Lua时默认带一个self参数
xLua(五)——C#访问Lua的table_热更新_06

——————访问table中function的完整代码

using XLua;
using UnityEngine;

public class CsCallLua : MonoBehaviour
{
    private void Start()
    {
        LuaEnv luaenv = new LuaEnv();

        luaenv.DoString("require '1'");

        IPerson p = luaenv.Global.Get<IPerson>("person");
        
        p.eat(1,2);             //LUA:3               

        luaenv.Dispose();
    }

    [CSharpCallLua]
    interface IPerson
    {
        void eat(int num1,int num2);
    }
}

 映射到Class/Struct与映射到Interface的区别:
——映射到Class/Struct不能访问到表中的函数,映射到Interface可以访问到表中的函数
——映射到Class/Struct时,xLua的拷贝过程是一个值拷贝(xLua内部会帮你new一个实例,然后再将值赋值给这个实例,因为是值传递所以修改class的字段值不会同步到原始表中),映射到Interface的过程不是值拷贝而是引用拷贝

using XLua;
using UnityEngine;

public class CsCallLua : MonoBehaviour
{
    private void Start()
    {
        LuaEnv luaenv = new LuaEnv();

        luaenv.DoString("require '1'");

        Person p1 = luaenv.Global.Get<Person>("person");
        IPerson p2 = luaenv.Global.Get<IPerson>("person");

        p1.name = "chen";
        print(p1.name);                             //chen
        luaenv.DoString("print(person.name)");      //LUA:liu

        p2.name = "chen";
        print(p2.name);                             //chen
        luaenv.DoString("print(person.name)");      //LUA:chen

        luaenv.Dispose();
    }

    [CSharpCallLua]
    interface IPerson
    {
        string name { get; set; }
    }

    class Person
    {
        public string name;
    }
}

     


 三:映射到Dictionary/List

这种方式不需要写太多的代码,因为不需要定义类或者接口,代码比较简洁,但是有很多的局限性

首先在Lua脚本中定义一个table
xLua(五)——C#访问Lua的table_C#_07

——映射到Dictionary
只能映射table中同时有键和值的数据(类似字典),table中的函数虽然可以映射过来但是结果并不正确

using XLua;
using UnityEngine;
using System.Collections.Generic;

public class CsCallLua : MonoBehaviour
{
    private void Start()
    {
        LuaEnv luaenv = new LuaEnv();

        luaenv.DoString("require '1'");

        Dictionary<string, object> pDict = luaenv.Global.Get<Dictionary<string, object>>("person");
        foreach (object temp in pDict)
        {
            print(temp);    //[name,liu]
                            //[age,10]
                            //[eat,function:11]
        }

        luaenv.Dispose();
    }
}

 

 

——映射到List
只能映射table中没有键的数据(类似数组)

using XLua;
using UnityEngine;
using System.Collections.Generic;

public class CsCallLua : MonoBehaviour
{
    private void Start()
    {
        LuaEnv luaenv = new LuaEnv();

        luaenv.DoString("require '1'");

        List<object> pDict = luaenv.Global.Get<List<object>>("person");
        foreach (object temp in pDict)
        {
            print(temp);    //1023
                            //may
        }

        luaenv.Dispose();
    }
}

四:映射到LuaTable

这种方式与映射到Dictionary/List类似不需要写太多代码,但是性能会降低很多,不推荐使用

using XLua;
using UnityEngine;

public class CsCallLua : MonoBehaviour
{
    private void Start()
    {
        LuaEnv luaenv = new LuaEnv();

        luaenv.DoString("require '1'");

        LuaTable pTab = luaenv.Global.Get<LuaTable>("person");
        print(pTab.Get<int>("age"));        //10
        print(pTab.Get<string>("name"));    //liu

        luaenv.Dispose();
    }
}