之前一直在纠结项目的某些运营界面使用全Lua来写,这样可以热更新上线不同的活动,而不需要上架不同的版本,虽然可以通过资源更新加载xml的方式来实现,但是要通过xml来组合一些新的活动逻辑会很困难.
然后听了很多朋友最近都在推荐xlua, 不但可以做纯lua的逻辑更新,还可以做 C# 代码的bug hotfix.
就是可以在保持项目使用C#逻辑开发的前提下,出现bug后使用lua来修复.听起来很棒棒.
github地址 : xlua
试用一下之后,发现xlua的hotfix原理也很简单, 就是通过反射取出打上了 [hotfix] 标记的类,
然后对需要fix的函数执行下列伪代码
1 2 3 4 5 6 7 | void Start() { if(_hotfix) _lua_add(a,b); else _csharp_add(a,b); } |
那么思路就来了.
设定一个全局 hotfix管理类, 在游戏初始化的时候拉取服务器的 hotfix 版本号, 看看服务器上是否有新的补丁需要下载, 如果有,将补丁存到本地. 之后加载 补丁, 打补丁. 最后进入游戏.
正好以前自己写过好几个lua项目比如 : PrompaLua, lua还没忘记..正好用上 哈哈
首先是一个范例:
一个有bug的类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | 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 () { } } |
错误有 A,B 没有初始化
Add函数被写成了减法
好在类的开头被打上了 [Hotfix] 标记,让我们有机会热修复他.
然后是HotFix类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | 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>(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() { } } |
他会在游戏启动的时候去下载 http://www.dreamfairy.cn/xlua/test/version.txt 版本号数据
之后去补丁地址下载补丁文件 http://www.dreamfairy.cn/xlua/test/hotfix.lua
下载完毕后,缓存到本地, 然后调用游戏启动 StartUp
启动游戏后, 原本控制台输出 0 的结构, 热更新后 控制台输出 600
最后是lua部分的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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 ) |
lua部分的代码,就3段 第一段 xlua.private_accessible(CS.FuckYouSelf)
让lua可以访问私有字段, 目的是为了改成员变量 A,B 他们是私有的
第二段是修改 类中的 Init函数, 来初始化A,B
第三段是修改 类中的 Add函数,让他正确执行加法