ILRuntime使用调试器 基于TCP的调试,没有机器限制,可以调试本地,也可以调试真机。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 void  InitializeILRuntime ( )    { 		……         appdomain.DebugService.StartDebugService(56000 );     } IEnumerator WaitDebuggerAndRun ( )     {         Debug.Log("等待调试器连接" );         while  (!appdomain.DebugService.IsDebuggerAttached)         {             yield  return  null ;         }         yield  return  new  WaitForSeconds (1  ) ;         OnHotFixLoaded();     } 
 
ILRuntime使用委托 在热更里面创建的委托实例,传到主工程的变量里,称为委托实例的跨域。这种情况需要在主工程注册适配器才能正常运行。 1.由于IL2CPP的特性,使用到不同参数组合的委托需要注册委托适配器、 2.如果使用非Action/Func类型委托,需要注册委托转换器。 3.尽量避免不必要的跨域委托调用。 4.尽量使用Action/Func这两个万能委托类型。
DelegateDemo.cs 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 70 71 72 73 74 public  delegate  void  TestDelegateMethod (int  a ) ;public  delegate  string  TestDelegateFunction (int  a ) ;public  class  DelegateDemo  : MonoBehaviour {     public  static  TestDelegateMethod TestMethodDelegate;     public  static  TestDelegateFunction TestFunctionDelegate;     public  static  System.Action<string > TestActionDelegate;     void  InitializeILRuntime ( )     { #if  DEBUG && (UNITY_EDITOR || UNITY_ANDROID || UNITY_IPHONE)                  appdomain.UnityMainThreadID = System.Threading.Thread.CurrentThread.ManagedThreadId; #endif                            appdomain.DelegateManager.RegisterMethodDelegate<int >();                  appdomain.DelegateManager.RegisterFunctionDelegate<int , string >();                  appdomain.DelegateManager.RegisterMethodDelegate<string >();                                    appdomain.DelegateManager.RegisterDelegateConvertor<TestDelegateMethod>((action) =>         {                          return  new  TestDelegateMethod((a) =>             {                                  ((System.Action<int >)action)(a);             });         });                  appdomain.DelegateManager.RegisterDelegateConvertor<TestDelegateFunction>((action) =>         {             return  new  TestDelegateFunction((a) =>             {                 return  ((System.Func<int , string >)action)(a);             });         });                  appdomain.DelegateManager.RegisterDelegateConvertor<UnityEngine.Events.UnityAction<float >>((action) =>         {             return  new  UnityEngine.Events.UnityAction<float >((a) =>             {                 ((System.Action<float >)action)(a);             });         });     }     void  OnHotFixLoaded ( )     {         Debug.Log("完全在热更DLL内部使用的委托,直接可用,不需要做任何处理" );                  Debug.Log("如果需要跨域调用委托(将热更DLL里面的委托实例传到Unity主工程用), 就需要注册适配器" );         Debug.Log("这是因为iOS的IL2CPP模式下,不能动态生成类型,为了避免出现不可预知的问题,我们没有通过反射的方式创建委托实例,因此需要手动进行一些注册" );         Debug.Log("如果没有注册委托适配器,运行时会报错并提示需要的注册代码,直接复制粘贴到ILRuntime初始化的地方" );         appdomain.Invoke("HotFix_Project.TestDelegate" , "Initialize2" , null , null );         appdomain.Invoke("HotFix_Project.TestDelegate" , "RunTest2" , null , null );         Debug.Log("运行成功,我们可以看见,用Action或者Func当作委托类型的话,可以避免写转换器,所以项目中在不必要的情况下尽量只用Action和Func" );         Debug.Log("另外应该尽量减少不必要的跨域委托调用,如果委托只在热更DLL中用,是不需要进行任何注册的" );         Debug.Log("---------" );         Debug.Log("我们再来在Unity主工程中调用一下刚刚的委托试试" );         TestMethodDelegate(789 );         var  str = TestFunctionDelegate(098 );         Debug.Log("!! OnHotFixLoaded str = "  + str);         TestActionDelegate("Hello From Unity Main Project" );     } } 
 
HotFix_Project.TestDelegate 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 namespace  HotFix_Project {     public  class  TestDelegate      {         static  TestDelegateMethod delegateMethod;         static  TestDelegateFunction delegateFunc;         static  Action<string > delegateAction;         public  static  void  Initialize ( )         {             delegateMethod = Method;             delegateFunc = Function;             delegateAction = Action;         }         public  static  void  RunTest ( )         {             delegateMethod(123 );             var  res = delegateFunc(456 );             UnityEngine.Debug.Log("!! TestDelegate.RunTest res = "  + res);             delegateAction("rrr" );         }         public  static  void  Initialize2 ( )         {             DelegateDemo.TestMethodDelegate = Method;             DelegateDemo.TestFunctionDelegate = Function;             DelegateDemo.TestActionDelegate = Action;         }         public  static  void  RunTest2 ( )         {             DelegateDemo.TestMethodDelegate(123 );             var  res = DelegateDemo.TestFunctionDelegate(456 );             UnityEngine.Debug.Log("!! TestDelegate.RunTest2 res = "  + res);             DelegateDemo.TestActionDelegate("rrr" );         }         static  void  Method (int  a )         {             UnityEngine.Debug.Log("!! TestDelegate.Method, a = "  + a);         }         static  string  Function (int  a )         {             return  a.ToString();         }         static  void  Action (string  a )         {             UnityEngine.Debug.Log("!! TestDelegate.Action, a = "  + a);         }     } } 
 
在ILRuntime继承主工程 ILRuntime中跨域继承 
1.热更DLL中继承Unity主工程的类型称为跨域继承。 2.跨域继承需要编写跨域继承适配器。 3.热更DLL不能同时继承或实现1个以上主工程的类型或接口。 4.尽量避免跨域继承,尤其避免继承MonoBehaviour。
Inheritance.cs 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 void  OnHotFixLoaded ( )    {         Debug.Log("首先我们来创建热更里的类实例" );         TestClassBase obj;         Debug.Log("现在我们来注册适配器, 该适配器由ILRuntime/Generate Cross Binding Adapter菜单命令自动生成" );         appdomain.RegisterCrossBindingAdaptor(new  TestClassBaseAdapter());         Debug.Log("现在再来尝试创建一个实例" );         obj = appdomain.Instantiate<TestClassBase>("HotFix_Project.TestInheritance" );         Debug.Log("现在来调用成员方法" );         obj.TestAbstract(123 );         obj.TestVirtual("Hello" );         obj.Value = 233 ;         Debug.LogFormat("obj.Value={0}" , obj.Value);         Debug.Log("现在换个方式创建实例" );         obj = appdomain.Invoke("HotFix_Project.TestInheritance" , "NewObject" , null , null ) as  TestClassBase;         obj.TestAbstract(456 );         obj.TestVirtual("Foobar" );         obj.Value = 2333333 ;         Debug.LogFormat("obj.Value={0}" , obj.Value);     } 
 
主工程TestClassBase 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public  abstract  class  TestClassBase {     public  virtual  int  Value     {         get          {             return  0 ;         }         set          {         }     }     public  virtual  void  TestVirtual (string  str )     {         Debug.Log("!! TestClassBase.TestVirtual, str = "  + str);     }     public  abstract  void  TestAbstract (int  gg ) ; } 
 
适配器InheritanceAdapter.cs 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 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 public  class  TestClassBaseAdapter  : CrossBindingAdaptor     {         static  CrossBindingFunctionInfo <System.Int32 > mget_Value_0  = new  CrossBindingFunctionInfo<System.Int32>("get_Value" );         static  CrossBindingMethodInfo <System.Int32 > mset_Value_1  = new  CrossBindingMethodInfo<System.Int32>("set_Value" );         static  CrossBindingMethodInfo <System.String > mTestVirtual_2  = new  CrossBindingMethodInfo<System.String>("TestVirtual" );         static  CrossBindingMethodInfo <System.Int32 > mTestAbstract_3  = new  CrossBindingMethodInfo<System.Int32>("TestAbstract" ); 		         public  override  Type BaseCLRType         {             get              {                 return  typeof (global ::TestClassBase); 				             }         }         public  override  Type AdaptorType         {             get              {                 return  typeof (Adapter); 				             }         }         public  override  object  CreateCLRInstance (ILRuntime.Runtime.Enviorment.AppDomain appdomain, ILTypeInstance instance )         {             return  new  Adapter(appdomain, instance);         }         public  class  Adapter  : global ::TestClassBase , CrossBindingAdaptorType          {             ILTypeInstance instance;             ILRuntime.Runtime.Enviorment.AppDomain appdomain;             public  Adapter ( )             {             }             public  Adapter (ILRuntime.Runtime.Enviorment.AppDomain appdomain, ILTypeInstance instance )             {                 this .appdomain = appdomain;                 this .instance = instance;             }             public  ILTypeInstance ILInstance { get  { return  instance; } }             public  override  void  TestVirtual (System.String str )             {                 if  (mTestVirtual_2.CheckShouldInvokeBase(this .instance))                     base .TestVirtual(str);                 else                      mTestVirtual_2.Invoke(this .instance, str);             }             public  override  void  TestAbstract (System.Int32 gg )             {                 mTestAbstract_3.Invoke(this .instance, gg);             }             public  override  System.Int32 Value             {             get              {                 if  (mget_Value_0.CheckShouldInvokeBase(this .instance))                     return  base .Value;                 else                      return  mget_Value_0.Invoke(this .instance);             }             set              {                 if  (mset_Value_1.CheckShouldInvokeBase(this .instance))                     base .Value = value ;                 else                      mset_Value_1.Invoke(this .instance, value );             }             }             public  override  string  ToString ( )             {                 IMethod m = appdomain.ObjectType.GetMethod("ToString" , 0 );                 m = instance.Type.GetVirtualMethod(m);                 if  (m == null  || m is  ILMethod)                 {                     return  instance.ToString();                 }                 else                      return  instance.Type.FullName;             }         }     } 
 
HotFix_Project.TestInheritance 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20     public  class  TestInheritance  : TestClassBase      {         public  override  int  Value { get ; set ; }         public  override  void  TestAbstract (int  gg )         {             UnityEngine.Debug.Log("!! TestInheritance.TestAbstract gg ="  + gg);         }         public  override  void  TestVirtual (string  str )         {             base .TestVirtual(str);             UnityEngine.Debug.Log("!! TestInheritance.TestVirtual str ="  + str);         }         public  static  TestInheritance NewObject ( )         {             return  new  HotFix_Project.TestInheritance();         }     }