騰訊開源的 Unity全系列 代碼邏輯熱修復方案--InjectFix

InjectFix

騰訊開源的 Unity 代碼邏輯熱修復方案

Unity代碼邏輯熱修復

可用於Unity業務的bug修復,支持Unity全系列,全平台。

幾個亮點

  • 直接在Unity工程上修改C#即可更新
  • 老項目無需修改原有代碼即可使用
  • 每個遊戲一份私有補丁格式,安全更有保障

編譯安裝

  • Window下打開源碼包的Source\VSProj\build_for_unity.bat,UNITY_HOME變量的值修改為指向本機unity安裝目錄
  • 運行build_for_unity.bat

複製

這裡對應的是一個Unity工程目錄

  • IFixToolKit拷貝到Unity項目的Assets同級目錄
  • Assets/IFix,Assets/Plugins拷貝到Unity項目的Assets下

接入示例

判斷有補丁就加載補丁

var patchPath = "./Assets/IFix/Resources/Assembly-CSharp.ill.bytes";
if (File.Exists(patchPath))
{
PatchManager.Load(new FileStream(patchPath, FileMode.Open));
}

配置

熱補丁的實現依賴於提前做些靜態代碼插入,所以需要配置對哪些類預處理,配置了才能被修復。一般而言,只要不是性能要求很苛刻的類都可以加入。

iFix支持動態和靜態列表方式,由於類型往往比較多,動態列表會方便些。下面是一個實例,配置XLua名字空間下除匿名類之外的所有類型。

[Configure]
public class InterpertConfig {
[IFix]
static IEnumerable<Type> ToProcess
{
get
{
return (from type in Assembly.Load("Assembly-CSharp").GetTypes()
where type.Namespace == "XLua" && !type.Name.Contains("<")
select type);
}
}
}

划下重點:

  • 配置類打上Configure標籤
  • 配置的屬性打上IFix標籤,而且必須是 static 類型

動態配置除了不用一個個配,還可能有其它額外好處,比如上述配置,後續該名字空間下增刪類,都不需要更改配置。

配置好後,打包手機版本會自動預處理,如果希望自動化打包,也可以手動調用IFix.Editor.IFixEditor.InjectAllAssemblys函數。

補丁製作

對需要打補丁的函數打上Patch標籤

[Patch]
public int Add(int a, int b)
{
return a + b;
}

執行"InjectFix/Fix"菜單。

補丁製作成功後會放到工程目錄下,文件名為“{Dll Name}.patch.bytes”(比如:“Assembly-CSharp.patch.bytes”),上傳補丁到手機,加載就能看到效果。

注意事項:如果要Patch的函數存在條件編譯宏,比如這樣的代碼:

[Patch]
public void Job(int a)
{
#if UNITY_EDITOR
Foo();
#endif
#if !UNITY_EDITOR
Bar();
#endif
}

如果還是直接在編輯器下直接生成補丁,將會比手機上運行多調用了個Foo,少調用了個Bar,這可能會導致各種問題:邏輯不對,調用了編輯器專用函數而導致找不到要調用的函數等等。

這時可以按對應平台的編譯參數把Assembly-CSharp.dll編譯出來,然後調用IFix.Editor.IFixEditor.GenPatch去生成補丁。

Unity編譯是在工程的Temp目錄新建一個文件,把命令行參數放到那個文件,然後執行類似(目錄根據自己的unity安裝情況而定)如下命令進行編譯:

"D:\Program Files\Unity201702\Editor\Data\MonoBleedingEdge\bin\mono.exe" "D:\Program Files\Unity201702\Editor\Data\MonoBleedingEdge\lib\mono\4.5\mcs.exe" @Temp/UnityTempFile-55a959adddae39f4aaa18507dd165989

你可以嘗試一次編輯器下的手機版本打包,然後到工程目錄下的Temp目錄把那個臨時文件拷貝出來(編譯完會自動刪掉,所以要手快)。

這個文件大多數地方都不會變的,變的主要是C#文件列表,可以改為動態生成這個文件:C#文件列表根據當前項目生成,其它保持不變。然後用這個文件作為輸入來編譯。

github地址:

https://github.com/tencent/injectfix

更多更優質的資訊,請關注我,你的支持會鼓勵我不斷分享更多更好的優質文章。