美文网首页
xlua热补丁笔记

xlua热补丁笔记

作者: 黒可乐 | 来源:发表于2017-07-20 09:45 被阅读0次

这个是几个月前记的,没有整理。先暂时这样吧,后面具体用到了再来整理吧。

1.使用xlua.hotfix替换方法,变量;xlua.hotfix(类名,{中间写要替换的方法})

   xlua.hotfix(CS.HotfixCalc, {
             Test1 = function(self)
                print('Test1', self)
                return 1
             end;
             Test2 = function(self, a, b)
                 print('Test1', self, a, b)
                 return a + 10, 1024, b
             end;
             Test3 = function(a)
                print(a)
                return 10
             end;
             Test4 = function(a)
                print(a)
             end;
             Test5 = function(self, a, ...)
                print('Test4', self, a, ...)
             end
        })

打补丁

xlua可以用lua函数替换C#的构造函数,函数,属性,事件的替换。lua实现都是函数,比如属性对于一个getter函数和一个setter函数,事件对应一个add函数和一个remove函数。

  • 函数

method_name传函数名,支持重载,不同重载都是转发到同一个lua函数。

比如:


// 要fix的C#类
[Hotfix]
public class HotfixCalc
{
    public int Add(int a, int b)
    {
        return a - b;
    }

    public Vector3 Add(Vector3 a, Vector3 b)
    {
        return a - b;
    }
}


xlua.hotfix(CS.HotfixCalc, 'Add', function(self, a, b)
    return a + b
end)

静态函数和成员函数的区别是,成员函数会加一个self参数,这个self在Stateless方式下是C#对象本身(对应C#的this),Stateful方式下传lua构造函数实现的返回值(一个table或者nil)

普通参数对于lua的参数,ref参数对应lua的一个参数和一个返回值,out参数对于lua的一个返回值。

泛化函数的打补丁规则和普通函数一样。

  • 构造函数

构造函数对应的method_name是".ctor"。

如果是Stateful方式,你可以返回一个table作为这个对象的状态。

和普通函数不一样的是,构造函数的热补丁并不是替换,而是执行原有逻辑后调用lua。

  • 属性

对于名为“AProp”的属性,会对应一个getter,method_name等于get_AProp,setter的method_name等于set_AProp。

  • []操作符

赋值对应set_Item,取值对应get_Item。第一个参数是self,赋值后面跟key,value,取值只有key参数,返回值是取出的值。

  • 其它操作符

C#的操作符都有一套内部表示,比如+号的操作符函数名是op_Addition(其它操作符的内部表示可以去请参照相关资料),覆盖这函数就覆盖了C#的+号操作符。

  • 事件

比如对于事件“AEvent”,+=操作符是add_AEvent,-=对应的是remove_AEvent。这两个函数均是第一个参数是self,第二个参数是操作符后面跟的delegate。

通过xlua.private_accessible来直接访问事件对应的私有delegate的直接访问后,可以通过对象的"&事件名"字段直接触发事件,例如self['&MyEvent'](),其中MyEvent是事件名。

  • 析构函数

method_name是"Finalize",传一个self参数。

和普通函数不一样的是,析构函数的热补丁并不是替换,而是开头调用lua函数后继续原有逻辑。

  • 泛化类型

其它规则一致,需要说明的是,每个泛化类型实例化后都是一个独立的类型,只能针对实例化后的类型分别打补丁。比如:

public class GenericClass<T>
{
}

你只能对GenericClass<double>,GenericClass<int>这些类,而不是对GenericClass打补丁。

另外值得一提的是,要注意泛化类型的命名方式,比如GenericClass<double>的命名是GenericClass`1[System.Double],具体可以看MSDN

对GenericClass<double>打补丁的实例如下:

luaenv.DoString(@"
    xlua.hotfix(CS['GenericClass`1[System.Double]'], {
        ['.ctor'] = function(obj, a)
            print('GenericClass<double>', obj, a)
        end;
        Func1 = function(obj)
            print('GenericClass<double>.Func1', obj)
        end;
        Func2 = function(obj)
            print('GenericClass<double>.Func2', obj)
            return 1314
        end
    })
