InjectFix 学习
unity版本: 2018.4.6f1
https://github.com/Tencent/InjectFix
学习项目 void87/InjectFixLearn (github.com)
安装
编译
- Window下打开源码包的Source\VSProj\build_for_unity.bat,UNITY_HOME变量的值修改为指向本机unity安装目录
- 运行build_for_unity.bat
复制
这里对应的是一个Unity工程目录
- IFixToolKit拷贝到Unity项目的Assets同级目录
- Assets/IFix,Assets/Plugins拷贝到Unity项目的Assets下
HelloWorld
HelloWorld(编辑器下体验iFix)
1. 模拟有bug的项目
原始Calculator(加和乘都是错的)
namespace IFix.Test { //HelloworldCfg.cs里配置了这个类型 public class Calculator { //修改成正确的逻辑后,打开如下注释,生成的补丁将修正该函数 //[Patch] public int Add(int a, int b) { return a * b; } public int Sub(int a, int b) { return a / b; } } }
配置类HelloworldCfg
using System.Collections.Generic; using IFix; using System; // 1. 配置类必须打[Configure]标签 // 2. 必须放Editor目录 [Configure] public class HelloworldCfg { [IFix] static IEnumerable<Type> hotfix { get { return new List<Type>() { typeof(IFix.Test.Calculator) }; } } }
Helloworld
using UnityEngine; using IFix.Core; using System.IO; using System.Diagnostics; // 跑不同仔细看文档Doc/example.md public class Helloworld : MonoBehaviour { // check and load patchs void Start () { VirtualMachine.Info = (s) => UnityEngine.Debug.Log(s); //try to load patch for Assembly-CSharp.dll var patch = Resources.Load<TextAsset>("Assembly-CSharp.patch"); if (patch != null) { UnityEngine.Debug.Log("loading Assembly-CSharp.patch ..."); var sw = Stopwatch.StartNew(); PatchManager.Load(new MemoryStream(patch.bytes)); UnityEngine.Debug.Log("patch Assembly-CSharp.patch, using " + sw.ElapsedMilliseconds + " ms"); } test(); } //[IFix.Patch] void test() { var calc = new IFix.Test.Calculator(); //test calc.Add UnityEngine.Debug.Log("10 + 9 = " + calc.Add(10, 9)); //test calc.Sub UnityEngine.Debug.Log("10 - 2 = " + calc.Sub(10, 2)); } }
2. 修复Bug
修改后的Calculator(模拟修bug后,生成文件 Assembly-CSharp.patch.bytes)
namespace IFix.Test { //HelloworldCfg.cs里配置了这个类型 public class Calculator { //修改成正确的逻辑后,打开如下注释,生成的补丁将修正该函数 [Patch] public int Add(int a, int b) { return a + b; // return a * b; } public int Sub(int a, int b) { return a / b; } } }
修复bug后,点击生成
3. 回滚到有bug的代码,模拟发包(包里有bug)
将代码还原成有bug的代码
namespace IFix.Test { //HelloworldCfg.cs里配置了这个类型 public class Calculator { //修改成正确的逻辑后,打开如下注释,生成的补丁将修正该函数 //[Patch] public int Add(int a, int b) { return a * b; } public int Sub(int a, int b) { return a / b; } }
点击.一个版本的包只需要点一次
将Assembly-CSharp.patch.bytes拷贝到
启动带有Assembly-CSharp.patch.bytes补丁的代码
各种测试
IFix.Patch 测试
IFix.Patch 支持普通方法
// IFix.Patch支持普通方法 [IFix.Patch] public int Add(int a, int b) { return a * b; }
IFix.Patch 不支持泛型方法
// IFix.Patch 不支持泛型方法 [IFix.Patch] public void GenericMethod<T>(T t) { UnityEngine.Debug.Log("GenericMethod<T>: " + t); }
参考
IFix.Patch 支持普通方法中调用泛型方法
// IFix.Patch 支持普通方法 [IFix.Patch] public int Add(int a, int b) { // IFix.Patch 支持普通方法中调用泛型方法 InnerGenericMethod<string>("arg"); return a * b; } public void InnerGenericMethod<T>(T t) { UnityEngine.Debug.Log("InnerGenericMethod: " + t); }
参考
IFix.Patch 不支持字段
// IFix.Patch 不支持字段 [IFix.Patch] public string TestField = "TestField";
IFix.Patch 支持普通协程
// IFix.Patch 支持普通协程 [IFix.Patch] public IEnumerator PatchEnumerator() { yield return new WaitForSeconds(1); UnityEngine.Debug.Log("Wait 1 Second"); }
IFix.Patch 不支持构造函数
// IFix.Patch 不支持构造函数 [IFix.Patch] public Calculator() { }
参考
IFix.Patch 支持getter,setter函数
private string testField = "testField"; public string TestProperty { [IFix.Patch] get { return testField; } [IFix.Patch] set { testField = value; } }
参考
IFix.Interpret
IFix.Interpret 支持不带泛型方法的新憎类
// IFix.Interpret 支持不带泛型方法的新增类 [IFix.Interpret] public class NewClass { public Action<object> act; public string testField = "TestField"; public NewClass(string cons) { UnityEngine.Debug.Log("NewClass.Constructor"); } }
IFix.Interpret 不支持带泛型方法的新增类
// IFix.Interpret 不支持带泛型方法的新增类 [IFix.Interpret] public class PatchClass { public void PatchGenericMethod<T>(T t) { UnityEngine.Debug.Log(t); } }
IFix.Interpret 支持新增普通方法
// IFix.Interpret 支持新增普通方法 [IFix.Interpret] public void PatchMethod() { UnityEngine.Debug.Log("PatchMethod"); }
参考
IFix.Interpret 不支持新增泛型方法
// IFix.Interpret 不支持新增泛型方法 [IFix.Interpret] public void PatchGenericMethod<T>(T t) { UnityEngine.Debug.Log("PatchGenericMethod"); }
IFix.Interpret 支持新增类继承新增类
[IFix.Interpret] public class PatchBaseClass { public void BaseMethod() { UnityEngine.Debug.Log("BaseMethod"); } } // IFix.Interpret 支持新增类继承新增类 [IFix.Interpret] public class PatchChildClass : PatchBaseClass { public void ChildMethod() { UnityEngine.Debug.Log("ChildMethod"); } }
参考
IFix.Interpret 不支持字段
// IFix.Patch 不支持字段 [IFix.Interpret] public string TestField = "TestField";
参考
IFix.Interpret 不支持构造函数
// IFix.Interpret 不支持构造函数 [IFix.Interpret] public Calculator() { }
IFix.Interpret支持协程,但有限制
// 非热更代码里用过 IEnumerator private IEnumerator IE_Main() { yield return new WaitForEndOfFrame(); Debug.Log("IE_Main"); } [IFix.Interpret] private IEnumerator IE_Patch() { // 非热更代码里用过 IEnumerator, 热更代码里可以使用 yield return new WaitForSeconds(1); yield return new WaitForEndOfFrame(); yield return 0; yield return null; Debug.Log("IE_Patch"); yield break; }
[IFix.Interpret] public IEnumerator IE_Patch() { // 非热更代码里没有用过 IEnumerator, 热更代码里不可以使用 yield return new WaitForSeconds(1); yield return new WaitForEndOfFrame(); yield return 0; yield return null; Debug.Log("IE_Patch"); yield break; }
参考
IFix.Interpret不支持Struct
参考
IFix.CustomBridge
热更代码新增实现非热更代码里的接口时,需要在非热更代码里增加处理, 热更代码目前不支持继承非热更代码里的原生类
using System; using System.Collections; using System.Collections.Generic; using UnityEngine; public class Test : MonoBehaviour { [IFix.Patch] void Start() { PatchClassInheritInterface pcii = new PatchClassInheritInterface(); pcii.TestInterfaceMethod(); //PatchClassInheritClass pcic = new PatchClassInheritClass(); //pcic.TestMethod(); } } // 非热更接口 public interface TestInterface { void TestInterfaceMethod(); } // 热更新增类能继承非热更原生接口 [IFix.Interpret] public class PatchClassInheritInterface : TestInterface { public void TestInterfaceMethod() { UnityEngine.Debug.Log("TestInterfaceMethod"); } } //// 非热更类 //public class TestClass { // public virtual void TestMethod() { // Debug.Log("TestMethod"); // } //} //// 热更新增类不能继承非热更原生类 //[IFix.Interpret] //public class PatchClassInheritClass : TestClass { // public override void TestMethod() { // Debug.Log("TestMethod"); // } //} // 要在非热更代码里提前加上 [IFix.CustomBridge] public static class AdditionalBridge { static List<Type> bridge = new List<Type>() { typeof(TestInterface), // typeof(TestClass) // 目前不支持, 热更新增类继承非热更原生接口 }; }
参考
CustomBridge的新增类只支持interface,不支持class
IL2CPP相关
Some questions about Fix in IL2CPP mode
版本相关
async
Instruction
使用 build_for_unity.bat 生成的 Instruction.cs
/* * Tencent is pleased to support the open source community by making InjectFix available. * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. * InjectFix is licensed under the MIT License, except for the third-party components listed in the file 'LICENSE' which may be subject to their corresponding license terms. * This file is subject to the terms and conditions defined in file 'LICENSE', which is part of this source code package. */ namespace IFix.Core { public enum Code { Newobj, //Pseudo instruction StackSpace, Ldelem_I8, Pop, Ldelem_U4, Constrained, Throw, Ldc_R4, Cpblk, Sizeof, Stind_I8, Not, Cpobj, Unaligned, Ldelem_U1, Ldelem_I1, CallExtern, Ldelem_R4, Conv_Ovf_I2_Un, Sub, Sub_Ovf_Un, Stind_R8, Ldind_U1, Ldsflda, Ble, Localloc, Ldstr, Add, Stelem_R4, Unbox_Any, Conv_U, Initblk, Leave, Stind_I, Conv_I2, Cgt, Stind_I1, Stind_I2, Conv_Ovf_U1, Ckfinite, Ldind_U2, Ldfld, Box, Conv_Ovf_U, Bgt_Un, Bge_Un, Break, Blt, Ldc_I8, Conv_Ovf_U8_Un, Conv_R4, Stelem_Any, Beq, Volatile, Ldind_U4, //Calli, Ldloca, Ldtype, // custom Ldelema, Ldobj, Mkrefany, Newanon, Ldelem_I4, Stobj, Mul, Ldloc, Stind_Ref, Ldelem_R8, Stsfld, Rem_Un, Callvirt, Ldind_I2, Shr, No, Stind_R4, Ldind_I8, Conv_R_Un, Sub_Ovf, Initobj, Ldind_Ref, Refanytype, Stelem_I2, Ldlen, Stelem_I8, Ldind_I1, Ldarg, Conv_Ovf_I, Shl, Ldelem_Any, Stloc, Brfalse, Conv_Ovf_I4, Bge, Endfilter, Stelem_Ref, Conv_U1, Newarr, Ldelem_Ref, Conv_Ovf_I8_Un, Conv_Ovf_U8, Brtrue, Castclass, Conv_U8, Stelem_I, Dup, Conv_Ovf_I2, Readonly, Stelem_R8, Conv_Ovf_U1_Un, Conv_Ovf_I8, Ldind_R4, Clt_Un, Starg, Conv_I4, Add_Ovf, Conv_Ovf_I_Un, Ldtoken, Conv_Ovf_I4_Un, Ldind_R8, Conv_Ovf_U4_Un, Ldc_R8, Ldelem_U2, Div, Conv_I8, Mul_Ovf_Un, Cgt_Un, Unbox, Ldnull, Ldvirtftn, Callvirtvirt, Ble_Un, Conv_Ovf_U2, Endfinally, Div_Un, Bgt, Conv_Ovf_I1, Ldarga, Br, Conv_I1, Ldelem_I2, Arglist, Conv_Ovf_U4, Ceq, And, Stfld, Conv_R8, Stind_I4, Refanyval, Ldelem_I, Tail, Blt_Un, Rethrow, Call, Jmp, Conv_U4, Shr_Un, Stelem_I1, Stelem_I4, Ldsfld, Conv_Ovf_U2_Un, Mul_Ovf, Ldc_I4, Ldind_I, Ldflda, Ret, Nop, Conv_I, Neg, Conv_Ovf_I1_Un, Clt, Conv_U2, Bne_Un, Switch, Isinst, Ldftn, Conv_Ovf_U_Un, Rem, Ldind_I4, Xor, Add_Ovf_Un, Or, } [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)] public struct Instruction { /// <summary> /// 指令MAGIC /// </summary> public const ulong INSTRUCTION_FORMAT_MAGIC = 5158825760788742785; /// <summary> /// 当前指令 /// </summary> public Code Code; /// <summary> /// 操作数 /// </summary> public int Operand; } public enum ExceptionHandlerType { Catch = 0, Filter = 1, Finally = 2, Fault = 4 } public sealed class ExceptionHandler { public System.Type CatchType; public int CatchTypeId; public int HandlerEnd; public int HandlerStart; public ExceptionHandlerType HandlerType; public int TryEnd; public int TryStart; } }
反编译 IFix.exe 后的相关代码
using System; namespace IFix.Core { // Token: 0x02000002 RID: 2 public enum Code { // Token: 0x04000002 RID: 2 Newobj, // Token: 0x04000003 RID: 3 StackSpace, // Token: 0x04000004 RID: 4 Ldelem_I8, // Token: 0x04000005 RID: 5 Pop, // Token: 0x04000006 RID: 6 Ldelem_U4, // Token: 0x04000007 RID: 7 Constrained, // Token: 0x04000008 RID: 8 Throw, // Token: 0x04000009 RID: 9 Ldc_R4, // Token: 0x0400000A RID: 10 Cpblk, // Token: 0x0400000B RID: 11 Sizeof, // Token: 0x0400000C RID: 12 Stind_I8, // Token: 0x0400000D RID: 13 Not, // Token: 0x0400000E RID: 14 Cpobj, // Token: 0x0400000F RID: 15 Unaligned, // Token: 0x04000010 RID: 16 Ldelem_U1, // Token: 0x04000011 RID: 17 Ldelem_I1, // Token: 0x04000012 RID: 18 CallExtern, // Token: 0x04000013 RID: 19 Ldelem_R4, // Token: 0x04000014 RID: 20 Conv_Ovf_I2_Un, // Token: 0x04000015 RID: 21 Sub, // Token: 0x04000016 RID: 22 Sub_Ovf_Un, // Token: 0x04000017 RID: 23 Stind_R8, // Token: 0x04000018 RID: 24 Ldind_U1, // Token: 0x04000019 RID: 25 Ldsflda, // Token: 0x0400001A RID: 26 Ble, // Token: 0x0400001B RID: 27 Localloc, // Token: 0x0400001C RID: 28 Ldstr, // Token: 0x0400001D RID: 29 Add, // Token: 0x0400001E RID: 30 Stelem_R4, // Token: 0x0400001F RID: 31 Unbox_Any, // Token: 0x04000020 RID: 32 Conv_U, // Token: 0x04000021 RID: 33 Initblk, // Token: 0x04000022 RID: 34 Leave, // Token: 0x04000023 RID: 35 Stind_I, // Token: 0x04000024 RID: 36 Conv_I2, // Token: 0x04000025 RID: 37 Cgt, // Token: 0x04000026 RID: 38 Stind_I1, // Token: 0x04000027 RID: 39 Stind_I2, // Token: 0x04000028 RID: 40 Conv_Ovf_U1, // Token: 0x04000029 RID: 41 Ckfinite, // Token: 0x0400002A RID: 42 Ldind_U2, // Token: 0x0400002B RID: 43 Ldfld, // Token: 0x0400002C RID: 44 Box, // Token: 0x0400002D RID: 45 Conv_Ovf_U, // Token: 0x0400002E RID: 46 Bgt_Un, // Token: 0x0400002F RID: 47 Bge_Un, // Token: 0x04000030 RID: 48 Break, // Token: 0x04000031 RID: 49 Blt, // Token: 0x04000032 RID: 50 Ldc_I8, // Token: 0x04000033 RID: 51 Conv_Ovf_U8_Un, // Token: 0x04000034 RID: 52 Conv_R4, // Token: 0x04000035 RID: 53 Stelem_Any, // Token: 0x04000036 RID: 54 Beq, // Token: 0x04000037 RID: 55 Volatile, // Token: 0x04000038 RID: 56 Ldind_U4, // Token: 0x04000039 RID: 57 Ldloca, // Token: 0x0400003A RID: 58 Ldtype, // Token: 0x0400003B RID: 59 Ldelema, // Token: 0x0400003C RID: 60 Ldobj, // Token: 0x0400003D RID: 61 Mkrefany, // Token: 0x0400003E RID: 62 Newanon, // Token: 0x0400003F RID: 63 Ldelem_I4, // Token: 0x04000040 RID: 64 Stobj, // Token: 0x04000041 RID: 65 Mul, // Token: 0x04000042 RID: 66 Ldloc, // Token: 0x04000043 RID: 67 Stind_Ref, // Token: 0x04000044 RID: 68 Ldelem_R8, // Token: 0x04000045 RID: 69 Stsfld, // Token: 0x04000046 RID: 70 Rem_Un, // Token: 0x04000047 RID: 71 Callvirt, // Token: 0x04000048 RID: 72 Ldind_I2, // Token: 0x04000049 RID: 73 Shr, // Token: 0x0400004A RID: 74 No, // Token: 0x0400004B RID: 75 Stind_R4, // Token: 0x0400004C RID: 76 Ldind_I8, // Token: 0x0400004D RID: 77 Conv_R_Un, // Token: 0x0400004E RID: 78 Sub_Ovf, // Token: 0x0400004F RID: 79 Initobj, // Token: 0x04000050 RID: 80 Ldind_Ref, // Token: 0x04000051 RID: 81 Refanytype, // Token: 0x04000052 RID: 82 Stelem_I2, // Token: 0x04000053 RID: 83 Ldlen, // Token: 0x04000054 RID: 84 Stelem_I8, // Token: 0x04000055 RID: 85 Ldind_I1, // Token: 0x04000056 RID: 86 Ldarg, // Token: 0x04000057 RID: 87 Conv_Ovf_I, // Token: 0x04000058 RID: 88 Shl, // Token: 0x04000059 RID: 89 Ldelem_Any, // Token: 0x0400005A RID: 90 Stloc, // Token: 0x0400005B RID: 91 Brfalse, // Token: 0x0400005C RID: 92 Conv_Ovf_I4, // Token: 0x0400005D RID: 93 Bge, // Token: 0x0400005E RID: 94 Endfilter, // Token: 0x0400005F RID: 95 Stelem_Ref, // Token: 0x04000060 RID: 96 Conv_U1, // Token: 0x04000061 RID: 97 Newarr, // Token: 0x04000062 RID: 98 Ldelem_Ref, // Token: 0x04000063 RID: 99 Conv_Ovf_I8_Un, // Token: 0x04000064 RID: 100 Conv_Ovf_U8, // Token: 0x04000065 RID: 101 Brtrue, // Token: 0x04000066 RID: 102 Castclass, // Token: 0x04000067 RID: 103 Conv_U8, // Token: 0x04000068 RID: 104 Stelem_I, // Token: 0x04000069 RID: 105 Dup, // Token: 0x0400006A RID: 106 Conv_Ovf_I2, // Token: 0x0400006B RID: 107 Readonly, // Token: 0x0400006C RID: 108 Stelem_R8, // Token: 0x0400006D RID: 109 Conv_Ovf_U1_Un, // Token: 0x0400006E RID: 110 Conv_Ovf_I8, // Token: 0x0400006F RID: 111 Ldind_R4, // Token: 0x04000070 RID: 112 Clt_Un, // Token: 0x04000071 RID: 113 Starg, // Token: 0x04000072 RID: 114 Conv_I4, // Token: 0x04000073 RID: 115 Add_Ovf, // Token: 0x04000074 RID: 116 Conv_Ovf_I_Un, // Token: 0x04000075 RID: 117 Ldtoken, // Token: 0x04000076 RID: 118 Conv_Ovf_I4_Un, // Token: 0x04000077 RID: 119 Ldind_R8, // Token: 0x04000078 RID: 120 Conv_Ovf_U4_Un, // Token: 0x04000079 RID: 121 Ldc_R8, // Token: 0x0400007A RID: 122 Ldelem_U2, // Token: 0x0400007B RID: 123 Div, // Token: 0x0400007C RID: 124 Conv_I8, // Token: 0x0400007D RID: 125 Mul_Ovf_Un, // Token: 0x0400007E RID: 126 Cgt_Un, // Token: 0x0400007F RID: 127 Unbox, // Token: 0x04000080 RID: 128 Ldnull, // Token: 0x04000081 RID: 129 Ldvirtftn, // Token: 0x04000082 RID: 130 Callvirtvirt, // Token: 0x04000083 RID: 131 Ble_Un, // Token: 0x04000084 RID: 132 Conv_Ovf_U2, // Token: 0x04000085 RID: 133 Endfinally, // Token: 0x04000086 RID: 134 Div_Un, // Token: 0x04000087 RID: 135 Bgt, // Token: 0x04000088 RID: 136 Conv_Ovf_I1, // Token: 0x04000089 RID: 137 Ldarga, // Token: 0x0400008A RID: 138 Br, // Token: 0x0400008B RID: 139 Conv_I1, // Token: 0x0400008C RID: 140 Ldelem_I2, // Token: 0x0400008D RID: 141 Arglist, // Token: 0x0400008E RID: 142 Conv_Ovf_U4, // Token: 0x0400008F RID: 143 Ceq, // Token: 0x04000090 RID: 144 And, // Token: 0x04000091 RID: 145 Stfld, // Token: 0x04000092 RID: 146 Conv_R8, // Token: 0x04000093 RID: 147 Stind_I4, // Token: 0x04000094 RID: 148 Refanyval, // Token: 0x04000095 RID: 149 Ldelem_I, // Token: 0x04000096 RID: 150 Tail, // Token: 0x04000097 RID: 151 Blt_Un, // Token: 0x04000098 RID: 152 Rethrow, // Token: 0x04000099 RID: 153 Call, // Token: 0x0400009A RID: 154 Jmp, // Token: 0x0400009B RID: 155 Conv_U4, // Token: 0x0400009C RID: 156 Shr_Un, // Token: 0x0400009D RID: 157 Stelem_I1, // Token: 0x0400009E RID: 158 Stelem_I4, // Token: 0x0400009F RID: 159 Ldsfld, // Token: 0x040000A0 RID: 160 Conv_Ovf_U2_Un, // Token: 0x040000A1 RID: 161 Mul_Ovf, // Token: 0x040000A2 RID: 162 Ldc_I4, // Token: 0x040000A3 RID: 163 Ldind_I, // Token: 0x040000A4 RID: 164 Ldflda, // Token: 0x040000A5 RID: 165 Ret, // Token: 0x040000A6 RID: 166 Nop, // Token: 0x040000A7 RID: 167 Conv_I, // Token: 0x040000A8 RID: 168 Neg, // Token: 0x040000A9 RID: 169 Conv_Ovf_I1_Un, // Token: 0x040000AA RID: 170 Clt, // Token: 0x040000AB RID: 171 Conv_U2, // Token: 0x040000AC RID: 172 Bne_Un, // Token: 0x040000AD RID: 173 Switch, // Token: 0x040000AE RID: 174 Isinst, // Token: 0x040000AF RID: 175 Ldftn, // Token: 0x040000B0 RID: 176 Conv_Ovf_U_Un, // Token: 0x040000B1 RID: 177 Rem, // Token: 0x040000B2 RID: 178 Ldind_I4, // Token: 0x040000B3 RID: 179 Xor, // Token: 0x040000B4 RID: 180 Add_Ovf_Un, // Token: 0x040000B5 RID: 181 Or } }
using System; namespace IFix.Core { // Token: 0x02000003 RID: 3 public struct Instruction { // Token: 0x040000B6 RID: 182 public const ulong INSTRUCTION_FORMAT_MAGIC = 5158825760788742785UL; // Token: 0x040000B7 RID: 183 public Code Code; // Token: 0x040000B8 RID: 184 public int Operand; } }
using System; namespace IFix.Core { // Token: 0x02000004 RID: 4 public enum ExceptionHandlerType { // Token: 0x040000BA RID: 186 Catch, // Token: 0x040000BB RID: 187 Filter, // Token: 0x040000BC RID: 188 Finally, // Token: 0x040000BD RID: 189 Fault = 4 } }
using System; namespace IFix.Core { // Token: 0x02000005 RID: 5 public sealed class ExceptionHandler { // Token: 0x06000001 RID: 1 RVA: 0x000020EC File Offset: 0x000002EC public ExceptionHandler() { } // Token: 0x040000BE RID: 190 public Type CatchType; // Token: 0x040000BF RID: 191 public int CatchTypeId; // Token: 0x040000C0 RID: 192 public int HandlerEnd; // Token: 0x040000C1 RID: 193 public int HandlerStart; // Token: 0x040000C2 RID: 194 public ExceptionHandlerType HandlerType; // Token: 0x040000C3 RID: 195 public int TryEnd; // Token: 0x040000C4 RID: 196 public int TryStart; } }
参考
各种Issue
Close
多个 Assembly Definition 的template file 怎么设置?
添加配置文件,添加python构建脚本用于跨平台构建,添加混淆key支持
Warning: read ./Library/ScriptAssemblies/Assembly-CSharp.dll with symbol fail
执行"InjectFix/Fix"后提示please install the ToolKit
修改源码导出新的dll后,xcode工程导出报错,像是IL2CPP转方法报错了 IFix.Core.EvaluationStackOperation::ToObject
编辑器下除了reimport unity工程,有没有更好的方法回滚Inject了之后的dll
Unhandled Exception:System.Exception: Utils/<ReadBinaryFileAsync>d__0 is CompilerGenerated
The type or namespace name `IFix' could not be found
Exception: instruction magic not match
【优化IFix报错日志】使用debug模式运行ifix.exe,报错日志里包含源码文件和行信息,方便查问题
求增加一个Inject和Fix时的UI效果!提醒用户正在Inject或者Fix中!
【实现建议】不用IDMAP,只使用IDTagAttribute。
Error: the new assembly must not be inject, please reimport the project!
当使用 .net4.x async await来进行异步编程时,inject 阶段报异常
> 我也碰到了类似的问题,最简化代码如下,当注入class A的时候将会报错
Unity2019.2.15f1版本打包出来会出现未注入的情况
Unity2019.3.0f3 没有Editor\Data\Mono\bin\gmcs
UnityEditor热更没问题,打包到Android后Load报错
【BugReport】结构体初始化如果不使用new关键字,会报错
虚函数中如果用关键词in修饰struct类型的参数,inject后执行会报错
Fix 和 inject 时弹出 warnning ,并且在Editor下没有看到效果
当hotfix的代码导致游戏崩溃,几乎无法查找明确的堆栈入口信息或者明确的方法信息
最新版本无法生成IFix.Core.dll和IFix.exe
在编辑器模式下初始化Inject报错因为我使用了linq配置
子类没有override父类的函数,打Interpret标签不会生效
IEnumerator<T>的Current在解释执行下报错
[fixbug] CustomBridge 注入跨dll的delegate,InjectFix 时报错
Unity2019 iOS注入失败,Unity2018 iOS注入成功
CustomBridge属性可以做到自动给程序集的所有Delegate和Interface加上Wrapper吗?
请教 Non-static method requires a target 错误
Open
为什么说:InjectFix在对Unity协程,闭包的支持中其实是包含了对新增class的支持?
无法访问Unity的 Debug.unityLogger.logEnabled 属性
TargetException: Non-static method requires a target
使用了BurstCompile的类和结构体不能进行注入,否则加载patch之后会报burst的错误
2019.3.8再编译build_for_unity.bat时找不到gmcs目录
请教下GetTagMethods与GetTagClasses中assembly.CodeBase.IndexOf("ScriptAssemblies") != -1的用意。
//case Code.Stelem_Any: //0.03166702% 泛型中使用?泛型不支持解析,所以不会碰到这指令(我遇到了这个指令没被实现的异常)
增加方法没参数的情况会抛异常Exception: can not load field[*]
杂项
对程序集里的所有方法Inject
// 1. 配置类必须打[Configure]标签 // 2. 必须放Editor目录 [Configure] public class HelloworldCfg { [IFix] static IEnumerable<Type> hotfix { get { return (from type in Assembly.Load("Assembly-CSharp").GetTypes() select type); } } }
[Patch](补丁修改方法)标签,Inject前后DLL对比
为每个方法生成一个枚举ID
2021.6.3 更新
现在已经支持新增字段
相关文章
https://m.ithome.com/html/444969.htm
https://www.zhihu.com/question/345639690/answer/825301379
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步