使用XLua 与 Lua 热重载 (记录 3)

使用XLua 与 Lua 热重载 (记录 3)

//

使用方式

1、打开该特性

添加HOTFIX_ENABLE宏,(在Unity3DFile->Build Setting->Scripting Define Symbols下添加)。编辑器、各手机平台这个宏要分别设置!如果是自动化打包,要注意在代码里头用API设置的宏是不生效的,需要在编辑器设置。

(建议平时开发业务代码不打开HOTFIXENABLE,只在build手机版本或者要在编译器下开发补丁时打开HOTFIXENABLE

2、执行XLua/Generate Code菜单。

3、注入,构建手机包这个步骤会在构建时自动进行,编辑器下开发补丁需要手动执行"XLua/Hotfix Inject In Editor"菜单。打印“hotfix inject finish!”或者“had injected!”才算成功,否则会打印错误信息。

如果已经打印了“hotfix inject finish!”或者“had injected!”,执行xlua.hotfix仍然报类似“xlua.access, no field _Hitfix0Update”的错误,要么是该类没配置到Hotfix列表,要么是注入成功后,又触发了编译,覆盖了注入结果。

约束

不支持静态构造函数。

目前只支持Assets下代码的热补丁,不支持引擎,c#系统库的热补丁。

API

xlua.hotfix(class, [method_name], fix)

  • 描述 注入lua补丁
  • class C#类,两种表示方法,CS.Namespace.TypeName或者字符串方式"Namespace.TypeName",字符串格式和C#Type.GetType要求一致,如果是内嵌类型(Nested Type)是非Public类型的话,只能用字符串方式表示"Namespace.TypeName+NestedTypeName"
  • method_name 方法名,可选;
  • fix 如果传了methodnamefix将会是一个function,否则通过table提供一组函数。table的组织按keymethodnamevaluefunction的方式。

base(csobj)

  • 描述 子类override函数通过base调用父类实现。
  • csobj 对象
  • 返回值 新对象,可以通过该对象base上的方法

例子(位于HotfixTest2.cs):

lua xlua.hotfix(CS.BaseTest, 'Foo', function(self, p) print('BaseTest', p) base(self):Foo(p) end)

util.hotfixex(class, methodname, fix)

  • 描述 xlua.hotfix的增强版本,可以在fix函数里头执行原来的函数,缺点是fix的执行会略慢。
  • method_name 方法名;
  • fix 用来替换C#方法的lua function

标识要热更新的类型

和其它配置一样,有两种方式

方式一:直接在类里头打Hotfix标签(不建议,示例只是为了方便演示采取这种方式);

方式二:在一个static类的static字段或者属性里头配置一个列表。属性可以用于实现的比较复杂的配置,比如根据Namespace做白名单。

~~~csharp //如果涉及到Assembly-CSharp.dll之外的其它dll,如下代码需要放到Editor目录 public static class HotfixCfg { [Hotfix] public static List by_field = new List() { typeof(HotFixSubClass), typeof(GenericClass<>), };

[Hotfix]

public static List<Type> by_property

{

    get

    {

        return (from type in Assembly.Load("Assembly-CSharp").GetTypes()

                where type.Namespace == "XXXX"

                select type).ToList();

    }

}

} ~~~

Hotfix Flag

Hotfix标签可以设置一些标志位对生成代码及插桩定制化

  • StatelessStateful

遗留设置,Stateful方式在新版本已经删除,因为这种方式可以用xlua.util.state接口达到类似的效果,该接口的使用可以看下HotfixTest2.cs里的示例代码。

由于没Stateful,默认就是Stateless,所以也没必要设置该标志位。

  • ValueTypeBoxing

值类型的适配delegate会收敛到object,好处是代码量更少,不好的是值类型会产生boxinggc,适用于对text段敏感的业务。

  • IgnoreProperty

不对属性注入及生成适配代码,一般而言,大多数属性的实现都很简单,出错几率比较小,建议不注入。

  • IgnoreNotPublic

不对非public的方法注入及生成适配代码。除了像MonoBehaviour那种会被反射调用的私有方法必须得注入,其它仅被本类调用的非public方法可以不注入,只不过修复时会工作量稍大,所有引用到这个函数的public方法都要重写。

  • Inline

不生成适配delegate,直接在函数体注入处理代码。

  • IntKey