");
  • Unity协程

通过util.cs_generator可以用一个function模拟一个IEnumerator,在里头用coroutine.yield,就类似C#里头的yield return。比如下面的C#代码和对应的hotfix代码是等同效果的

[XLua.Hotfix]
public class HotFixSubClass : MonoBehaviour {
    IEnumerator Start()
    {
        while (true)
        {
            yield return new WaitForSeconds(3);
            Debug.Log("Wait for 3 seconds");
        }
    }
}
luaenv.DoString(@"
    local util = require 'xlua.util'
    xlua.hotfix(CS.HotFixSubClass,{
        Start = function(self)
            return util.cs_generator(function()
                while true do
                    coroutine.yield(CS.UnityEngine.WaitForSeconds(3))
                    print('Wait for 3 seconds')
                end             
            end
        end;
    })
");
  • 整个类

如果要替换整个类,不需要一次次的调用xlua.hotfix去替换,可以整个一次完成。只要给一个table,按method_name = function组织即可


xlua.hotfix(CS.StatefullTest, {
    ['.ctor'] = function(csobj)
        return {evt = {}, start = 0}
    end;
    set_AProp = function(self, v)
        print('set_AProp', v)
        self.AProp = v
    end;
    get_AProp = function(self)
        return self.AProp
    end;
    get_Item = function(self, k)
        print('get_Item', k)
        return 1024
    end;
    set_Item = function(self, k, v)
        print('set_Item', k, v)
    end;
    add_AEvent = function(self, cb)
        print('add_AEvent', cb)
        table.insert(self.evt, cb)
    end;
    remove_AEvent = function(self, cb)
       print('remove_AEvent', cb)
       for i, v in ipairs(self.evt) do
           if v == cb then
               table.remove(self.evt, i)
               break
           end
       end
    end;
    Start = function(self)
        print('Start')
        for _, cb in ipairs(self.evt) do
            cb(self.start, 2)
        end
        self.start = self.start + 1
    end;
    StaticFunc = function(a, b, c)
       print(a, b, c)
    end;
    Finalize = function(self)
       print('Finalize', self)
    end
})

其中self表示的是自身类,和this一个道理

相关文章

  • xlua热补丁笔记

    这个是几个月前记的,没有整理。先暂时这样吧,后面具体用到了再来整理吧。 1.使用xlua.hotfix替换方法,变...

  • XLua_热更新学习二,尝试打补丁

    本文是根据示例更改,为了认识lua函数1.Unity打开项目创建一个按钮,为按钮添加脚本XluaUptate 2....

  • XLua热更学习笔记(二)

    1.把官方的Xlua项目里和Assets并列的文件夹Tools拷到项目对应位置,只需要一个宏HOTFIX_ENAB...

  • XLua热更学习笔记(一)

    1.hotfix.md说明,常见FAQ解答 hotfix.md的原话:这个特性默认是关闭的,需要添加HOTFIX_...

  • [热更新&XLua]

    XLua代码 1.LuaEnv 正常的一个类的函数 public class Calc { intAdd(inta...

  • XLua-热更新(HotFix)

    仿照XLua的官方例子,我们做一个XLua的热更新1.按照hotfix.md的使用说明 1、添加HOTFIX_EN...

  • Unity3D 使用xLua实现热更新补丁修复

    原文 转载请注明保留原文链接:http://www.jianshu.com/p/dc4de5612d9e 作者:J...

  • Unity3D 使用xLua实现热更新补丁修复

    版权声明:本文为Jumbo原创文章,采用[知识共享 署名-非商业性使用-禁止演绎 4.0 国际 许可协议],转载前...

  • 2020-06-19

    C#写了个Bug,一个用来计算值的属性方法公式有问题,需要使用Xlua热更,然后网上查找关键字:Xlua重写C#的...

  • xLua介绍

    xLua地址:传送门[https://github.com/Tencent/xLua] Xlua是啥?2016年 ...

网友评论

      本文标题:xlua热补丁笔记

      本文链接:https://www.haomeiwen.com/subject/cwovwttx.html