基本操作
MyLua.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;
public class MyLua : MonoBehaviour
{
//Lua代码,模拟lua调用c#
private string luaScript = @"
-- Lua调用C#时,需要在C#的命名空间之前加入前缀CS
local GameObject = CS.UnityEngine.GameObject --获取C#中的类
local Debug = CS.UnityEngine.Debug --获取C#中的方法
local web = GameObject('baidu')
Debug.Log(web.name)
local myCamera = GameObject.Find('Main Camera')
Debug.Log(myCamera.name)
";
void Start()
{
//创建Xlua虚拟机,全局有且只有一个
LuaEnv luaEnv = new LuaEnv();
//C#代码内执行Lua代码,不常用
luaEnv.DoString("print('helloworld')");
//C#调用外部的Lua代码文件
//执行在resource文件夹中的lua文件,只支持txt bytes等
//因为不能识别.lua文件,因此脚本名需要为test.lua.txt
luaEnv.DoString("require 'test'");
//C#获取Lua代码中的数据
//调用数值
int a = luaEnv.Global.Get<int>("a");
//调用字符串
string b = luaEnv.Global.Get<string>("b");
//调用布尔变量
bool c = luaEnv.Global.Get<bool>("c");
//调用函数
LuaFunction d = luaEnv.Global.Get<LuaFunction>("d");
Debug.Log(a);
Debug.Log(b);
Debug.Log(c);
//执行函数
d.Call();
//Lua调用C#
luaEnv.DoString(luaScript);
}
}
test.lua.txt
print('hello world')
a=123
b='test'
c=false
function d()
print('ddd')
end
HotFix热补丁
环境初始化步骤
- 增加宏信息:File->BuildSetting->PlayerSetting->Player->Configuration->ScriptingDefineSymbols:HOTFIX_ENABLE
- 执行菜单生成命令:Xlua->GenerateCode,会生成一大堆Wrap文件,存放到Xlua/Gen文件夹下
- 执行菜单注入命令:Xlua->HotfixInjectInEditor,成功之后会在控制台输出成功消息,若失败注意要将Tools放到与Assets同级目录
热补丁演示
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;
//需要添加Hotfix标签,表示该类可以被热修复
[Hotfix]
public class MyHotfix : MonoBehaviour
{
private LuaEnv luaEnv;
private string luaHotScript = @"
xlua.hotfix(CS.MyHotfix, 'Hello', function()
print('Lua Hello')
end)
xlua.hotfix(CS.MyHotfix, 'Add', function(self, a, b)
print('Lua ' .. a+b)
end)
";
void Start()
{
luaEnv = new LuaEnv();
}
private void Hello()
{
Debug.Log("C# Hello");
}
private void Add(int a,int b)
{
Debug.Log("C# " + (a + b));
}
void Update()
{
//直接按A执行的是C#代码,按空格后再按A执行的是lua热修复代码
if (Input.GetKeyDown(KeyCode.A))
{
Hello();
Add(10, 5);
}
if (Input.GetKeyDown(KeyCode.Space))
{
luaEnv.DoString(luaHotScript);
}
}
}
注意:
- 每次修改完C#都要执行一次注入命令
- 有参方法修复时,需要传递当前脚本对象this,在lua中用self代替
加载外部文件热修复
MyHotfix2.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;
//需要添加Hotfix标签,表示该类可以被热修复
[Hotfix]
public class MyHotfix2 : MonoBehaviour
{
private void Hello()
{
Debug.Log("C# Hello");
}
private void Add(int a, int b)
{
Debug.Log("C# " + (a + b));
}
void Update()
{
if (Input.GetKeyDown(KeyCode.A))
{
Hello();
Add(10, 5);
}
}
}
HotfixManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;
public class HotfixManager : MonoBehaviour
{
private LuaEnv luaEnv;
void Awake()
{
luaEnv = new LuaEnv();
luaEnv.DoString("require 'luaFix'");
}
}
luaFix.lua.txt
xlua.hotfix(CS.MyHotfix2, 'Add', function(self, a, b)
print('Lua ' .. a+b)
end)
print('over')
有参游戏逻辑修复
HotfixManager代码不变
CreateWall.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;
/// <summary>
/// 无参 公开字段
/// </summary>
[Hotfix]
public class CreateWall : MonoBehaviour
{
public GameObject cube;
private void CreateCubeWall(GameObject prefab)
{
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
Instantiate(prefab, new Vector3(i, j, 0), Quaternion.identity);
}
}
}
void Start()
{
CreateCubeWall(cube);
}
}
luaFix.lua.txt
local GameObject = CS.UnityEngine.GameObject
local Vector3 = CS.UnityEngine.Vector3
local Quaternion = CS.UnityEngine.Quaternion
xlua.hotfix(CS.CreateWall, 'CreateCubeWall', function (self, prefab)
for i=1,3,1 do
for j=1,3,1 do
GameObject.Instantiate(prefab, Vector3(i, j, 0), Quaternion.identity);
end
end
end)
print('over')
无参游戏物体逻辑修复
两种解决方式
- 方法1:可以在lua代码内通过“self.字段名“进行访问,前提是该字段必须是public修饰的,可能会破坏C#语言的”封装性“
- 方法2:在lua语言中,使用代码获取C#类中private对象的访问权:xlua.private_accessible(CS.类名)就可以在lua脚本中访问到C#类中的私有成员,同时不会破坏C#语言的”封装性“和逻辑关系
CreateWall.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;
/// <summary>
/// 无参 公开字段
/// </summary>
[Hotfix]
public class CreateWall2 : MonoBehaviour
{
public GameObject cube;
private void CreateCubeWall()
{
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
Instantiate(cube, new Vector3(i, j, 0), Quaternion.identity);
}
}
}
void Start()
{
CreateCubeWall();
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;
/// <summary>
/// 无参 私有字段
/// </summary>
[Hotfix]
public class CreateWall3 : MonoBehaviour
{
private GameObject cube;
private void CreateCubeWall()
{
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
Instantiate(cube, new Vector3(i, j, 0), Quaternion.identity);
}
}
}
void Start()
{
cube = Resources.Load<GameObject>("Cube");
CreateCubeWall();
}
luaFix.lua.txt
--方法1
xlua.hotfix(CS.CreateWall2, 'CreateCubeWall', function (self)
for i=1,3,1 do
for j=1,3,1 do
GameObject.Instantiate(self.cube, Vector3(i, j, 0), Quaternion.identity);
end
end
end)
--方法2
xlua.private_accessible(CS.CreateWall3)
xlua.hotfix(CS.CreateWall3, 'CreateCubeWall', function (self)
for i=1,3,1 do
for j=1,3,1 do
GameObject.Instantiate(self.cube, Vector3(i, j, 0), Quaternion.identity);
end
end
end)
print('over')