不生成静态字段,而是把所有注入点放到一个数组集中管理。

好处:对text段影响小。

坏处:使用不像默认方式那么方便,需要通过id来指明hotfix哪个函数,而这个id是代码注入工具时分配的,函数到id的映射会保存在Gen/Resources/hotfixidmap.lua.txt,并且自动加时间戳备份到hotfixidmap.lua.txt同级目录,发布手机版本后请妥善保存该文件。

该文件的格式大概如下(注意:该文件仅IntKey模式使用,当你没类型指定IntKey模式注入,该文件只返回个空表):

~~~lua

return { ["HotfixTest"] = { [".ctor"] = { 5 }, ["Start"] = { 6 }, ["Update"] = { 7 }, ["FixedUpdate"] = { 8 }, ["Add"] = { 9,10 }, ["OnGUI"] = { 11 }, }, }

~~~

想要替换HotfixTestUpdate函数,你得

~~~lua

CS.XLua.HotfixDelegateBridge.Set(7, func)

~~~

如果是重载函数,将会一个函数名对应多个id,比如上面的Add函数。

能不能自动化一些呢?可以,xlua.util提供了autoidmap函数,执行一次后你就可以像以前那样直接用类,方法名去指明修补的函数。

~~~lua

(require 'xlua.util').autoidmap() xlua.hotfix(CS.HotfixTest, 'Update', function(self) self.tick = self.tick + 1 if (self.tick % 50) == 0 then print('<<<<<<<<Update in lua, tick = ' .. self.tick) end end)

~~~

前提是hotfixidmap.lua.txt放到可以通过require 'hotfixidmap'引用到的地方。

