Xlua学习笔记整理。还有很多没整理完,慢慢来。
1.直接执行字符串:
LuaEnv env = new LuaEnv();
env.DoString("print('这是我的第一个lua程序'");
2.加载Lua文件
使用Require函数加载Lua文件
require就是一个个的调用Loader,查找出匹配的lua文件,然后执行该文件。
(1)使用默认Loader加载
LuaEnv env = new LuaEnv();
env.DoString("require 'SimpleLua' ");//不用加lua后缀
(2)使用自定义Loader加载
通过Addloader可以注册个回调,该回调参数是字符串,Lua代码里头调用require时,参数将会自动传给回调,
回调中就可以根据这个参数去加载指定文件,如果需要支持调试,需要把filepath修改为真实路径传出。
LuaEnv env = new LuaEnv();
env.AddLoader(CustomMyLoader);
env.DoString("require 'HelloWord'");
///
/// 定义回调方法
/// 功能:
/// 本方法主要功能是自定义lua文件路径
///
/// 文件名称
///
private byte[] CustomMyLoader(ref string fileName)
{
byte[] byArrayReturn = null;//返回数据
//定义lua路径
string luaPath = Application.dataPath + "/StreamingAssets/" + fileName + ".lua";
//读取lua路径中指定lua文件内容
string strLuaContent =File.ReadAllText(luaPath);
//数据类型转换
byArrayReturn = System.Text.Encoding.UTF8.GetBytes(strLuaContent);
return byArrayReturn;
}
注意:
1.使用默认Loader加载lua文件,必须放在Resources特殊目录下,否则查找不到无法加载。
2.因为Resource只支持有限的后缀,放Resource下的lua文件需要加上txt后缀。
3.自定义Loader可以进一步扩展加载路径,可以按照自己的方式进行加载lua与执行lua代码。
4.require本质是按照既定的查找顺序,找到需要的lua程序,否则返回nil,然后报错。
主要是C#调用Lua的全局数据类型,包括字段,table,函数。
最大特点: env.Global.Get调用lua中的表,字段,函数。
访问LuaEnv.Global就可以了,上面有个模版Get方法,可指定返回的类型。
eg:
Lua
str="全局变量"
number=10
C#
string str1 = env.Global.Get("str");//字符串类型
int number = env.Global.Get("number");//数字类型
由于Lua中Table可以充当很多职能,如数组,字典(键值对),类(Class)。根据其职能不同调用也不同。
直接映射到List
eg:
Lua
progamLanguage={"C#","Lua","C++","C"}
C#
List
直接映射到Dictionary
eg:
Lua
gameLanguage={str1="C#语言",str2="lua语言",str3="C++语言",str4="C语言"}
C#
Dictionary dicGameLan = env.Global.Get>("gameLanguage");
当Lua中的table为类时有三种调用方法,一种是映射到普通class或struct,为值拷贝。一种是映射到接口interface,是引用拷贝。一种是映射到Xlua自身的LuaTable上。
Lua
--定义一个综合表(lua中的oop思想)
GameUser=
{
name="小河",
age=199,
ID="188875221",
Speak=function()
print("lua玩家在讨论中")
end,
Walking=function()
print("lua玩家在健身中")
end,
Calulation=function(this,num1,num2) --说明:this 这里命名可以任意,表示当前对象(即GameUser)
print("lua玩家加年龄和")
return this.age+num1+num2
end
}
定义一个class,有对应table的字段的public属性,而且有无参数构造函数即可。table的属性可以多于或者少于class的属性,可以嵌套其他复杂类型。
eg:
C#
public class GameUser
{
public string name;
public int age;
public int ID;
public void Speak()
{
}
public void Walking()
{
}
public int Calulation(int num1, int num2)
{
return 0;
}
}
public class CsharpCallLuaTableByClass : MonoBehaviour
{
//lua环境(官方建议全局唯一)
LuaEnv env = null;
private void Start()
{
env = new LuaEnv();
//不用加lua后缀
env.DoString("require 'CsharpCallLuaTable' ");
//**********************************************************************************
//方式1: 使用class(struct)来映射得到lua中的table内容。
//值得注意的是,这个过程是值拷贝,如果class比较复杂代价会比较大。(即:较消耗性能)
//而且修改class的字段值不会同步到table,反过来也不会。此种方式可以通过把类型加到
//GCPotimize生成减低开销。
//得到lua中的表信息
GameUser gameuser = env.Global.Get("GameUser");
Debug.Log("GameUser.name=" + gameuser.name);
Debug.Log("GameUser.age="+gameuser.age);
Debug.Log("GameUser.ID="+gameuser.ID);
gameuser.Walking();//调不出来
gameuser.Speak();//调不出来
Debug.Log(gameuser.Calulation(50, 30));//调不出来,值为0
}
性能分析:
这个过程是值拷贝,修改Class的字段值不会同步到Lua中的table。如果class比较复杂代价会比较大(即:较消耗性能。)而且修改class的字段值不会同步到table,反过来也不会。此种方式可以通过把类型加到GCPotimize生成减低开销。
这里要说明的是,后面的方法没有映射到,没有得到Lua中table的方法,可能是我的写法不对,也可能是这种方法不能获得lua中Tbale的函数方法。
这种方式依赖于生成代码(如果没生成代码会抛InvalidCastException异常),代码生成器会生成
这个interface的实例。如果get一个属性,生成代码会get对应的table字段,如果set属性也会
设置对应的字段。甚至可以通过interface的方法访问lua函数。
注意点与性能分析:
A:接口需要添加特性标签[CSarpCallLua],否则无法生成实例代码。
B:为引用拷贝,适合用在复杂表,一般商业项目推荐使用本方式。
eg:
C#
[CSharpCallLua]
public interface IGameUser
{
string name { get; set; }
int age { get; set; }
string ID { get; set; }
void Speak();
void Walking();
int Calulation(int num1, int num2);
}
public class CsharpCallLuaTableByInterfaceComplex : MonoBehaviour
{
//lua环境(官方建议全局唯一)
LuaEnv env = null;
private void Start()
{
env = new LuaEnv();
//
env.DoString("require 'CsharpCallLuaTable' ");
//得到lua中的表信息
IGameUser gameUser = env.Global.Get("GameUser");
//输出显示
Debug.Log("使用接口GameUser.name" + gameUser.ID);
Debug.Log("使用接口GameUser.age" + gameUser.age);
Debug.Log("使用接口GameUser.ID" + gameUser.ID);
//输出调用方法
gameUser.Speak();
gameUser.Walking();
int tmpResult = gameUser.Calulation(100, 200);
Debug.Log("经过lua中计算,结果是"+tmpResult);
}
}
这种方式好处是不需要生成代码,但问题就是比较慢(即:效率低下),比interface方式要慢一个数量级,比如没有类型检查。
性能分析:
因为效率较低,所以不推荐常用,适合用在一些较为复杂且使用频率很低的情况下,所以不推荐使用。
eg:
C#
public class CsharpCallLuaTableByLuaTable : MonoBehaviour
{
//lua环境(官方建议全局唯一)
LuaEnv env = null;
private void Start()
{
env = new LuaEnv();
//
env.DoString("require 'CsharpCallLuaTable' ");
//得到lua中的复杂表信息
XLua.LuaTable tabGameUser = env.Global.Get("GameUser");
//输出显示
Debug.Log("name=" + tabGameUser.Get("name"));
Debug.Log("age=" + tabGameUser.Get("age"));
Debug.Log("ID=" + tabGameUser.Get("ID"));
//效率较低,适合用于一些较为复杂且使用频率很低的情况下,所以不推荐使用。
//输出表中函数
XLua.LuaFunction funSpeak = tabGameUser.Get("Speak");
funSpeak.Call();
XLua.LuaFunction funWalking = tabGameUser.Get("Walking");
funSpeak.Call();
XLua.LuaFunction funCalulation = tabGameUser.Get("Calulation");
object[] objArray= funCalulation.Call(tabGameUser,10,20);
Debug.Log("输出结果="+objArray[0]);//输出结果
}
}
两种方法,映射到委托和映射到Xlua自身的LuaFunction.
Lua
--无参函数
function ProcMyFunc1()
print("ProcMyFunc1 无参函数")
end
--有参函数
function ProcMyFunc2(num1,num2)
print("ProcMyFunc2 两个函数 num1+num2="..num1+num2)
end
---带返回值函数
function ProcMyFunc3(num1,num2)
print("ProcMyFunc3 具备返回数值的函数")
return num1+num2
end
--带有多个参数的函数
function ProcMyFunc4(num1,num2,num3)
print("ProcMyFunc4 三个函数 num1+num2+num3="..num1+num2+num3)
end
--定义具有多个返回数值的函数
function ProcMyFunc5(num1,num2)
local result=num1+num2
print("ProcMyFunc5 函数,具备多个数值")
return num1,num2,result
end
优点:这是建议的方式,性能好很多,而且类型安全。
缺点:要生成代码。
delegate要怎样声明?对于function的每个参数就声明一个输入类型的参数。多返回值要怎么处理?从左往右映射到C#的输出参数,输出参数包括返回值,out参数,ref参数。
返回值类型支持哪些呢?都支持,各种复杂类型,out,ref修饰的,甚至可以返回另外一个delegate.
注意:
1.含有out与ref关键字委托也需要添加特性标签[CSharpCallLua]。
2.委托引用后,退出luaEnv前,需要释放委托引用,否则lua报错。
3.对于Unity与C#中的复杂类型API,必须加入Xlua的配置文件,经过生成代码后才能正确应用。
共三步:
第一步声明委托:含有out与ref关键字委托也需要添加特性标签[CSharpCallLua]
//自定义委托(使用out或者关键字)
[CSharpCallLua]
public delegate void delAddingMutiReturnOut(int num1, int num2, out int res1, out int res2, out int res3);
[CSharpCallLua]
public delegate void delAddingMutiReturnRef(ref int res1, ref int res2, out int result);
//不含out和ref关键字不用加标签
public delegate void delAddings(int num1, int num2);
第二步在xlua的ExampleGenConfig配置文件注册委托类型
[CSharpCallLua]
public static List CSharpCallLua = new List()
{
typeof(Action),
typeof(Action),新加的
typeof(Func),新加的
typeof(Func),
typeof(Action),
typeof(Action),
typeof(UnityEngine.Events.UnityAction),
typeof(System.Collections.IEnumerator)
};
第三步在对应位置调用lua中函数。
public class CsharpCallLuaFunctionByDelegateMultReturn : MonoBehaviour
{
//lua环境(官方建议全局唯一)
LuaEnv env = null;
//委托声明
delAddingMutiReturnOut act1 = null;
delAddingMutiReturnRef act2 = null;
delAddings act3 = null;
private void Start()
{
env = new LuaEnv();
//不用加lua后缀
env.DoString("require 'CsharpCallLuaTable' ");
//得到lua中的具有多个返回数值的函数(通过委托out关键字来进行映射)
act1 = env.Global.Get("ProcMyFunc5");
//使用out
//输出返回结果
int intOutRes1 = 0;
int intOutRes2 = 0;
int intOutRes3 = 0;
act1.Invoke(100, 880, out intOutRes1, out intOutRes2, out intOutRes3);
Debug.Log(string.Format("使用out关键字测试多输出 res1={0},res2={1},res3={2}", intOutRes1, intOutRes2, intOutRes3));
//使用ref
act2 = env.Global.Get("ProcMyFunc5");
//输出返回结果
int intResult = 0;
int intNum1 = 30;
int intNum2 = 20;
act2.Invoke(ref intNum1,ref intNum2,out intResult);
Debug.Log(string.Format("使用ref关键字测试多输出 res1={0},res2={1},res3={2}", intNum1, intNum2, intResult));
act3 = env.Global.Get("ProcMyFunc2");
act3.Invoke(5000,500);
}
private void OnDestroy()
{
act1 = null;
act2 = null;
act3 = null;
//释放LuaEnv
env.Dispose();
}
}
使用Xlua自身带有的LuaFunction.
优点:无需生成代码。
缺点:性能不高,不推荐。
这种方式的优缺点刚好和第一种相反。使用也简单。LuaFunction上由个变参的Call函数,可以传任意类型,任意个数的参数,返回值是object的数组,对应于lua的多返回值。
public class CharpCallLuaFunctionByLuaFunction : MonoBehaviour
{
//lua环境(官方建议全局唯一)
LuaEnv env = null;
private void Start()
{
env = new LuaEnv();
//不用加lua后缀
env.DoString("require 'CsharpCallLuaTable' ");
//得到lua中的函数信息(通过LuaFunction来进行映射)
LuaFunction luaFun = env.Global.Get("ProcMyFunc1");
LuaFunction luaFun2 = env.Global.Get("ProcMyFunc2");
LuaFunction luaFun3 = env.Global.Get("ProcMyFunc3");
//调用具有多返回数值
LuaFunction luaFun4 = env.Global.Get("ProcMyFunc5");
//输出
luaFun.Call();
luaFun2.Call(10, 20);
object[] objArray = luaFun3.Call(30, 40);
Debug.Log("调用ProcMyFunc3,结果=" + objArray[0]);
object[] objArray2 = luaFun4.Call(22, 80);
Debug.Log(string.Format("测试多返回数值 res={0},res2={1},res3={2}",objArray2[0],objArray2[1],objArray2[2]));
}
private void OnDestroy()
{
//释放LuaEnv
env.Dispose();
}
}
lua调C#常见情况有(new)实例化,调用字段属性,方法,委托事件。
基本方法:使用CS开头,实例化类。
eg:
C#
UnityEngine.GameObject newGameObject=new UnityEngine.GameObject();
Lua
local newGameObject=CS.UnityEngine.GameObject()
基本规则:
A:Lua里头没有new关键字。
B:所有C#相关的都放到CS下,包括构造函数,静态成员属性,方法。
如果有多个构造函数呢?
xlua支持重载,比如你要调用GameObject的带一个string参数的构造函数,这么写:
local newGameObj2=CS.UnityEngine.GameObject('helloworld')
小技巧:
如果需要经常访问的类,可以先用局部变量引用后访问,除了减少敲代码的时间,还能提高性能。(即:lua写查找与得到组件等方式,推荐与C#中一样,尽量把查找与得到的组件进行缓存,节省系统开销。)
eg:
c#
using UnityEngine;
namespace XluaPro
{
public class LuaCallMyClass
{
private string name = "HER";
public int Count = 5;
public string str = "你好";
public string Name
{
get { return name; }
set { name = value; }
}
public LuaCallMyClass(int sum)
{
Debug.Log("执行了构造函数LuaCallMyClass传入了数值:" + sum);
}
public void MyMethod()
{
this.Name = "gaimingle";
Debug.Log("执行了LuaCallMyClass中的MyMethod方法");
}
public static void StaticMyMethod()
{
Debug.Log("执行了LuaCallMyClass中的StaticMyMethod方法");
}
}
}
Lua
local LuaCallMyClass= CS.XluaPro.LuaCallMyClass
local classObj=LuaCallMyClass(100) --自动调用父类与子类的构造函数
local count= classObj.Count
local str=classObj.str
classObj:MyMethod()
classObj.MyMethod(classObj)
local name=classObj.Name
LuaCallMyClass.StaticMyMethod()
print("取得了c#中类的值count="..count.." str="..str.."name="..name)
注意:
1.Lua中调用函数有两种方式:点和冒号。
冒号是一个语法糖,冒号(:)调用函数时,会默认将调用者自身作为第一个参数。 classObj:MyMethod()和classObj.MyMethod(classObj)是一样的。
3.什么时候用冒号,什么时候用点:
当调用实例化类函数使用冒号,那为什么调用c#实例化类函数要将自身传递进去?这个我的解释是C#实例化类函数方法内都可以使用this关键字。当你在lua中调用实例化类这个函数方法的时候,系统不知道你到底用没用this关键字,万一你用了,lua这边没把自身的值给this,那边this就会报空引用异常,所以不管你用没用,系统强制都把自身作为参数给传进去避免出错。静态方法内不能使用this关键字。
我这个强行解释怎么样?当然以后自身姿势水平越来越高的时候,能给一个更高大上的解释。总之,调用非静态函数要用冒号,表现在代码层面就是这个函数方法内部可以使用this。
调用方法上面不是说明了吗,这里怎么还有?因为C#中的方法花样五花八门,委托事件其实也算在其中。这里我们把它们一一列举出来。
xlua支持(通过派生类)访问基类的静态属性,静态方法,(通过派生类实例)访问基类的成员属性,成员方法。
using UnityEngine;
namespace XluaPro
{
public class LuaCallCsharpClassFather
{
public string FatherName = "LuaCallCsharpClassFather";
public LuaCallCsharpClassFather()
{
Debug.Log("这是父类的构造函数");
}
public void MyFatherClass()
{
Debug.Log("这是父类的函数LuaCallCsharpClassFather.MyFatherClass");
}
}
public class LuaCallMyClass:LuaCallCsharpClassFather
{
private string name = "HER";
public int Count = 5;
public string str = "你好";
public string Name
{
get { return name; }
set { name = value; }
}
public LuaCallMyClass(int sum)
{
Debug.Log("执行了构造函数LuaCallMyClass传入了数值:" + sum);
}
public void MyMethod()
{
this.Name = "gaimingle";
Debug.Log("执行了LuaCallMyClass中的MyMethod方法");
}
public static void StaticMyMethod()
{
Debug.Log("执行了LuaCallMyClass中的StaticMyMethod方法");
}
}
}
Lua
local LuaCallMyClass= CS.XluaPro.LuaCallMyClass
local classObj=LuaCallMyClass(100) --自动调用父类与子类的构造函数
classObj:MyFatherClass()--调用父类的方法
print("父类的字符串FatherName="..classObj.FatherName)--调用父类的字段
xlua支持方法的重载,但为"有限重载".直接通过不同的参数类型进行重载参数的访问。
xlua只一定程度上支持重载函数的调用,因为lua的类型远远不如C#丰富,存在一对多的情况。比如C#int,float,double都对应于lua的number。所以如果重载类型是int和float则无法区分,只能调用到其中一个(生成代码中排前面的那个)
eg:
using UnityEngine;
namespace XluaPro
{
public class LuaCallMyClass:LuaCallCsharpClassFather
{
private string name = "HER";
public int Count = 5;
public string str = "你好";
public string Name
{
get { return name; }
set { name = value; }
}
public LuaCallMyClass(int sum)
{
Debug.Log("执行了构造函数LuaCallMyClass传入了数值:" + sum);
}
public void MyMethod()
{
this.Name = "gaimingle";
Debug.Log("执行了LuaCallMyClass中的MyMethod方法");
}
public static void StaticMyMethod()
{
Debug.Log("执行了LuaCallMyClass中的StaticMyMethod方法");
}
public void OverLoadMehtod(int a,int b)
{
Debug.Log("执行了OverLoadMehtod(int类型)方法");
}
public void OverLoadMehtod(float a, float b)
{
Debug.Log("执行了OverLoadMehtod(浮点类型)方法");
}
public void OverLoadMehtod(string a, string b)
{
Debug.Log("执行了OverLoadMehtod(字符串)方法");
}
}
}
Lua
local LuaCallMyClass= CS.XluaPro.LuaCallMyClass
local classObj=LuaCallMyClass(100) --自动调用父类与子类的构造函数
classObj:OverLoadMehtod(60.9,70.9) --lua无法区分整型和浮点型,哪个写在前面执行哪个,这里执行的是整型函数
classObj:OverLoadMehtod(60,70)
classObj:OverLoadMehtod("aaa","BBB")
各种奇怪的参数一起来吧。
C#
//可变参数
public void MyMethodParams(int a, int b, params string[] strArrary)
{
Debug.Log("a="+a+"b="+b+ string.Join("", strArrary));
}
Lua
local LuaCallMyClass= CS.XluaPro.LuaCallMyClass
local classObj=LuaCallMyClass(100)
classObj:MyMethodParams(20,30,"ABC","EFG","HIGK")
Lua使用一个表,来映射C#的结构体
public struct MyStruct
{
public string x;
public string y;
}
public void MyMethodStruct(MyStruct myStruct)
{
Debug.Log("myStruct.x="+myStruct.x+ " myStruct.y="+myStruct.y);
}
Lua
local LuaCallMyClass= CS.XluaPro.LuaCallMyClass
local classObj=LuaCallMyClass(100)
mystruct=
{
x="abc",
y="efg"
}
classObj:MyMethodStruct(mystruct)
lua使用一个表,来映射c#的接口。
注意:接口需要加入标记:[CSharpCallLua]
C#
//定义接口
[XLua.CSharpCallLua]
public interface MyInterFace
{
int x { get; set; }
int y { get; set; }
public void Speak();
}
public void MyInterFaceMethod(MyInterFace myInterface)
{
Debug.Log("MyInterFace.x="+myInterface.x+ " MyInterFace.y="+ myInterface.y);
myInterface.Speak();
}
Lua
local LuaCallMyClass= CS.XluaPro.LuaCallMyClass
local classObj=LuaCallMyClass(100)
--用于映射接口的表
myInterface=
{
x=100,
y=200,
Speak=function()
print("执行了myInterface里面的Speak方法");
end
}
--执行该方法
classObj:MyInterFaceMethod(myInterface)
lua使用一个函数,来映射C#的委托。
委托需要加入标记[CSharpCallLua] 这里不管你有没有带ref,out关键字都要加
eg:
C#
[XLua.CSharpCallLua]
public delegate void MyDelegate(int num);
public void MyDelegateMethod(MyDelegate mydelegate)
{
mydelegate.Invoke(99);
}
Lua
local LuaCallMyClass= CS.XluaPro.LuaCallMyClass
local classObj=LuaCallMyClass(100)
myDelegate=function(num)
num=num+100
print("执行了myDelegate方法,并且num的值为"..num)
end
classObj:MyDelegateMethod(myDelegate)
基本规则:参数的输入输出属性(out,ref)
A:C#的普通参数算一个输入形参,ref修饰的算一个输入形参,out不算,然后从左往右对应lua调用的实参列表。
B:Lua调用返回值处理规则:
C#函数的返回值(如果有的话)算一个返回值,out算一个返回值,ref算一个返回值,然后从左往右对应lua的多返回值。
C#
public int MultReutrnMehtod(ref int a,out int b,ref int c,int d,out int e)
{
b =20;
e = 50;
return a + b + c + d + e;
}
Lua
local LuaCallMyClass= CS.XluaPro.LuaCallMyClass
local classObj=LuaCallMyClass(100)
returnResult,a,b,c,e= classObj:MultReutrnMehtod(10,30,40)
print("a="..a.." b="..b.." c="..c.." e="..e.." returnResult="..returnResult)
注意:执行结果返回值是第一个,然后依据out,ref按顺序得到多返回值。
lua中的参数个数从左到右out忽略,上面例子在lua中实际上只有三个参数。
基本规则:
lua不直接支持C#的泛型方法,但可以通过扩展方法功能进行封装后调用。
使用Extension methods(扩展方法)技术就是C#中在不改变原始类的基础上,使用一种机制可以无限扩展这个类功能的机制。
Eg:原始类为:A 扩展类为:Ext_A
注意事项:
A:Ext_A 必须是一个静态类,且扩展方法也必须是静态的。方法的参数中必须要有被扩展类作为其中一个参数,此参数前面必须有this关键字修饰。
B:lua直接调用扩展方法,需要给"泛型类"与"扩展方法类",都加入特性标记:[xlua.LuaCallCSharp]
这里我有个疑问,我在C#中定义一个委托字段,然后在Lua中给这个委托字段添加委托链,并且在lua执行这个委托链。我自己试了下不行。可能是我的写法有问题。这里我在C#单独写一个添加方法的方法函数和一个执行的方法函数。
eg:
C#
//定义委托
[XLua.CSharpCallLua]
public delegate void MyDelegatestr(string str);
public MyDelegatestr mydelegateMehods;
public void AddAction(MyDelegatestr action)
{
this.mydelegateMehods += action;
}
public void InvokemydelegateMehods()
{
mydelegateMehods.Invoke("我来测试来了");
}
Lua
--委托链方法一
myDelegate1=function(num)
print("执行了方法myDelegate1"..num)
end
--方法二
myDelegate2=function(num)
print("执行了方法myDelegate2"..num)
end
--方法三
myDelegate3=function(num)
print("执行了方法myDelegate3"..num)
end
local LuaCallMyClass= CS.XluaPro.LuaCallMyClass
local classObj=LuaCallMyClass(100)
--使用LuaCallMyClass类的对象访问委托变量action
classObj:AddAction(myDelegate1)
classObj:AddAction(myDelegate2)
classObj:AddAction(myDelegate3)
--执行委托链
classObj:InvokemydelegateMehods()
事件就是加个关键字,只能在外部绑定,不能在外部执行。没啥可说的。这个以后发现了解决办法会回来更新
1:lua调用C#,需要在Xlua中生成"适配代码"。则在这个类打入一个[LuaCallCsharp]的标签。
2.如果lua调用C#的系统API,则无法拿到源代码,无法打入标签。则使用"静态列表"方式解决。
eg:
Public static List mymodule_LuaCallCS_List=new List()
{
typeof(GameObject),
typeof(Dictionary
};
然后把以上代码放入一个静态类中即可。
3.实际开发过程中,lua调用C#用的比较多。
xlua的优点体现的没有必要每次改的时候,都要生成代码。主要原理是依赖于编译器环境下,
利用反射来动态生成代码接口。
4:在标有"[XLua.LuaCallCsharp]"的C#类中,添加新的方法后,如果是生成了代码类,则必须重新生成或者删除,否则XLua用以前生成的,进行注册查询,会出现Lua异常:“视图访问一个nil的方法”
还有很多问题,先整理到这里,慢慢来。