C#调用Lua代码
LuaEnv luaenv = new LuaEnv();
luaenv.DoString("print('000')");
luaenv.Dispose();
在C#中使用Lua文件代码控制游戏物体,以及事件监听
这是一个稍微复杂的案例
首先我们需要一个LuaEnv,它用于将C#于lua进行交互,在整个项目中只存在一个LuaEnv
LuaTable创建一个直接进行操作的表
最后创建一个基于上面table的元表进行具体操作,原因应该是将数据与具体操作分开吗?
C#代码
public GameObject cube;
public TextAsset testAsset;
internal static LuaEnv luaEnv = new LuaEnv();
private Action luaStart;
private Action luaUpdate;
private Action luaOnDestroy;
private LuaTable scriptEnv;
void Start () {
scriptEnv = luaEnv.NewTable(); //创建一个新的表
LuaTable mat = luaEnv.NewTable();
SetMatTable(luaEnv, scriptEnv, mat);
//设置数据给lua接收
scriptEnv.Set("self", this); //将自身设置给self,这样就可以让lua文件拿到self
scriptEnv.Set("cube", cube); //将对象名和对象传给lua
luaEnv.DoString(testAsset.text, "MyCStoLua", scriptEnv); //传入lua代码
Action luaAwake = scriptEnv.Get<Action>("awake");
scriptEnv.Get("start", out luaStart); //抽取lua的start方法
scriptEnv.Get("update", out luaUpdate); //抽取lua的update方法
scriptEnv.Get("ondestroy", out luaOnDestroy); //抽取lua的ondestroy方法
if (luaAwake != null)
{
luaAwake(); //执行lua的awake
}
luaStart();
}
public void SetMatTable(LuaEnv luaEvent , LuaTable controller,LuaTable matTable)
{
matTable.Set("__index", luaEvent.Global); //将自身设置为,,,,
controller.SetMetaTable(matTable); //将meta设为scriptEnv元表
matTable.Dispose();
}
// Update is called once per frame
void Update () {
luaUpdate();
}
#Lua代码
local function awake()
end
function start()
print("拿到了盒子"..cube.name)
end
function update()
print("执行脚本====")
local transform = self.cube:GetComponent(typeof(CS.UnityEngine.Transform)) --访问self的全局变量
transform:Translate(CS.UnityEngine.Vector3.one*CS.UnityEngine.Time.deltaTime)
end
自定义加载lua文件
void Start () {
LuaEnv luaEnv = new LuaEnv();
luaEnv.AddLoader(Loader); //设置加载器
luaEnv.DoString("require 'LuaController'", "InputEvent", scriptEnv); //传入lua代码
}
public byte[] Loader(ref string filePath)
{
string path = Application.streamingAssetsPath + "/" + filePath + ".lua.txt"; //指定加载文件路径
return System.Text.Encoding.UTF8.GetBytes(File.ReadAllText(path)); //文件内容转字节数组
}
热更新案例
首先我们需要在PlayerSetting>>OtherSetting>>Scripting Define Symbols中增加HOTFIX_ENABLE参数
编写热更代码后,点击菜单的XLua/Hotfix Inject In Editor打印了“hotfix inject finish!”或者“had injected!”即为成功驻入
[Hotfix]
public class MyHotFix : MonoBehaviour {
private float timer = 0;
public float max = 1;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
timer += Time.deltaTime;
if (timer >= max)
{
timer = 0;
Debug.Log("C#输出代码");
}
}
public void Click()
{
LuaEnv luaenv = new LuaEnv();
luaenv.DoString(@"
xlua.hotfix(CS.MyHotFix,'Update',function(self)
self.timer =self.timer + CS.UnityEngine.Time.deltaTime;
if (self.timer >= self.max)then
self.timer = 0;
print('Lua输出代码');
end
end)
");
}
}
注意:需要被热更的代码必须要在类名上加上[Hotfix],一定要记得改变了代码要注入,否则会报错
说下实现结果:
我们再Update中输出了:C#输出代码
当通过按钮点击调用Click的时候会调用lua代码,而此处调用了xlua.hotfix(命名空间.类名,方法名,替换的方法(self))
self就是C#代码自身我们可以通过self获取到C#代码的变量,包括私有变量,如案例中的timer和max
关于这个有什么用,我曹兄弟,这个可以给代码进行热更修复,当已上线APP发现C#中含有致命Bug,通过热更新Lua即可修复,真的非常好用
热更新案例补充
在类上面加上[Hotfix]的方式是非常不建议的,此做法会导致代码非常的混乱,你不能一眼看出哪些代码加入了[Hotfix]
Xlua官方建议在一个static类的static字段或者属性里头配置一个列表。属性可以用于实现的比较复杂的配置,比如根据Namespace做白名单。
实现代码:
public static class HotFixManager {
[Hotfix]
public static List<Type> UIHotFixList = new List<Type>()
{
typeof(MyHotFix),
};
}
其他就不多写了,步骤跟上面一致