使用建议

  • 对所有较大可能变动的类型加上Hotfix标识;
  • 建议用反射找出所有函数参数、字段、属性、事件涉及的delegate类型,标注CSharpCallLua
  • 业务代码、引擎API、系统API,需要在Lua补丁里头高性能访问的类型,加上LuaCallCSharp
  • 引擎API、系统API可能被代码剪裁调(C#无引用的地方都会被剪裁),如果觉得可能会新增C#代码之外的API调用,这些API所在的类型要么加LuaCallCSharp,要么加ReflectionUse

打补丁

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

  • 函数

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

比如:

```csharp

// fixC# [Hotfix] public class HotfixCalc { public int Add(int a, int b) { return a - b; }

public Vector3 Add(Vector3 a, Vector3 b)

{

    return a - b;

}

```

```lua

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

```

静态函数和成员函数的区别是,成员函数会加一个self参数,这个selfStateless方式下是C#对象本身(对应C#this

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

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

  • 构造函数

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

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

  • 属性

对于名为“AProp”的属性,会对应一个gettermethodname等于getAPropsettermethodname等于setAProp

  • []操作符

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

  • 其它操作符

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

  • 事件

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

通过xlua.privateaccessible(版本号大于2.1.11不需要调用xlua.privateaccessible)来直接访问事件对应的私有delegate的直接访问后,可以通过对象的"&事件名"字段直接触发事件,例如self['&MyEvent'](),其中MyEvent是事件名。

  • 析构函数

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

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

  • 泛化类型

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

csharp public class GenericClass<T> {

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

GenericClass打补丁的实例如下:

csharp luaenv.DoString(@" xlua.hotfix(CS.GenericClass(CS.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代码是等同效果的

~~~csharp

[XLua.Hotfix] public class HotFixSubClass : MonoBehaviour { IEnumerator Start() { while (true) { yield return new WaitForSeconds(3); Debug.Log("Wait for 3 seconds"); } } }

 ~~~

~~~csharp

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组织即可

```lua

xlua.hotfix(CS.StatefullTest, {

['.ctor'] = function(csobj) return util.state(csobj, {evt = {}, start = 0, prop = 0}) end;

setAProp = function(self, v) print('setAProp', v) self.prop = v end;

getAProp = function(self) return self.prop end;

getItem = function(self, k) print('getItem', k) return 1024 end;

setItem = function(self, k, v) print('setItem', k, v) end;

addAEvent = function(self, cb) print('add_AEvent', cb) table.insert(self.evt, cb) end;

removeAEvent = function(self, cb)

    print('removeAEvent', 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

})```

 

///

namespace XLuaTest

{

    [Hotfix]

    public class HotfixTest : MonoBehaviour

    {

        LuaEnv luaenv = new LuaEnv();

 

        private int tick = 0;

 

        // Use this for initialization

        void Start()

        {

        }

 

        // Update is called once per frame

        void Update()

        {

            if (++tick % 50 == 0)

            {

                Debug.Log(">>>>>>>>Update in C#, tick = " + tick);

            }

        }

 

        void OnGUI()

        {

            if (GUI.Button(new Rect(10, 10, 300, 80), "Hotfix"))

            {

                luaenv.DoString(@"

                xlua.hotfix(CS.XLuaTest.HotfixTest, 'Update', function(self)

                    self.tick = self.tick + 1

                    if (self.tick % 50) == 0 then

                        print('<<<<<<<<Update in lua, tick = ' .. self.tick)

                    end

                end)

            ");

            }

 

            string chHint = @"在运行该示例之前,请细致阅读xLua文档,并执行以下步骤:

 

1.宏定义:添加 HOTFIX_ENABLE 'Edit > Project Settings > Player > Other Settings > Scripting Define Symbols'

(注意:各平台需要分别设置)

 

2.生成代码:执行 'XLua > Generate Code' 菜单,等待Unity编译完成。

 

3.注入:执行 'XLua > Hotfix Inject In Editor' 菜单。注入成功会打印 'hotfix inject finish!' 或者 'had injected!' ";

            string enHint = @"Read documents carefully before you run this example, then follow the steps below:

 

1. Define: Add 'HOTFIX_ENABLE' to 'Edit > Project Settings > Player > Other Settings > Scripting Define Symbols'.

(Note: Each platform needs to set this respectively)

 

2.Generate Code: Execute menu 'XLua > Generate Code', wait for Unity's compilation.

 

 

3.Inject: Execute menu 'XLua > Hotfix Inject In Editor'.There should be 'hotfix inject finish!' or 'had injected!' print in the Console if the Injection is successful.";

            GUIStyle style = GUI.skin.textArea;

            style.normal.textColor = Color.red;

            style.fontSize = 16;

            GUI.TextArea(new Rect(10, 100, 500, 290), chHint, style);

            GUI.TextArea(new Rect(10, 400, 500, 290), enHint, style);

        }

    }

}

 

using UnityEngine;

using XLua;

 

namespace XLuaTest

{

    [Hotfix]

    public class HotfixCalc

    {

        public int Add(int a, int b)

        {

            return a - b;

        }

 

        public Vector3 Add(Vector3 a, Vector3 b)

        {

            return a - b;

        }

 

        public int TestOut(int a, out double b, ref string c)

        {

            b = a + 2;

            c = "wrong version";

            return a + 3;

        }

 

        public int TestOut(int a, out double b, ref string c, GameObject go)

        {

            return TestOut(a, out b, ref c);

        }

 

        public T Test1<T>()

        {

            return default(T);

        }

 

        public T1 Test2<T1, T2, T3>(T1 a, out T2 b, ref T3 c)

        {

            b = default(T2);

            return a;

        }

 

        public static int Test3<T>(T a)

        {

            return 0;

        }

 

        public static void Test4<T>(T a)

        {

        }

 

        public void Test5<T>(int a, params T[] arg)

        {

 

        }

    }

 

    public class NoHotfixCalc

    {

        public int Add(int a, int b)

        {

            return a + b;

        }

    }

 

    [Hotfix]

    public class GenericClass<T>

    {

        T a;

 

        public GenericClass(T a)

        {

            this.a = a;

        }

 

        public void Func1()

        {

            Debug.Log("a=" + a);

        }

 

        public T Func2()

        {

            return default(T);

        }

    }

 

    [Hotfix]

    public class InnerTypeTest

    {

        public void Foo()

        {

            _InnerStruct ret = Bar();

            Debug.Log("{x=" + ret.x + ",y= " + ret.y + "}");

        }

 

        struct _InnerStruct

        {

            public int x;

            public int y;

        }

 

        _InnerStruct Bar()

        {

            return new _InnerStruct { x = 1, y = 2 };

        }

    }

 

    public class BaseTestHelper

    {

 

    }

 

    public class BaseTestBase<T> : BaseTestHelper

    {

        public virtual void Foo(int p)

        {

            Debug.Log("BaseTestBase<>.Foo, p = " + p);

        }

    }

 

    [Hotfix]

    [LuaCallCSharp]

    public class BaseTest : BaseTestBase<InnerTypeTest>

    {

        public override void Foo(int p)

        {

            Debug.Log("BaseTest<>.Foo, p = " + p);

        }

 

        public void Proxy(int p)

        {

            base.Foo(p);

        }

 

        public override string ToString()

        {

            return base.ToString();

        }

    }

 

    [Hotfix]

    public struct StructTest

    {

        GameObject go;

        public StructTest(GameObject go)

        {

            this.go = go;

        }

 

        public GameObject GetGo(int a, object b)

        {

            return go;

        }

 

        public override string ToString()

        {

            return base.ToString();

        }

 

        public string Proxy()

        {

            return base.ToString();

        }

    }

 

    [Hotfix]

    public struct GenericStruct<T>

    {

        T a;

 

        public GenericStruct(T a)

        {

            this.a = a;

        }

 

        public T GetA(int p)

        {

            return a;

        }

    }

 

    public class HotfixTest2 : MonoBehaviour

    {

 

        // 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.XLuaTest.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.XLuaTest.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.XLuaTest.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(@"

            local util = require 'xlua.util'

            xlua.hotfix(CS.XLuaTest.StatefullTest, {

                ['.ctor'] = function(csobj)

                    util.state(csobj, {evt = {}, start = 0, prop = 0})

                end;

                set_AProp = function(self, v)

                    print('set_AProp', v)

                    self.prop = v

                end;

                get_AProp = function(self)

                    return self.prop

                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.XLuaTest.GenericClass(CS.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.XLuaTest.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.XLuaTest.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.XLuaTest.GenericStruct(CS.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);

            }

 

 

            BaseTestBase<InnerTypeTest> bt = new BaseTest();

            bt.Foo(1);

            Debug.Log(bt);

 

            luaenv.DoString(@"

            xlua.hotfix(CS.XLuaTest.BaseTest, 'Foo', function(self, p)

                    print('BaseTest', p)

                end)

            xlua.hotfix(CS.XLuaTest.BaseTest, 'ToString', function(self)

                    return '>>>' .. base(self):ToString()

                end)

        ");

            bt.Foo(2);

            Debug.Log(bt);

        }

 

        void TestStateful()

        {

            StatefullTest sft = new StatefullTest();

            sft.AProp = 10;

            Debug.Log("sft.AProp:" + sft.AProp);

            sft["1"] = 1;

            Debug.Log("sft['1']:" + sft["1"]);

            System.Action<int, double> cb = (a, b) =>

            {

                Debug.Log("a:" + a + ",b:" + b);

            };

            sft.AEvent += cb;

            sft.Start();

            sft.Start();

            sft.AEvent -= cb;

            sft.Start();

            StatefullTest.StaticFunc(1, 2);

            StatefullTest.StaticFunc("e", 3, 4);

            sft.GenericTest(1);

            sft.GenericTest("hehe");

        }

 

        // Update is called once per frame

        void Update()

        {

 

        }

    }

}

 

using UnityEngine;

 

namespace XLuaTest

{

    [XLua.Hotfix]

    public class StatefullTest

    {

        public StatefullTest()

        {

 

        }

 

        public StatefullTest(int a, int b)

        {

            if (a > 0)

            {

                return;

            }

 

            Debug.Log("a=" + a);

            if (b > 0)

            {

                return;

            }

            else

            {

                if (a + b > 0)

                {

                    return;

                }

            }

            Debug.Log("b=" + b);

        }

 

        public int AProp

        {

            get;

            set;

        }

 

        public event System.Action<int, double> AEvent;

 

        public int this[string field]

        {

            get

            {

                return 1;

            }

            set

            {

            }

        }

 

        public void Start()

        {

 

        }

 

        void Update()

        {

 

        }

 

        public void GenericTest<T>(T a)

        {

 

        }

 

        static public void StaticFunc(int a, int b)

        {

        }

        static public void StaticFunc(string a, int b, int c)

        {

        }

 

        ~StatefullTest()

        {

            Debug.Log("~StatefullTest");

        }

    }

}

 

 

/

 

 

 

 

//

 

/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值