Hotfix

HotfixTest.cs

  1. using UnityEngine;
  2. using XLua;
  3. [Hotfix]
  4. public class HotfixTest : MonoBehaviour
  5. {
  6. LuaEnv luaenv = new LuaEnv();
  7. public int tick = 0; //如果是private的,在lua设置xlua.private_accessible(CS.HotfixTest)后即可访问
  8. // Use this for initialization
  9. void Start()
  10. {
  11. }
  12. // Update is called once per frame
  13. void Update()
  14. {
  15. if (++tick % 50 == 0)
  16. {
  17. Debug.Log(">>>>>>>>Update in C#, tick = " + tick);
  18. }
  19. }
  20. void OnGUI()
  21. {
  22. if (GUI.Button(new Rect(10, 10, 300, 80), "Hotfix"))
  23. {
  24. luaenv.DoString(@"
  25. xlua.hotfix(CS.HotfixTest, 'Update', function(self)
  26. self.tick = self.tick + 1
  27. if (self.tick % 50) == 0 then
  28. print('<<<<<<<<Update in lua, tick = ' .. self.tick)
  29. end
  30. end)
  31. ");
  32. }
  33. string chHint = @"在运行该示例之前,请细致阅读xLua文档,并执行以下步骤:
  34. 1.宏定义:添加 HOTFIX_ENABLE 到 'Edit > Project Settings > Player > Other Settings > Scripting Define Symbols'。
  35. (注意:各平台需要分别设置)
  36. 2.生成代码:执行 'XLua > Generate Code' 菜单,等待Unity编译完成。
  37. 3.注入:执行 'XLua > Hotfix Inject In Editor' 菜单。注入成功会打印 'hotfix inject finish!' 或者 'had injected!' 。";
  38. string enHint = @"Read documents carefully before you run this example, then follow the steps below:
  39. 1. Define: Add 'HOTFIX_ENABLE' to 'Edit > Project Settings > Player > Other Settings > Scripting Define Symbols'.
  40. (Note: Each platform needs to set this respectively)
  41. 2.Generate Code: Execute menu 'XLua > Generate Code', wait for Unity's compilation.
  42. 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.";
  43. GUIStyle style = GUI.skin.textArea;
  44. style.normal.textColor = Color.red;
  45. style.fontSize = 16;
  46. GUI.TextArea(new Rect(10, 100, 500, 290), chHint, style);
  47. GUI.TextArea(new Rect(10, 400, 500, 290), enHint, style);
  48. }
  49. }

HotfixTest2.cs

  1. using UnityEngine;
  2. using System.Collections.Generic;
  3. using XLua;
  4. [CSharpCallLua]
  5. public delegate int TestOutDelegate(HotfixCalc calc, int a, out double b, ref string c);
  6. [Hotfix]
  7. public class HotfixCalc
  8. {
  9. public int Add(int a, int b)
  10. {
  11. return a - b;
  12. }
  13. public Vector3 Add(Vector3 a, Vector3 b)
  14. {
  15. return a - b;
  16. }
  17. public int TestOut(int a, out double b, ref string c)
  18. {
  19. b = a + 2;
  20. c = "wrong version";
  21. return a + 3;
  22. }
  23. public int TestOut(int a, out double b, ref string c, GameObject go)
  24. {
  25. return TestOut(a, out b, ref c);
  26. }
  27. public T Test1<T>()
  28. {
  29. return default(T);
  30. }
  31. public T1 Test2<T1, T2, T3>(T1 a, out T2 b, ref T3 c)
  32. {
  33. b = default(T2);
  34. return a;
  35. }
  36. public static int Test3<T>(T a)
  37. {
  38. return 0;
  39. }
  40. public static void Test4<T>(T a)
  41. {
  42. }
  43. public void Test5<T>(int a, params T[] arg)
  44. {
  45. }
  46. }
  47. public class NoHotfixCalc
  48. {
  49. public int Add(int a, int b)
  50. {
  51. return a + b;
  52. }
  53. }
  54. [Hotfix]
  55. public class GenericClass<T>
  56. {
  57. T a;
  58. public GenericClass(T a)
  59. {
  60. this.a = a;
  61. }
  62. public void Func1()
  63. {
  64. Debug.Log("a=" + a);
  65. }
  66. public T Func2()
  67. {
  68. return default(T);
  69. }
  70. }
  71. [Hotfix]
  72. public class InnerTypeTest
  73. {
  74. public void Foo()
  75. {
  76. _InnerStruct ret = Bar();
  77. Debug.Log("{x=" + ret.x + ",y= " + ret.y + "}");
  78. }
  79. struct _InnerStruct
  80. {
  81. public int x;
  82. public int y;
  83. }
  84. _InnerStruct Bar()
  85. {
  86. return new _InnerStruct { x = 1, y = 2 };
  87. }
  88. }
  89. [Hotfix]
  90. public struct StructTest
  91. {
  92. GameObject go;
  93. public StructTest(GameObject go)
  94. {
  95. this.go = go;
  96. }
  97. public GameObject GetGo(int a, object b)
  98. {
  99. return go;
  100. }
  101. }
  102. [Hotfix(HotfixFlag.Stateful)]
  103. public struct GenericStruct<T>
  104. {
  105. T a;
  106. public GenericStruct(T a)
  107. {
  108. this.a = a;
  109. }
  110. public T GetA(int p)
  111. {
  112. return a;
  113. }
  114. }
  115. public class HotfixTest2 : MonoBehaviour {
  116. // Use this for initialization
  117. void Start () {
  118. LuaEnv luaenv = new LuaEnv();
  119. HotfixCalc calc = new HotfixCalc();
  120. NoHotfixCalc ordinaryCalc = new NoHotfixCalc();
  121. int CALL_TIME = 100 * 1000 * 1000 ;
  122. var start = System.DateTime.Now;
  123. for (int i = 0; i < CALL_TIME; i++)
  124. {
  125. calc.Add(2, 1);
  126. }
  127. var d1 = (System.DateTime.Now - start).TotalMilliseconds;
  128. Debug.Log("Hotfix using:" + d1);
  129. start = System.DateTime.Now;
  130. for (int i = 0; i < CALL_TIME; i++)
  131. {
  132. ordinaryCalc.Add(2, 1);
  133. }
  134. var d2 = (System.DateTime.Now - start).TotalMilliseconds;
  135. Debug.Log("No Hotfix using:" + d2);
  136. Debug.Log("drop:" + ((d1 - d2) / d1));
  137. Debug.Log("Before Fix: 2 + 1 = " + calc.Add(2, 1));
  138. Debug.Log("Before Fix: Vector3(2, 3, 4) + Vector3(1, 2, 3) = " + calc.Add(new Vector3(2, 3, 4), new Vector3(1, 2, 3)));
  139. luaenv.DoString(@"
  140. xlua.hotfix(CS.HotfixCalc, 'Add', function(self, a, b)
  141. return a + b
  142. end)
  143. ");
  144. Debug.Log("After Fix: 2 + 1 = " + calc.Add(2, 1));
  145. Debug.Log("After Fix: Vector3(2, 3, 4) + Vector3(1, 2, 3) = " + calc.Add(new Vector3(2, 3, 4), new Vector3(1, 2, 3)));
  146. double num;
  147. string str = "hehe";
  148. int ret = calc.TestOut(100, out num, ref str);
  149. Debug.Log("ret = " + ret + ", num = " + num + ", str = " + str);
  150. luaenv.DoString(@"
  151. xlua.hotfix(CS.HotfixCalc, 'TestOut', function(self, a, c, go)
  152. print('TestOut', self, a, c, go)
  153. if go then error('test error') end
  154. return a + 10, a + 20, 'right version'
  155. end)
  156. ");
  157. str = "hehe";
  158. ret = calc.TestOut(100, out num, ref str);
  159. Debug.Log("ret = " + ret + ", num = " + num + ", str = " + str);
  160. luaenv.DoString(@"
  161. xlua.hotfix(CS.HotfixCalc, {
  162. Test1 = function(self)
  163. print('Test1', self)
  164. return 1
  165. end;
  166. Test2 = function(self, a, b)
  167. print('Test1', self, a, b)
  168. return a + 10, 1024, b
  169. end;
  170. Test3 = function(a)
  171. print(a)
  172. return 10
  173. end;
  174. Test4 = function(a)
  175. print(a)
  176. end;
  177. Test5 = function(self, a, ...)
  178. print('Test4', self, a, ...)
  179. end
  180. })
  181. ");
  182. int r1 = calc.Test1<int>();
  183. double r2 = calc.Test1<double>();
  184. Debug.Log("r1:" + r1 + ",r2:" + r2);
  185. string ss = "heihei";
  186. int r3 = calc.Test2(r1, out r2, ref ss);
  187. Debug.Log("r1:" + r1 + ",r2:" + r2 + ",r3:" + r3 + ",ss:" + ss);
  188. r3 = HotfixCalc.Test3("test3");
  189. r3 = HotfixCalc.Test3(2);
  190. r3 = HotfixCalc.Test3(this);
  191. Debug.Log("r3:" + r3);
  192. HotfixCalc.Test4(this);
  193. HotfixCalc.Test4(2);
  194. calc.Test5(10, "a", "b", "c");
  195. calc.Test5(10, 1, 3, 5);
  196. Debug.Log("----------------------before------------------------");
  197. TestStateful();
  198. System.GC.Collect();
  199. System.GC.WaitForPendingFinalizers();
  200. luaenv.DoString(@"
  201. xlua.hotfix(CS.StatefullTest, {
  202. ['.ctor'] = function(csobj)
  203. return {evt = {}, start = 0}
  204. end;
  205. set_AProp = function(self, v)
  206. print('set_AProp', v)
  207. self.AProp = v
  208. end;
  209. get_AProp = function(self)
  210. return self.AProp
  211. end;
  212. get_Item = function(self, k)
  213. print('get_Item', k)
  214. return 1024
  215. end;
  216. set_Item = function(self, k, v)
  217. print('set_Item', k, v)
  218. end;
  219. add_AEvent = function(self, cb)
  220. print('add_AEvent', cb)
  221. table.insert(self.evt, cb)
  222. end;
  223. remove_AEvent = function(self, cb)
  224. print('remove_AEvent', cb)
  225. for i, v in ipairs(self.evt) do
  226. if v == cb then
  227. table.remove(self.evt, i)
  228. break
  229. end
  230. end
  231. end;
  232. Start = function(self)
  233. print('Start')
  234. for _, cb in ipairs(self.evt) do
  235. cb(self.start, 2)
  236. end
  237. self.start = self.start + 1
  238. end;
  239. StaticFunc = function(a, b, c)
  240. print(a, b, c)
  241. end;
  242. GenericTest = function(self, a)
  243. print(self, a)
  244. end;
  245. Finalize = function(self)
  246. print('Finalize', self)
  247. end
  248. })
  249. ");
  250. Debug.Log("----------------------after------------------------");
  251. TestStateful();
  252. luaenv.FullGc();
  253. System.GC.Collect();
  254. System.GC.WaitForPendingFinalizers();
  255. var genericObj = new GenericClass<double>(1.1);
  256. genericObj.Func1();
  257. Debug.Log(genericObj.Func2());
  258. luaenv.DoString(@"
  259. xlua.hotfix(CS['GenericClass`1[System.Double]'], {
  260. ['.ctor'] = function(obj, a)
  261. print('GenericClass<double>', obj, a)
  262. end;
  263. Func1 = function(obj)
  264. print('GenericClass<double>.Func1', obj)
  265. end;
  266. Func2 = function(obj)
  267. print('GenericClass<double>.Func2', obj)
  268. return 1314
  269. end
  270. })
  271. ");
  272. genericObj = new GenericClass<double>(1.1);
  273. genericObj.Func1();
  274. Debug.Log(genericObj.Func2());
  275. InnerTypeTest itt = new InnerTypeTest();
  276. itt.Foo();
  277. luaenv.DoString(@"
  278. xlua.hotfix(CS.InnerTypeTest, 'Bar', function(obj)
  279. print('lua Bar', obj)
  280. return {x = 10, y = 20}
  281. end)
  282. ");
  283. itt.Foo();
  284. StructTest st = new StructTest(gameObject);
  285. Debug.Log("go=" + st.GetGo(123, "john"));
  286. luaenv.DoString(@"
  287. xlua.hotfix(CS.StructTest, 'GetGo', function(self, a, b)
  288. print('GetGo', self, a, b)
  289. return nil
  290. end)
  291. ");
  292. Debug.Log("go=" + st.GetGo(123, "john"));
  293. GenericStruct<int> gs = new GenericStruct<int>(1);
  294. Debug.Log("gs.GetA()=" + gs.GetA(123));
  295. luaenv.DoString(@"
  296. xlua.hotfix(CS['GenericStruct`1[System.Int32]'], 'GetA', function(self, a)
  297. print('GetA',self, a)
  298. return 789
  299. end)
  300. ");
  301. Debug.Log("gs.GetA()=" + gs.GetA(123));
  302. try
  303. {
  304. calc.TestOut(100, out num, ref str, gameObject);
  305. }
  306. catch(LuaException e)
  307. {
  308. Debug.Log("throw in lua an catch in c# ok, e.Message:" + e.Message);
  309. }
  310. }
  311. void TestStateful()
  312. {
  313. StatefullTest sft = new StatefullTest();
  314. sft.AProp = 10;
  315. Debug.Log("sft.AProp:" + sft.AProp);
  316. sft["1"] = 1;
  317. Debug.Log("sft['1']:" + sft["1"]);
  318. System.Action<int, double> cb = (a, b) =>
  319. {
  320. Debug.Log("a:" + a + ",b:" + b);
  321. };
  322. sft.AEvent += cb;
  323. sft.Start();
  324. sft.Start();
  325. sft.AEvent -= cb;
  326. sft.Start();
  327. StatefullTest.StaticFunc(1, 2);
  328. StatefullTest.StaticFunc("e", 3, 4);
  329. sft.GenericTest(1);
  330. sft.GenericTest("hehe");
  331. }
  332. // Update is called once per frame
  333. void Update () {
  334. }
  335. }

StatefullTest.cs

  1. using UnityEngine;
  2. using System.Collections;
  3. [XLua.Hotfix(XLua.HotfixFlag.Stateful)]
  4. public class StatefullTest {
  5. public StatefullTest()
  6. {
  7. }
  8. public StatefullTest(int a, int b)
  9. {
  10. if (a > 0)
  11. {
  12. return;
  13. }
  14. Debug.Log("a=" + a);
  15. if (b > 0)
  16. {
  17. return;
  18. }
  19. else
  20. {
  21. if (a + b > 0)
  22. {
  23. return;
  24. }
  25. }
  26. Debug.Log("b=" + b);
  27. }
  28. public int AProp
  29. {
  30. get;
  31. set;
  32. }
  33. public event System.Action<int, double> AEvent;
  34. public int this[string field]
  35. {
  36. get
  37. {
  38. return 1;
  39. }
  40. set
  41. {
  42. }
  43. }
  44. public void Start () {
  45. }
  46. void Update () {
  47. }
  48. public void GenericTest<T>(T a)
  49. {
  50. }
  51. static public void StaticFunc(int a, int b)
  52. {
  53. }
  54. static public void StaticFunc(string a, int b, int c)
  55. {
  56. }
  57. ~StatefullTest()
  58. {
  59. Debug.Log("~StatefullTest");
  60. }
  61. }

?