使用xlua 进行Unity3D 热更新

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 版本号, 看看服务器上是否有新的补丁需要下载, 如果有,将补丁存到本地. 之后加载 补丁, 打补丁. 最后进入游戏.

首先是一个范例:
一个有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 .=  300
    self .=  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函数,让他正确执行加法

猜你喜欢

转载自blog.csdn.net/weixin_39706943/article/details/80596800