首先在Lua脚本中定义一个table:
一:映射到Class&Struct
在CS脚本中:
——新建映射类中的字段名必须与Lua中table的键名相同(Lua中键为name,那么映射类中字段名也要是name)
using UnityEngine;
using XLua;
public class CallLua: MonoBehaviour
{
private void Start()
{
LuaEnv luaenv = new LuaEnv();
luaenv.DoString("require 'CsCallLua'");
Person person = luaenv.Global.Get<Person>("person");
print(person.age + "-" + person.name); //输出:15-liu
person.eat(); //没有输出
luaenv.Dispose();
}
class Person
{
public string name;
public int age;
public void eat();
}
}
二:映射到Interface(推荐使用)
!!!2018版本的Unity无法使用这个方法
在CS脚本中:
——接口中不能包含字段,只能使用属性
——接口需要用[CSharpCallLua]去修饰
——新建的映射接口中的属性名必须与Lua的table键名相同(Lua中键为name,那么映射接口中的属性名也要是name)
using UnityEngine;
using XLua;
public class CallLua: MonoBehaviour
{
private void Start()
{
LuaEnv luaenv = new LuaEnv();
luaenv.DoString("require 'CsCallLua'");
IPerson person = luaenv.Global.Get<IPerson>("person");
print(person.name + "-" + person.age); //输出:liu-15
person.eat(); //输出:LUA:正在吃饭
luaenv.Dispose();
}
[CSharpCallLua]
interface IPerson
{
string name { get; set; }
int age { get; set; }
void eat();
}
}
那么如果Lua中的函数带参数呢?
在Lua脚本中:
在CS中:
运行后发现报错:
报错内容为:尝试将一个数字赋给一个表。这是因为在C#调用Lua的函数时,函数有一个隐藏参数,指向自身。
当我们定义function(a,b)时,其实内部的参数有三个,表名(person),a,b,第一个参数为默认的参数:表名(person),后面的参数才是自己定义的参数,在调用eat(1,2)时相当于我们把数字1赋给了一个表类型person,所以会报错。
有以下两种写法避免这个错误:
1.在Lua中定义函数时增加一个代表自身的参数:
运行后控制台输出:LUA:3
2.在Lua中定义函数时用冒号去定义,这样C#调用Lua时默认带一个self参数。
运行后控制台输出:LUA:3
映射到Class与映射到Interface的区别:
1.映射到Class不能访问到Lua中的函数,映射到Interface可以访问到Lua中的函数。
2.映射到Class时,xLua内部会帮你new一个实例,然后再将值拷贝赋值给这个实例,如果class比较复杂代价会比较大而且因为是值传递所以修改class的字段值不会同步到table。但是映射到Interface却不是值传递而是引用传递。
可以用luaenv.DoString("print('person.name')")去访问到Lua脚本中的值
三:映射到Dictionary&List
这种方式不需要写太多的代码,因为不需要定义类或者接口,代码比较简洁,但是有很多的局限性。
首先在Lua脚本中写一个table:
1.映射到Dictionary
只能映射table中同时有键和值的数据(类似字典),table中的函数虽然可以映射过来但是结果并不正确。
using UnityEngine;
using System.Collections.Generic;
using XLua;
public class CallLua : MonoBehaviour
{
private void Start()
{
LuaEnv luaenv = new LuaEnv();
luaenv.DoString("require 'CsCallLua'");
Dictionary<string, object> personDict = luaenv.Global.Get<Dictionary<string, object>>("person");
foreach (string key in personDict.Keys)
{
print(key + "-" + personDict[key]); //输出:name-liu
//输出:age-15
//输出:eat-functiom():11
}
luaenv.Dispose();
}
}
2.映射到List
只能映射table中没有键的数据(类似数组)。
using UnityEngine;
using System.Collections.Generic;
using XLua;
public class CallLua : MonoBehaviour
{
private void Start()
{
LuaEnv luaenv = new LuaEnv();
luaenv.DoString("require 'CsCallLua'");
List<object> personList = luaenv.Global.Get<List<object>>("person");
foreach (object temp in personList)
{
print(temp); //输出:1023
//输出:may
}
luaenv.Dispose();
}
}
四:映射到LuaTable
这种方式与映射到字典和列表类似不需要写太多代码,但是性能会慢很多。
using UnityEngine;
using System.Collections.Generic;
using XLua;
public class CallLua : MonoBehaviour
{
private void Start()
{
LuaEnv luaenv = new LuaEnv();
luaenv.DoString("require 'CsCallLua'");
LuaTable personTab = luaenv.Global.Get<LuaTable>("person");
print(personTab.Get<int>("age")); //输出:15
print(personTab.Get<string>("name")); //输出:liu
luaenv.Dispose();
}
}