Xlua学习笔记(Lua调用C#及踩坑)
XLua是目前国内使用较多的热更新框架(可能是有腾讯加持), Xlua同时也提供了Lua调用C#的能力,其实Lua调用C#的场景更多,要想实现热更新,很多控制逻辑都得写在Lua里,这篇文章主要是记录了Lua如何调用C#,以及踩过的一些坑。
在Lua中new C#对象
例如创建GameObject
print("Lua call C# start...")
CS.UnityEngine.GameObject()
-- 指定GameObject的名称
CS.UnityEngine.GameObject("NewByLua")
Lua访问静态属性、静态方法
记得最好设置本地Local变量,提高性能
创建对象:
local newGo = CS.UnityEngine.GameObject();
local newGo = CS.UnityEngine.GameObject('name')
访问静态属性:
CS.UnityEngine.Time.deltaTime
CS.UnityEngine.Time.timeScale = 0.5
访问静态方法:
CS.UnityEngine.GameObject.Find('name')
小技巧:如果有一些需要经常访问的类,可以用局部变量引用后,通过局部变量进行访问,可以提高性能
local GameObject = CS.UnityEngine.GameObject
GameObject.Find('name')
Lua中访问C#成员变量和方法
访问成员属性:.
运算符
local camera = CS.UnityEngine.GameObject.Find("Main Camera")
camera.name = "newName";
访问成员方法:.
运算符或 :
语法糖
local cameraComponent = camera.GetComponent(camera, "Camera")
local cameraComponent = camera:GetComponent("Camera")
注意:在Lua中没有this关键字,所以如果使用 .
,则需要在方法中手动传递对象本身;如果使用:
则不需要
带有结构体的参数的方法
在lua端定义一个表去映射结构体:
public struct MyStruct
{
public string x;
public string y;
}
public void CSharpFunc(MyStruct p)
{
Debug.Log(p.x);
Debug.Log(p.y);
}
--lua
myStructTable={x="C#",y="lua"}
obj:CSharpFunc(myStructTable)
调用C#泛型方法
lua中不支持C#的泛型方法,但可以使用扩展方法来调用
public void GenericMethod<T>()
{
Debug.Log("GenericMethod<" + typeof(T) + ">");
}
[LuaCallCSharp]
public static class DerivedClassExtensions
{
public static int GetSomeData(this DerivedClass obj)
{
Debug.Log("GetSomeData ret = " + obj.DMF);
return obj.DMF;
}
public static int GetSomeBaseData(this BaseClass obj)
{
Debug.Log("GetSomeBaseData ret = " + obj.BMF);
return obj.BMF;
}
public static void GenericMethodOfString(this DerivedClass obj)
{
obj.GenericMethod<string>();
}
}
print(testobj:GetSomeData())
print(testobj:GetSomeBaseData()) --访问基类的Extension methods
testobj:GenericMethodOfString() --通过Extension methods实现访问泛化方法
Lua访问C#的其他注意事项:
Lua调用C#,需要在Xlua中生成"适配代码",则在这个类打入一个[LuaCallCsharp]的标签。
实际开发过程中,lua调用C#用的比较多。
在标有[XLua.LuaCallCsharp]
的C#类中,添加新的方法后,如果是生成了代码类,则必须重新生成或者删除,否则XLua用以前生成的,进行注册查询,会出现Lua异常
Lua语言踩坑
这部分内容是7.27 号补充
1、Lua中的nil和C#中的null不能同等比较!
之前遇到个BUG,偶现报空指针,原来才发现Lua中的nil和C#中的null不能同等比较。Lua中依旧存在引用关系,但是C# 里这个对象已经被销毁了,根据原有的业务逻辑,所以需要两次判空才可以。
基于这种状况有两种解决方式:
第一种就是双重判断,obj==nil or obj:Equals(nil)
function IsNull( obj )
if obj==nil or obj:Equals(nil) then
return true;
end
return false;
end
第二种就是C#提供判空方法:
[XLua.LuaCallCSharp]
public static class MyObj
{
/// <summary>
/// 扩展一个Object判空的方法,主要是给lua使用,lua没法用nil和null进行比较
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public static bool IsNull(this Object obj)
{
return obj == null;
}
}
2、Lua数组索引从1开始;
3、if not xx
与 if ~ xxx
C:\Users\15291>lua
Lua 5.1.5 Copyright (C) 1994-2012 Lua.org, PUC-Rio
> a = false
> b = true
> print((a and b))
false
> print((a or b))
true
> if not (nil and a) then print("xx") end
xx
> if not nil and a then print("xx") end
>
>