{"record":{"id":"610d2fa9d6b173e5","repo":"egametang/ET","slug":"wraning-method-methodname-must-has-a-attribut","errorCode":null,"errorMessage":"WRANING: method [{methodName}] must has a Attribute `MethodImpl(MethodImplOptions.NoOptimization)` to prevent code call to this optimized by compiler(pass args by shared stack)","messagePattern":"WRANING: method \\[(.+?)\\] must has a Attribute `MethodImpl\\(MethodImplOptions\\.NoOptimization\\)` to prevent code call to this optimized by compiler\\(pass args by shared stack\\)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"Packages/cn.etetet.hybridclr/Scripts/Editor/Share/3rds/UnityHook/MethodHook.cs","lineNumber":214,"sourceCode":"\n            {\n                if ((targetMethod.MethodImplementationFlags & MethodImplAttributes.InternalCall) != MethodImplAttributes.InternalCall)\n                {\n                    int codeSize = targetMethod.GetMethodBody().GetILAsByteArray().Length; // GetMethodBody can not call on il2cpp\n                    if (codeSize < minMethodBodySize)\n                        UnityEngine.Debug.LogWarning($\"WRANING: you can not hook method [{methodName}], cause its method body is too short({codeSize}), will random crash on IL2CPP release mode\");\n                }\n            }\n\n            if(proxyMethod != null)\n            {\n                methodName = $\"{proxyMethod.DeclaringType.Name}.{proxyMethod.Name}\";\n                int codeSize = proxyMethod.GetMethodBody().GetILAsByteArray().Length;\n                if (codeSize < minMethodBodySize)\n                    UnityEngine.Debug.LogWarning($\"WRANING: size of method body[{methodName}] is too short({codeSize}), will random crash on IL2CPP release mode, please fill some dummy code inside\");\n\n                if ((proxyMethod.MethodImplementationFlags & MethodImplAttributes.NoOptimization) != MethodImplAttributes.NoOptimization)\n                    throw new Exception($\"WRANING: method [{methodName}] must has a Attribute `MethodImpl(MethodImplOptions.NoOptimization)` to prevent code call to this optimized by compiler(pass args by shared stack)\");\n            }\n#endif\n        }\n\n        private void CreateCodePatcher()\n        {\n            long addrOffset = Math.Abs(_targetPtr.ToInt64() - _proxyPtr.ToInt64());\n            \n            if(_proxyPtr != IntPtr.Zero)\n                addrOffset = Math.Max(addrOffset, Math.Abs(_targetPtr.ToInt64() - _proxyPtr.ToInt64()));\n\n            if (LDasm.IsARM())\n            {\n                if (IntPtr.Size == 8)\n                    _codePatcher = new CodePatcher_arm64_near(_targetPtr, _replacementPtr, _proxyPtr);\n                else if (addrOffset < ((1 << 25) - 1))\n                    _codePatcher = new CodePatcher_arm32_near(_targetPtr, _replacementPtr, _proxyPtr);\n                else if (addrOffset < ((1 << 27) - 1))","sourceCodeStart":196,"sourceCodeEnd":232,"githubUrl":"https://github.com/egametang/ET/blob/5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f/Packages/cn.etetet.hybridclr/Scripts/Editor/Share/3rds/UnityHook/MethodHook.cs#L196-L232","documentation":"Thrown by MethodHook.CheckMethod() on Unity versions older than 2020.3 when the proxy (call-forwarding) method lacks the [MethodImpl(MethodImplOptions.NoOptimization)] attribute. The proxy method preserves the original method's call semantics so the hook can call through to the original code. Without NoOptimization, the IL2CPP or JIT compiler may optimize argument passing via shared stack slots, which breaks the trampoline and causes random crashes in release builds.","triggerScenarios":"CheckMethod() runs under #if UNITY_EDITOR && !UNITY_2020_3_OR_NEWER. If proxyMethod is set and its MethodImplementationFlags does not include NoOptimization, the exception fires. This only affects older Unity versions; 2020.3+ skips this check.","commonSituations":"Writing a proxy method for a hook on Unity 2019 or earlier without adding [MethodImpl(MethodImplOptions.NoOptimization)]; updating from a newer Unity where the attribute wasn't required to an older target; copy-pasting a proxy method from a sample that omitted the attribute.","solutions":["Add [MethodImpl(MethodImplOptions.NoOptimization)] to the proxy method declaration.","Upgrade to Unity 2020.3 or newer where this check is compiled out.","Ensure the attribute import is present: using System.Runtime.CompilerServices.","Add a build-time Roslyn analyzer or code review checklist to verify the attribute on all proxy methods."],"exampleFix":"// before\npublic static IntPtr OriginalMethodProxy(IntPtr self, int param)\n{\n    return OriginalMethod(self, param);\n}\n\n// after\n[MethodImpl(MethodImplOptions.NoOptimization)]\npublic static IntPtr OriginalMethodProxy(IntPtr self, int param)\n{\n    return OriginalMethod(self, param);\n}","handlingStrategy":"validation","validationCode":"#if UNITY_EDITOR && !UNITY_2020_3_OR_NEWER\nif (proxyMethod != null)\n{\n    var implFlags = proxyMethod.GetCustomAttribute<MethodImplAttribute>();\n    if (implFlags == null || (implFlags.Value & (int)MethodImplOptions.NoOptimization) == 0)\n    {\n        Debug.LogError($\"Proxy method '{proxyMethod.Name}' must have [MethodImpl(MethodImplOptions.NoOptimization)] \" +\n            \"to prevent IL2CPP release-mode crashes.\");\n    }\n}\n#endif","typeGuard":"#if UNITY_EDITOR && !UNITY_2020_3_OR_NEWER\nstatic bool HasNoOptimizationAttribute(MethodInfo method)\n{\n    if (method == null) return true; // proxy is optional\n    return (method.MethodImplementationFlags & MethodImplAttributes.NoOptimization)\n        == MethodImplAttributes.NoOptimization;\n}\n#endif","tryCatchPattern":"try\n{\n    hook.CheckMethod();\n}\ncatch (Exception ex) when (ex.Message.Contains(\"NoOptimization\"))\n{\n    Debug.LogError($\"Proxy method '{proxyMethod.Name}' is missing [MethodImpl(MethodImplOptions.NoOptimization)]. \" +\n        \"Add the attribute or upgrade to Unity 2020.3+.\");\n}","preventionTips":["Always decorate proxy methods with [MethodImpl(MethodImplOptions.NoOptimization)] on Unity < 2020.3.","Upgrade to Unity 2020.3 or newer to eliminate this requirement entirely.","Add a code review checklist item: verify the attribute on every proxy/trampoline method.","Use a Roslyn analyzer to enforce the attribute on methods matching a proxy naming convention."],"tags":["unityhook","method-hook","no-optimization","il2cpp","unity-version","proxy-method"],"backgroundTag":null,"analyzedSha":"5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f","analyzedAt":"2026-08-13T21:10:40.377Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}