C# 동적 교체 방법 사용

19545 단어 UnityC#
이렇게 해보면 움직이니까 공유하는 거야.

견본

using UnityEngine;
using System;
using System.Collections;
using System.Reflection;

public class ReplaceMethod1 : MonoBehaviour
{
    static void ExchangeFunctionPointer(MethodInfo method0, MethodInfo method1)
    {
        unsafe
        {
            var functionPointer0 = method0.MethodHandle.Value.ToPointer();
            var functionPointer1 = method1.MethodHandle.Value.ToPointer();
            var tmpPointer = *((int*)new IntPtr(((int*)functionPointer0 + 1)).ToPointer());
            *((int*)new IntPtr(((int*)functionPointer0 + 1)).ToPointer()) = *((int*)new IntPtr(((int*)functionPointer1 + 1)).ToPointer());
            *((int*)new IntPtr(((int*)functionPointer1 + 1)).ToPointer()) = tmpPointer;
        }
    }

    void Awake()
    {
        MethodInfo onGuiMethod = this.GetType().GetMethod("OnGUI", BindingFlags.NonPublic | BindingFlags.Instance);
        MethodInfo onGuiV2Method = this.GetType().GetMethod("OnGUIv2", BindingFlags.NonPublic | BindingFlags.Instance);
        ExchangeFunctionPointer(onGuiMethod, onGuiV2Method);
    }

    void OnGUI()
    {
        if (GUILayout.Button("This is OnGUIv1"))
        {
        }
    }

    void OnGUIv2()
    {
        if (GUILayout.Button("This is OnGUIv2"))
        {
        }
    }
}

실행 결과



OnGUI 대신 OnGUIv2가 호출되었습니다.

적당한 해설


하고 있는 일
1. Awake의 반사로 OnGUI, OnGUIv2 방법을 얻어 Exchange Function Pointer 방법에 두 가지 투입
2. Exchange Function Pointer 메서드에서 실제 처리된 함수 포인터를 다음으로 대체
3. 끝
바늘이 머무르는 관계에서 아마도 unsafe일 것이다.
이 예에서 두 가지 방법의 처리는 교체된 것이지만 이것은 절대적인 것이 아니라 지침을 공유할 수도 있다.
iOS 실기에서도 작동돼 충격적이었다.

단, 한 번에 실제 호출하는 방법도 변경할 수 없다


치명상이야...
using UnityEngine;
using System;
using System.Collections;
using System.Reflection;

public class ReplaceMethod1 : MonoBehaviour
{
    static void ExchangeFunctionPointer(MethodInfo method0, MethodInfo method1)
    {
        unsafe
        {
            var functionPointer0 = method0.MethodHandle.Value.ToPointer();
            var functionPointer1 = method1.MethodHandle.Value.ToPointer();
            var tmpPointer = *((int*)new IntPtr(((int*)functionPointer0 + 1)).ToPointer());
            *((int*)new IntPtr(((int*)functionPointer0 + 1)).ToPointer()) = *((int*)new IntPtr(((int*)functionPointer1 + 1)).ToPointer());
            *((int*)new IntPtr(((int*)functionPointer1 + 1)).ToPointer()) = tmpPointer;
        }
    }

    void OnGUI()
    {
        if (GUILayout.Button("This is OnGUIv1"))
        {
            MethodInfo onGuiMethod = this.GetType().GetMethod("OnGUI", BindingFlags.NonPublic | BindingFlags.Instance);
            MethodInfo onGuiV2Method = this.GetType().GetMethod("OnGUIv2", BindingFlags.NonPublic | BindingFlags.Instance);
            ExchangeFunctionPointer(onGuiMethod, onGuiV2Method);        }
    }

    void OnGUIv2()
    {
        if (GUILayout.Button("This is OnGUIv2"))
        {
            MethodInfo onGuiMethod = this.GetType().GetMethod("OnGUI", BindingFlags.NonPublic | BindingFlags.Instance);
            MethodInfo onGuiV2Method = this.GetType().GetMethod("OnGUIv2", BindingFlags.NonPublic | BindingFlags.Instance);
            ExchangeFunctionPointer(onGuiMethod, onGuiV2Method);        }
    }
}
원래 이렇게 하려고 했는데 어쨌든 로드하는 방법이 나중에 지침을 붙여도 의미가 없나요?

Debug.애플 회사.Register LogCallback 이외의 방법으로 연결을 하는 용도 등

#if UNITY_EDITOR
using UnityEditor;
using System;
using System.Collections;
using System.Reflection;

[InitializeOnLoad]
public class ReplaceMethod2
{
    static ReplaceMethod2()
    {
        MethodInfo logMethod = typeof(Debug).GetMethod("Log", new System.Type[] { typeof(object) });
        MethodInfo logWarningMethod = typeof(Debug).GetMethod("LogWarning", new System.Type[] { typeof(object) });
        ExchangeFunctionPointer(logMethod, logWarningMethod);
        Debug.LogWarning("this is Warning");
        Debug.Log("this is Log");
    }

    static void ExchangeFunctionPointer(MethodInfo method0, MethodInfo method1)
    {
        unsafe
        {
            var functionPointer0 = method0.MethodHandle.Value.ToPointer();
            var functionPointer1 = method1.MethodHandle.Value.ToPointer();
            var tmpPointer = *((int*)new IntPtr(((int*)functionPointer0 + 1)).ToPointer());
            *((int*)new IntPtr(((int*)functionPointer0 + 1)).ToPointer()) = *((int*)new IntPtr(((int*)functionPointer1 + 1)).ToPointer());
            *((int*)new IntPtr(((int*)functionPointer1 + 1)).ToPointer()) = tmpPointer;
        }
    }
}
#endif
지상 Debug.Log 및 Debug워닝을 교체해보세요.

좋은 웹페이지 즐겨찾기