使用Xlua可以用lua语言覆盖CS脚本的内容。
这里贴出官方的热更新教程~
https://github.com/Tencent/xLua/blob/master/Assets/XLua/Doc/hotfix.md
然后以下是本文大致的实现步骤:
1. 这里使用AB包把需要修改的物体对象资源、要覆盖CS脚本的lua文件打包
2. 客户端从服务器下载ab包,然后把新ab包缓存在本地,直到服务器下一次更新ab包
3. 然后客户端用以前写好的CS脚本来从ab包获取lua文本,放到本地沙盒路径,然后再执行lua文本内容
4. lua文本里可以继续从ab包缓存里获取其他资源,并对原CS脚本进行覆盖来修改bug
准备阶段,也就是正常的用C#编码阶段,也可以说是作预处理阶段,发布游戏之前,下次客户端更新之前。
设置HotFix
设置[LuaCallSharp]
1. 在需要更新的类上加上[Hotfix] ,这个类需要提前预判,一般来说只更新UI部分,一般不更新物体,数据类
2. 在可能更新的类方法中前[LuaCallCsharp]
如:
[Hotfix]
public class BeHotFixA : MonoBehaviour {
public int num1 = 100;
private int num2 = 200;
[LuaCallCSharp]
void Update () {
if (Input.GetMouseButtonDown (0)) {
GameObject go = Resources.Load ("ObjA") as GameObject;
Instantiate (go);
}
}
}
注意:这里第三步骤的脚本也是发布游戏之前写好的脚本
现在就进入处理阶段了,此时出现bug,需要做热更新了
如下就是要替代C#的Lua代码,通过xlua.hotfix()方法
--第二次开发-》开始使用lua更新原工程内容
--BeHotFixA类的私有成员可以被访问
xlua.private_accessible(CS.BeHotFixA)
--替换CS中某个类的某个方法
xlua.hotfix(CS.BeHotFixA,"Update",function(self)
print(num1,num2)
local cs = CS.UnityEngine
if cs.Input.GetMouseButtonDown(0) then
local ab = cs.GameObject.Find("GameObject"):GetComponent("DownLoadAB").ab
local obj = ab:LoadAsset("ObjB")
local go = cs.GameObject.Instantiate(obj)
end
end)
当发生bug,就需要把替代C#的lua文件,要更改的UI、材质等资源
做成AssetBundle包
第三步应该是提前准备阶段就做好的,因为这里是在本机测试,实际放到服务器,直接更改路径即可
public class DownLoadABB : MonoBehaviour {
private string path = "file:///Users/neworigin/Desktop/YoungAB/ab";
public AssetBundle ab;
void Awake(){
WWW www = WWW.LoadFromCacheOrDownload (path, 11);//三
ab = www.assetBundle;//四
TextAsset hot = ab.LoadAsset ("hot.lua.txt") as TextAsset;
Debug.Log (hot.text);//五
string newPath = Application.persistentDataPath + "/hot.lua.txt";
Debug.Log (newPath);
//把AB里面的Hot脚本内容写入到沙盒路文件中
File.WriteAllText(newPath,hot.text);//五、六
}
使用WWW 下载AB包,然后获取ab包的资源(lua)和其他要覆盖资源
执行游戏时,会默认调用原先做好的CS脚本,此时客户端就会从服务器获取文件,需要进行测试
此CS脚本需要在发布游戏前写好,做预处理。当出现问题时,就可以从(这里是沙盒路径)本地路径
找到lua来执行。 这里的lua就是重新从服务器下载好的lua文本
public class HotFix : MonoBehaviour {
void Awake(){
LuaBehaviour.luaEnv.AddLoader (MyLoader);
LuaBehaviour.luaEnv.DoString ("require 'hot'");
}
public byte[] MyLoader(ref string filepath) {
string path = Application.persistentDataPath + "/" + filepath + ".lua.txt";
string str = File.ReadAllText (path);
return System.Text.Encoding.UTF8.GetBytes (str);
}
}
另外补充下对AddLoader 和 MyLoader 的理解
AddLoader()参数是方法名,这个方法的类型是被定义好的委托类型,
filepath是DoString下的require ‘hot’ 的 hot 名
此时就根据hot名配合沙盒路径找到那个lua文件
lua文件被流读出来,用字符串的形式读出,最后返回出来全部内容 被DoString() 全部执行
DoString(“print(‘如这样的形式’)”)
就是执行Xlua的Dostring,来执行新写好的lua文本内容
LuaBehaviour.luaEnv.DoString ("require 'hot'");
以上就热更新完成了,当下一次版本发布时,就把原来的lua文件覆盖的CS的bug重构修复即可
每次Build 新的ab包后,服务器加载也要更新,因为有缓存,要设置新版本号来提示客户端重新下载
如:WWW www = WWW.LoadFromCacheOrDownload (path, 11)
且版本号要从小到大加的。
每次CS脚本更新之后,就要重新生成GenerateXlua一下,然后点Hotfix injext in Enditor一下。才能播放测试。
Lua文本因为没有IDE提示,很容易写错(字符错误),建议在之前先用Resource.Load直接获取Lua文本(不build ab包,不从服务器下载) 直接获取lua内容来进行测试,直到lua文本不报错再换回来。