調用/執行 熱更中的方法
調用熱更代碼中方法,寫在AppDomain中,記錄一下主要幾個方法:
AppDomain.LoadAssembly 加載熱更dll
執行熱更代碼的方法,有兩種方式:
- appdomain.Invoke("HotFix_Project.InstanceClass", "StaticFunTest", null, null);
- 預先獲得IMethod,可以減低每次調用查找方法耗用的時間,代碼如下:
//預先獲得IMethod,可以減低每次調用查找方法耗用的時間
IType type = appdomain.LoadedTypes["HotFix_Project.InstanceClass"];
//根據方法名稱和參數個數獲取方法
IMethod method = type.GetMethod("StaticFunTest", 0);
appdomain.Invoke(method, null, null);
監聽主工程的委托
在熱更工程中監聽主工程的事件,由主工程觸發。
如果非Action或Func,則需要在主工程中寫適配器,所以建議使用系統自帶的Action和Func。
繼承主工程,實現主工程接口
因為跨域繼承必須要注冊適配器。 如果是熱更DLL里面繼承熱更里面的類型,不需要任何注冊。
適配器代碼怎么寫
Demo中有三個適配器示例,都繼承自CrossBindingAdaptor,適配器中有內部類,繼承或實現接口的方法。
public class MonoBehaviourAdapter : CrossBindingAdaptor
{
public override Type BaseCLRType {get { return typeof(MonoBehaviour); } }
public override Type AdaptorType {get { return typeof(Adaptor); } }
public override object CreateCLRInstance(ILRuntime.Runtime.Enviorment.AppDomain appdomain, ILTypeInstance instance)
{
return new Adaptor(appdomain, instance);
}
//為了完整實現MonoBehaviour的所有特性,這個Adapter還得擴展,這里只拋磚引玉,只實現了最常用的Awake, Start和Update
public class Adaptor : MonoBehaviour, CrossBindingAdaptorType
{
ILTypeInstance instance;
ILRuntime.Runtime.Enviorment.AppDomain appdomain;
public Adaptor()
{
}
public Adaptor(ILRuntime.Runtime.Enviorment.AppDomain appdomain, ILTypeInstance instance)
{
this.appdomain = appdomain;
this.instance = instance;
}
public ILTypeInstance ILInstance { get { return instance; } set { instance = value; } }
public ILRuntime.Runtime.Enviorment.AppDomain AppDomain { get { return appdomain; } set { appdomain = value; } }
public void Awake() {}
void Start(){}
void Update(){ }
public override string ToString(){ }
}
}
CLR重定向/熱補丁
CLRRedirectionDemo,需要在AppDomain中注冊 RegisterCLRMethodRedirection
在熱更工程中調用主工程的代碼時會重定向新的實現,新手可以從修改CLR生成的綁定代碼開始。
例子是修改Debug.Log方法,在熱更中打印的日志也能顯示堆棧信息。
生成適配代碼
類似於slua/tolua/xlua一樣, 把在熱更工程會用到的類添加到列表中,然后生成適配代碼。
ILRuntime提供一個智能分析在熱更工程使用的代碼。
在熱更工程使用協程
官方例子是調用主工程的方法來啟動協程,我測試熱更工程也可以調用MonoBehaviour的方法開啟協程。
熱更工程代碼如下:
public static void RunTest()
{
Debug.Log("熱更工程中開啟協程");
CoroutineDemo.Instance.StartCoroutine(Coroutine());
}
static System.Collections.IEnumerator Coroutine()
{
Debug.Log("開始協程,t=" + Time.time);
yield return new WaitForSeconds(3);
Debug.Log("等待了3秒,t=" + Time.time);
}
對主工程的值類型做綁定
那些需要做綁定?Unity的常用值類型,比如:Vector3,Vector2
這項操作會提升性能,減少額外的CPU開銷和GC Alloc。
方法:
AppDomain.RegisterValueTypeBinder(typeof(Vector3), new Vector3Binder());
Demo 做了十萬次運算,打印日志如下:
Value: a=(100001.0, 100002.0, 100003.0),dot=0, time = 750ms
Value: a=(100001.0, 100002.0, 100003.0),dot=0, time = 1911ms
Value: a=(-0.4, -0.8, -1.7, -5.1),dot=-124.7494, time = 604ms
Value: a=(-0.4, -0.8, -1.7, -5.1),dot=-124.7494, time = 1550ms
Value: a=(100001.0, 100002.0),dot=0, time = 710ms
Value: a=(100001.0, 100002.0),dot=0, time = 1902ms
我的小結
可以把熱更工程的VS項目(HotFix_Project.csproj)添加到Unity生成的解決方案中(ILRuntimeDemo.sln),在開發期不用兩個工程切換。
由於Unity 2018和Unity5的目錄結構調整,**Library\UnityAssemblies\ **在Unity2018目錄沒有
所以我在熱更工程引用 Unity_2018_2_7f1\Editor\Data\Managed\UnityEngine\UnityEngine.CoreModule.dll
熱更工程最常做的事情
根據我們以往的項目使用Lua做為熱更腳本為例,我們在熱更工程做的最多的事情:
-
在熱更工程中調用主工程的方法,或監聽主工程的事件,監聽Unity組件觸發的事件。
-
熱更工程調用主工程接口加載資源
-
熱更工程處理UI代碼邏輯
-
讀取配置,對配置解析
-
熱更工程中處理網絡的回調
-
熱更工程基本處理所有的業務邏輯
為什么要寫適配器
因為ILRuntime可以理解為藍大寫的C#虛擬機,這個虛擬機要在運行時和Unity的腳本進行交互。
由於IOS的AOT限制,在運行時ILRuntime中是不知道Unity中的類型,所以需要我們在主工程寫適配器讓ILRuntime知道如何調用在Unity的代碼,或當Unity的事件觸發時讓ILRuntime能夠監聽到。