美文网首页
【Unity3D】默认编辑器逻辑修改

【Unity3D】默认编辑器逻辑修改

作者: crossous | 来源:发表于2023-06-05 17:52 被阅读0次

  有时候我们不清楚Unity编辑器的逻辑是如何执行的,可以通过查看UnityCsReference查看相关逻辑。有些实用的方法Unity没有开放出来,而做自定义工具会用到,因此可以利用反射来获取这些隐藏的方法。
  有时我们需要给修改一些默认逻辑,例如在烘焙光照前后执行某些逻辑,例如执行其他自定义烘焙逻辑、弹出窗口提醒美术操作等,方便和规范美术的流程。
  修改源码当然是一种操作,但这样不方便迭代,也不方便升级、切换引擎版本,对项目用到的引擎还要严格规范,这样不是一个好的方法。
  然后想到了Hook,既然能用UnityCsReference获取到函数的MethodInfo,那么用Hook就可以在关键函数的执行前后插入自己的逻辑、修改原有逻辑。
  例如Unity生成光照按钮的方法(从UnityCsReference找的):

namespace UnityEditor
{
    internal class LightingWindowLightingTab
    {
        public void OnGUI()
        {
            //something
            Buttons();
        }

        void Buttons()
        {
            //something
            DoBake();
        }
    }
}

  里面的DoBake就是我们关注的方法,如果我们想要在Bake前执行操作,就需要对DoBake函数进行Hook。
  本来想查Unity C#如何Hook,发现Misaka佬已经有现成的库可用:MonoHook
  因此写了如下的Hook方法:

using System;
using System.Reflection;
using System.Runtime.CompilerServices;
using MonoHook;
using UnityEditor;
using UnityEngine;

#if UNITY_EDITOR
    using UnityEditor.Callbacks;
    /// <summary>
    /// 修改烘焙逻辑
    /// </summary>
    [InitializeOnLoad]
    public static class GenerateLightingCallback
    {
        private static MethodHook _hook;

        static GenerateLightingCallback()
        {
            if (_hook == null)
            {
                Type type = Type.GetType("UnityEditor.LightingWindowLightingTab,UnityEditor.dll");
                MethodInfo DoBakeTarget = type.GetMethod("DoBake", BindingFlags.Instance | BindingFlags.NonPublic);

                MethodInfo Replacement = new Action(NewBakeMethod).Method;
                MethodInfo Proxy = new Action(ProxyBakeFunction).Method;
                
                _hook = new MethodHook(DoBakeTarget, Replacement, Proxy);
                _hook.Install();
            }
        }

        //Bake 前要做的逻辑
        private static void OnBake()
        {
            //这里可以注册一些方法来执行
            Debug.Log("generate lighting!");
        }
        
        #region private
        [MethodImpl(MethodImplOptions.NoInlining)]
        private static void NewBakeMethod()
        {
            OnBake();//自定义逻辑
            ProxyBakeFunction();//调用原来的逻辑
        }

        //原方法占用,逻辑不重要,不会执行
        [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
        private static void ProxyBakeFunction()
        {
            // 随便乱写点东西以占据空间
            for (int i = 0; i < 100; i++)
            {
                UnityEngine.Debug.Log("something");
            }
            UnityEngine.Debug.Log(Application.targetFrameRate);
        }
        #endregion
    }
#endif

相关文章

网友评论

      本文标题:【Unity3D】默认编辑器逻辑修改

      本文链接:https://www.haomeiwen.com/subject/hhkwedtx.html