// Use this for initialization
    void Start()
    {
        LuaEnv       luaenv       = new LuaEnv();
        HotfixCalc   calc         = new HotfixCalc();
        NoHotfixCalc ordinaryCalc = new NoHotfixCalc();

        int CALL_TIME = 100 * 1000 * 1000;
        var start     = System.DateTime.Now;

        for (int i = 0; i < CALL_TIME; i++)
        {
            calc.Add(2, 1);
        }
        var d1 = (System.DateTime.Now - start).TotalMilliseconds;

        Debug.Log("Hotfix using:" + d1);

        start = System.DateTime.Now;
        for (int i = 0; i < CALL_TIME; i++)
        {
            ordinaryCalc.Add(2, 1);
        }
        var d2 = (System.DateTime.Now - start).TotalMilliseconds;

        Debug.Log("No Hotfix using:" + d2);

        Debug.Log("drop:" + ((d1 - d2) / d1));

        Debug.Log("Before Fix: 2 + 1 = " + calc.Add(2, 1));
        Debug.Log("Before Fix: Vector3(2, 3, 4) + Vector3(1, 2, 3) = " + calc.Add(new Vector3(2, 3, 4), new Vector3(1, 2, 3)));
        luaenv.DoString(@"
            xlua.hotfix(CS.HotfixCalc, 'Add', function(self, a, b)
                return a + b
            end)
        ");
        Debug.Log("After Fix: 2 + 1 = " + calc.Add(2, 1));
        Debug.Log("After Fix: Vector3(2, 3, 4) + Vector3(1, 2, 3) = " + calc.Add(new Vector3(2, 3, 4), new Vector3(1, 2, 3)));

        double num;
        string str = "hehe";
        int    ret = calc.TestOut(100, out num, ref str);

        Debug.Log("ret = " + ret + ", num = " + num + ", str = " + str);

        luaenv.DoString(@"
            xlua.hotfix(CS.HotfixCalc, 'TestOut', function(self, a, c, go)
                    print('TestOut', self, a, c, go)
                    if go then error('test error') end
                    return a + 10, a + 20, 'right version'
                end)
        ");
        str = "hehe";
        ret = calc.TestOut(100, out num, ref str);
        Debug.Log("ret = " + ret + ", num = " + num + ", str = " + str);

        luaenv.DoString(@"
            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
            })
        ");

        int    r1 = calc.Test1 <int>();
        double r2 = calc.Test1 <double>();

        Debug.Log("r1:" + r1 + ",r2:" + r2);

        string ss = "heihei";
        int    r3 = calc.Test2(r1, out r2, ref ss);

        Debug.Log("r1:" + r1 + ",r2:" + r2 + ",r3:" + r3 + ",ss:" + ss);

        r3 = HotfixCalc.Test3("test3");
        r3 = HotfixCalc.Test3(2);
        r3 = HotfixCalc.Test3(this);
        Debug.Log("r3:" + r3);
        HotfixCalc.Test4(this);
        HotfixCalc.Test4(2);
        calc.Test5(10, "a", "b", "c");
        calc.Test5(10, 1, 3, 5);

        Debug.Log("----------------------before------------------------");
        TestStateful();
        System.GC.Collect();
        System.GC.WaitForPendingFinalizers();
        luaenv.DoString(@"
            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;
                GenericTest = function(self, a)
                   print(self, a)
                end;
                Finalize = function(self)
                   print('Finalize', self)
                end
           })
        ");
        Debug.Log("----------------------after------------------------");
        TestStateful();
        luaenv.FullGc();
        System.GC.Collect();
        System.GC.WaitForPendingFinalizers();

        var genericObj = new GenericClass <double>(1.1);

        genericObj.Func1();
        Debug.Log(genericObj.Func2());
        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
            })
        ");
        genericObj = new GenericClass <double>(1.1);
        genericObj.Func1();
        Debug.Log(genericObj.Func2());

        InnerTypeTest itt = new InnerTypeTest();

        itt.Foo();
        luaenv.DoString(@"
            xlua.hotfix(CS.InnerTypeTest, 'Bar', function(obj)
                    print('lua Bar', obj)
                    return {x = 10, y = 20}
                end)
        ");
        itt.Foo();

        try
        {
            calc.TestOut(100, out num, ref str, gameObject);
        }
        catch (LuaException e)
        {
            Debug.Log("throw in lua an catch in c# ok, e.Message:" + e.Message);
        }
    }
