安装
编译
- 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;
}
}
}
Calculator
配置类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)
};
}
}
}
HelloworldCfg
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));
}
}
Helloworld
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;
}
}
}
Calculator修复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;
}
}
Calculator点击
.一个版本的包只需要点一次
将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 不支持泛型方法
[IFix.Patch]
public void GenericMethod<T>(T t)
{
UnityEngine.Debug.Log("GenericMethod<T>: " + t);
}
IFix.Patch 不支持泛型方法
参考
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 不支持字段
[IFix.Patch]
public string TestField = "TestField";
IFix.Patch 不支持字段
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 不支持构造函数
[IFix.Patch]
public Calculator()
{
}
IFix.Patch 不支持构造函数
参考
IFix.Patch 支持getter,setter函数
private string testField = "testField";
public string TestProperty {
[IFix.Patch]
get { return testField; }
[IFix.Patch]
set {
testField = value;
}
}
getter, setter
参考
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 不支持带泛型方法的新增类
[IFix.Interpret]
public class PatchClass
{
public void PatchGenericMethod<T>(T t)
{
UnityEngine.Debug.Log(t);
}
}
IFix.Interpret 不支持带泛型方法的新增类
IFix.Interpret 支持新增普通方法
// IFix.Interpret 支持新增普通方法
[IFix.Interpret]
public void PatchMethod()
{
UnityEngine.Debug.Log("PatchMethod");
}
IFix.Interpret 支持新增普通方法
参考
IFix.Interpret 不支持新增泛型方法
// IFix.Interpret 不支持新增泛型方法
[IFix.Interpret]
public void PatchGenericMethod<T>(T t)
{
UnityEngine.Debug.Log("PatchGenericMethod");
}
IFix.Interpret 不支持新增泛型方法
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.Interpret 不支持字段
// IFix.Patch 不支持字段
[IFix.Interpret]
public string TestField = "TestField";
IFix.Patch 不支持字段
参考
IFix.Interpret 不支持构造函数
// IFix.Interpret 不支持构造函数
[IFix.Interpret]
public Calculator()
{
}
IFix.Interpret 不支持构造函数
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;
}
非热更代码里用过 IEnumerator, 热更代码里可以使用
[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;
}
非热更代码里没有用过 IEnumerator, 热更代码里不可以使用
参考
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;
}
}
生成的 Instruction.cs
反编译 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
}
}
IFix.Core.Code
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;
}
}
IFix.Core.Instruction
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
}
}
ExceptionHandlerType
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;
}
}
ExceptionHandler
参考
如何保证多次生成Instruction.cs内容一致
各种Issue
Close
和ILRunTime有什么区别呢?以及性能比较?
多个 Assembly Definition 的template file 怎么设置?
如何卸载补丁
添加配置文件,添加python构建脚本用于跨平台构建,添加混淆key支持
异步匿名函数不支持吗?
对于已经注入的工程,如何取消注入呢?
fix后生成2个补丁文件
Warning: read ./Library/ScriptAssemblies/Assembly-CSharp.dll with symbol fail
执行"InjectFix/Fix"后提示please install the ToolKit
修改源码导出新的dll后,xcode工程导出报错,像是IL2CPP转方法报错了 IFix.Core.EvaluationStackOperation::ToObject
可以使用ILRuntime+injectfix方式吗
编辑器下除了reimport unity工程,有没有更好的方法回滚Inject了之后的dll
Unhandled Exception:System.Exception: Utils/<ReadBinaryFileAsync>d__0 is CompilerGenerated
带out泛型参数的方法Patch不生效
在patch的函数中调用父类的函数会导致无限循环
The type or namespace name `IFix' could not be found
和xlua测试用例的比较
修改文本编码,避免在其他平台显示乱码问题
Exception: instruction magic not match
IFix报错日志,缺少源码行信息,不方便排查问题
【优化IFix报错日志】使用debug模式运行ifix.exe,报错日志里包含源码文件和行信息,方便查问题
求增加一个Inject和Fix时的UI效果!提醒用户正在Inject或者Fix中!
项目在Unity可热修复,在apk包中无法热修复
【实现建议】不用IDMAP,只使用IDTagAttribute。
配置注入所有types,但是注入报错!
热更成功,但有个方法Patch会报错
热更成功,Debug信息正常,但是 Text 赋值失败
【实用建议】为方法分配id,能否根据方法签名生成唯一id
IFix.IDMAP问题求助
子类重写时先执行带泛型的方法会出错
Inject引起Unity崩溃
Error: the new assembly must not be inject, please reimport the project!
当使用 .net4.x async await来进行异步编程时,inject 阶段报异常
Enum的Equals方法
请问如何对预生成的dll进行注入
支持其他程序集的注入么?
支持代码混淆之后打补丁吗
> 我也碰到了类似的问题,最简化代码如下,当注入class A的时候将会报错
引入第三方工具引发的一个编译问题
Unity2019.2.15f1版本打包出来会出现未注入的情况
Unity2019.3.0f3 没有Editor\Data\Mono\bin\gmcs
[Change]
找不到IFix.Core.dll了
UnityEditor热更没问题,打包到Android后Load报错
打包il2cpp的时候报错
【BugReport】结构体初始化如果不使用new关键字,会报错
虚函数中如果用关键词in修饰struct类型的参数,inject后执行会报错
注入方法过多时,ios在armv7结构的链接过程会报错
补丁中调用Enum.Parse报错
Fix 和 inject 时弹出 warnning ,并且在Editor下没有看到效果
当hotfix的代码导致游戏崩溃,几乎无法查找明确的堆栈入口信息或者明确的方法信息
最新版本无法生成IFix.Core.dll和IFix.exe
命名空间下的方法fix报错
在编辑器模式下初始化Inject报错因为我使用了linq配置
foreach遍历包含枚举的容器会报错
支持IL2CPP模式下打包的Android和ios包热更吗
子类没有override父类的函数,打Interpret标签不会生效
[求助]遇到一个问题
编译报错
2019.3安卓版本注入失败
2019.3.3f1找不到gmcs
IEnumerator<T>的Current在解释执行下报错
打包资源和打包apk对于Inject的操作问题
Invoke不支持吗?新方法调用新方法问题
[fixbug] CustomBridge 注入跨dll的delegate,InjectFix 时报错
Unity2019 iOS注入失败,Unity2018 iOS注入成功
兼容2017 没有ISubsystem 添加新增类配置
验证新增类的类名是否存在
编辑器下体验热补丁,报错,不知道哪一步出的问题
CustomBridge属性可以做到自动给程序集的所有Delegate和Interface加上Wrapper吗?
请教 Non-static method requires a target 错误
执行hotfix报错
Open
如果一个函数内有new int[]{1,2,3}类操作,会报Warning: not support il[IL_0008: ldtoken <PrivateImplementationDetails>/
针对不同平台进行Fix时报错
多次打patch的问题
Unity 使用ILTocpp方式出现问题
自己生成的Dll在手机上fix有问题
子类方法里调用父类报错
为什么说:InjectFix在对Unity协程,闭包的支持中其实是包含了对新增class的支持?
inject失败弹Warning
是否支持c#匿名函数内的逻辑修改
!UNITY_EDITOR包含类或方法,无法生成patch
无法访问Unity的 Debug.unityLogger.logEnabled 属性
TargetException: Non-static method requires a target
使用了BurstCompile的类和结构体不能进行注入,否则加载patch之后会报burst的错误
只能在windows下使用吗?mac环境怎么编译呢
何时会开放新增类功能?
热更新后log问题
demo里的新增类必然报错,版本是2017
async Task 不支持吗?
2017.4 真机 cound not load type
2019.3.8再编译build_for_unity.bat时找不到gmcs目录
DateTime.Now.AddSeconds打补丁失败
Entities.ForEach 里的ref类修复报错
希望尽快支持async await特性
IFix.Interpret新类内不能用到typeof
无法Patch返回协程衍生类的函数
关于对IFix实践后的一些问题请教
按下标取struct数组解释执行报错
请教下GetTagMethods与GetTagClasses中assembly.CodeBase.IndexOf("ScriptAssemblies") != -1的用意。
//case Code.Stelem_Any: //0.03166702% 泛型中使用?泛型不支持解析,所以不会碰到这指令(我遇到了这个指令没被实现的异常)
支持继承时重写object的虚函数
增加方法没参数的情况会抛异常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 更新
现在已经支持新增字段