之前一直在纠结项目的某些运营界面使用全Lua来写,这样可以热更新上线不同的活动,而不需要上架不同的版本,虽然可以通过资源更新加载xml的方式来实现,但是要通过xml来组合一些新的活动逻辑会很困难.

然后听了很多朋友最近都在推荐xlua, 不但可以做纯lua的逻辑更新,还可以做 C# 代码的bug hotfix.
就是可以在保持项目使用C#逻辑开发的前提下,出现bug后使用lua来修复.听起来很棒棒.

github地址 : xlua

试用一下之后,发现xlua的hotfix原理也很简单, 就是通过反射取出打上了 [hotfix] 标记的类,
然后对需要fix的函数执行下列伪代码
[cc lang=”C++”]
void Start()
{
if(_hotfix)
_lua_add(a,b);
else
_csharp_add(a,b);
}[/cc]

那么思路就来了.
设定一个全局 hotfix管理类, 在游戏初始化的时候拉取服务器的 hotfix 版本号, 看看服务器上是否有新的补丁需要下载, 如果有,将补丁存到本地. 之后加载 补丁, 打补丁. 最后进入游戏.

正好以前自己写过好几个lua项目比如 : PrompaLua, lua还没忘记..正好用上 哈哈

首先是一个范例:
一个有bug的类
[cc lang=”C++”]
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;

[Hotfix]
public class FuckYouSelf : MonoBehaviour {

private int A;
private int B;

void Init() {

}
// Use this for initialization
void Start () {
Init();
UnityEngine.Debug.Log(Add(A, B));
}

int Add(int a, int b) {
return a – b;
}

// Update is called once per frame
void Update () {

}
}
[/cc]
错误有 A,B 没有初始化
Add函数被写成了减法

好在类的开头被打上了 [Hotfix] 标记,让我们有机会热修复他.

然后是HotFix类
[cc lang=”C++”]
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;

public class HotFix : MonoBehaviour {

public GameObject StartUp;

[Serializable]
struct VersionData {
public string Version;
public string FixUrl;
}

LuaEnv luaevn = new LuaEnv();
// Use this for initialization
void Awake () {

StartCoroutine(LoadVersion(“http://www.dreamfairy.cn/xlua/test/version.txt”));
}

IEnumerator LoadVersion(string versionUrl) {
WWW versionData = new WWW(versionUrl);

yield return versionData;

if(null != versionData.error) {
Debug.LogError(versionData.error);
} else {
VersionData data = JsonUtility.FromJson(versionData.text);
StartCoroutine(LoadFix(data.FixUrl, data.Version));
}
}

IEnumerator LoadFix(string fixUrl, string version) {

//todo: check storage hotfix version

WWW fixData = new WWW(fixUrl);

yield return fixData;

if (null != fixData.error) {
Debug.LogError(fixData.error);
} else {
ApplyHotFix(fixData.text);
SaveToStorage(fixData.text, version);
}
}

void ApplyHotFix(string luastr) {
luaevn.DoString(luastr);

if(null != StartUp) {
StartUp.SetActive(true);
}
}

void SaveToStorage(string luastr, string version) {
//todo
}

private void OnDestroy() {

}
}
[/cc]

他会在游戏启动的时候去下载 http://www.dreamfairy.cn/xlua/test/version.txt 版本号数据
之后去补丁地址下载补丁文件 http://www.dreamfairy.cn/xlua/test/hotfix.lua

下载完毕后,缓存到本地, 然后调用游戏启动 StartUp

启动游戏后, 原本控制台输出 0 的结构, 热更新后 控制台输出 600

最后是lua部分的代码
[cc lang=”lua”]
xlua.private_accessible(CS.FuckYouSelf)

xlua.hotfix(CS.FuckYouSelf, ‘Init’,
function(self)
self.A = 300
self.B = 300
end
)

xlua.hotfix(CS.FuckYouSelf, ‘Add’,
function(self, a, b)
return a + b
end
)
[/cc]

lua部分的代码,就3段 第一段 xlua.private_accessible(CS.FuckYouSelf)
让lua可以访问私有字段, 目的是为了改成员变量 A,B 他们是私有的

第二段是修改 类中的 Init函数, 来初始化A,B

第三段是修改 类中的 Add函数,让他正确执行加法