Exemplo n.º 2
0
    // Use this for initialization
    void Start()
    {
        LuaEnv       luaenv       = new LuaEnv();
        HotfixCalc   calc         = new HotfixCalc();
        NoHotfixCalc ordinaryCalc = new NoHotfixCalc();

        //对比热更与不热更标签用时(毫秒),执行同样的一组循环
        int CALL_TIME = 100 * 1000 * 1000;
        var start     = System.DateTime.Now;

        for (int i = 0; i < CALL_TIME; i++)
        {
            calc.Add(2, 1);  //return a-b=1
        }
        var d1 = (System.DateTime.Now - start).TotalMilliseconds;

        Debug.Log("Hotfix using:" + d1);

        start = System.DateTime.Now;
        for (int i = 0; i < CALL_TIME; i++)
        {
            ordinaryCalc.Add(2, 1);
        }
        var d2 = (System.DateTime.Now - start).TotalMilliseconds;

        Debug.Log("No Hotfix using:" + d2);
        Debug.Log("drop:" + ((d1 - d2) / d1));
        Debug.Log("Before Fix: 2 + 1 = " + calc.Add(2, 1));                                                                     //热更变成减法了
        Debug.Log("Before Fix: Vector3(2, 3, 4) + Vector3(1, 2, 3) = " + calc.Add(new Vector3(2, 3, 4), new Vector3(1, 2, 3))); //向量减法
        luaenv.DoString(@"
            xlua.hotfix(CS.HotfixCalc, 'Add', function(self, a, b)
                return a + b
            end)
        ");
        Debug.Log("After Fix: 2 + 1 = " + calc.Add(2, 1));                                                                      //热更再变成加法
        Debug.Log("After Fix: Vector3(2, 3, 4) + Vector3(1, 2, 3) = " + calc.Add(new Vector3(2, 3, 4), new Vector3(1, 2, 3)));

        double num;
        string str = "hehe";
        int    ret = calc.TestOut(100, out num, ref str);

        Debug.Log("ret = " + ret + ", num = " + num + ", str = " + str); //返回值是100+3,num+=2,str被赋值wrong version
        //打印test out, self=这个类,打印传入的值
        luaenv.DoString(@"
            xlua.hotfix(CS.HotfixCalc, 'TestOut', function(self, a, c, go)
                    print('TestOut', self, a, c, go)
                    if go then error('test error') end
                    return a + 10 , a + 20, 'right version'
                end)
        ");
        str = "hehe";
        ret = calc.TestOut(100, out num, ref str);
        Debug.Log("ret = " + ret + ", num = " + num + ", str = " + str); //110 120 rightversion,第一个可以理解成C#只接受第一个返回值

        luaenv.DoString(@"
            xlua.hotfix(CS.HotfixCalc, {
                 Test1 = function(self)
                    print('Test1', self) --self不是实参,相当于this,但是可以指向表
                    return 1
                 end;
                 Test2 = function(self, a, b)  --out向外传参可以不写
                     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
            })
        ");
        //泛型热更演示
        int    r1 = calc.Test1 <int>(); //无论什么类型都是返回1
        double r2 = calc.Test1 <double>();

        Debug.Log("r1:" + r1 + ",r2:" + r2);

        string ss = "heihei"; //ref必须初始化
        int    r3 = calc.Test2(r1, out r2, ref ss);

        Debug.Log("r1:" + r1 + ",r2:" + r2 + ",r3:" + r3 + ",ss:" + ss); //这里面return c#只能接受第一个参数,因为有out和ref所以,r2 r3能取到值

        r3 = HotfixCalc.Test3("test3");
        r3 = HotfixCalc.Test3(2);
        r3 = HotfixCalc.Test3(this);  //lua变成C#之后再执行,这里面就和C#脚本的this是一样的
        Debug.Log("r3:" + r3);
        HotfixCalc.Test4(this);
        HotfixCalc.Test4(2);
        calc.Test5(10, "a", "b", "c");
        calc.Test5(10, 1, 3, 5);

        Debug.Log("----------------------before------------------------");
        //Stateless比较适合无状态的类,有状态的话,你得通过反射去操作私有成员,也没法新增状态(field)。Stateless有个好处,可以运行的任意时刻执行替换。
        // Stateful的代价是会在类增加一个LuaTable类型的字段(中间层面增加,不会改源代码)。但这种方式是适用性更广,比如你不想要lua状态,可以在构造函数拦截那返回空。而且操作状态性能比反射操作C#私有变量要好,也可以随意新增任意的状态信息。缺点是,执行成员函数之前就new好的对象,接收到的状态会是空,所以需要重启,在一开始就执行替换。
        TestStateful(); //Stateful方式下你可以在Lua的构造函数返回一个table,然后后续成员函数调用会把这个table给传递过去。
        System.GC.Collect();
        System.GC.WaitForPendingFinalizers();
        luaenv.DoString(@"
            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;
                GenericTest = function(self, a)
                   print(self, a)
                end;
                Finalize = function(self)   --析构函数固定写法
                   print('Finalize', self)
                end
           })
        ");
        Debug.Log("----------------------after------------------------");
        TestStateful(); //在下面调用执行的
        luaenv.FullGc();
        System.GC.Collect();
        System.GC.WaitForPendingFinalizers();

        var genericObj = new GenericClass <double>(1.1);

        genericObj.Func1();
        Debug.Log(genericObj.Func2());
        //泛型类要指定类型后热更
        luaenv.DoString(@"
            xlua.hotfix(CS['GenericClass`1[System.Double]'], {  --数字代表几个参数,固定的泛型命名写法 Type.GetType Method (String)
                ['.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
            })
        ");
        genericObj = new GenericClass <double>(1.1);
        genericObj.Func1();
        Debug.Log(genericObj.Func2());

        InnerTypeTest itt = new InnerTypeTest();

        itt.Foo();
        luaenv.DoString(@"
            xlua.hotfix(CS.InnerTypeTest, 'Bar', function(obj)
                    print('lua Bar', obj)
                    return {x = 10, y = 20}
                end)
        ");
        itt.Foo();

        StructTest st = new StructTest(gameObject);

        Debug.Log("go=" + st.GetGo(123, "john"));
        luaenv.DoString(@"
            xlua.hotfix(CS.StructTest, 'GetGo', function(self, a, b)
                    print('GetGo', self, a, b)
                    return nil
                end)
        ");
        Debug.Log("go=" + st.GetGo(123, "john"));

        GenericStruct <int> gs = new GenericStruct <int>(1);

        Debug.Log("gs.GetA()=" + gs.GetA(123));
        luaenv.DoString(@"
            xlua.hotfix(CS['GenericStruct`1[System.Int32]'], 'GetA', function(self, a)
                    print('GetA',self, a)
                    return 789
                end)
        ");
        Debug.Log("gs.GetA()=" + gs.GetA(123));

        try
        {
            calc.TestOut(100, out num, ref str, gameObject);
        }
        catch (LuaException e)
        {
            Debug.Log("throw in lua an catch in c# ok, e.Message:" + e.Message);
        }
    }