• UnityTips:使用反射调用内部方法拓展编辑器


    大家都知道Unity是一个C/C++的游戏引擎,C#只是Unity提供的脚本层。因此大部分功能都是通过C#来调用底层的C++代码的。而一些朋友可能不知道的是,其实Unity的C#代码中也有很多方法是我们不能直接调用的非公共方法,一个常见的情景是在拓展Editor时,除了Unity提供的公共方法之外,我们还可以通过反射的方式,调用一些Unity提供的内部方法来实现一些特殊的功能。
    至于Unity的C#代码都有哪些内容,各位可以在这里找到答案:
    https://github.com/MattRix/UnityDecompiled
    当然C#部分的代码并没有什么实际的操作,但是它能告诉我们有哪些方法我们可以调用。
    一个有趣的例子就是如何在Editor中完全关闭Gizmo呢?一个很简单但是我们正常情况下无法调用的方法就是来干这事的。

    internal static extern void SetGizmoEnabled(int classID, string scriptClass, int gizmoEnabled);
    

    所以,我们就可以通过C#的反射机制,在自己的脚本中调用Editor内封装的非公共方法来实现。

    forcefield2233456789336.gif

    using System;
    using System.Collections;
    using System.Reflection;
    using UnityEditor;
    
    public class SceneViewGizmos
    {
    
        #region 方法
    
        [MenuItem("temp/Disable All Gizmos")]
        private static void DisableAllSceneGizmos()
        {
            ToggleGizmos(false);
        }
    
        [MenuItem("temp/Enable All Gizmos")]
        private static void EnableAllSceneGizmos()
        {
            ToggleGizmos(true);
        }
    
        private static void ToggleGizmos(bool gizmosOn)
        {
            int val = gizmosOn ? 1 : 0;
            Assembly asm = Assembly.GetAssembly(typeof(Editor));
            Type type = asm.GetType("UnityEditor.AnnotationUtility");
    
            if (type == null)
            {
                return;
            }
    
            MethodInfo getAnnotations = type.GetMethod("GetAnnotations", BindingFlags.Static | BindingFlags.NonPublic);
            MethodInfo setGizmoEnabled = type.GetMethod("SetGizmoEnabled", BindingFlags.Static | BindingFlags.NonPublic);
            MethodInfo setIconEnabled = type.GetMethod("SetIconEnabled", BindingFlags.Static | BindingFlags.NonPublic);
            var annotations = getAnnotations.Invoke(null, null);
    
            foreach (object annotation in (IEnumerable)annotations)
            {
                Type annotationType = annotation.GetType();
                FieldInfo classIdField = annotationType.GetField("classID", BindingFlags.Public | BindingFlags.Instance);
                FieldInfo scriptClassField = annotationType.GetField("scriptClass", BindingFlags.Public | BindingFlags.Instance);
                if (classIdField != null && scriptClassField != null)
                {
                    int classId = (int)classIdField.GetValue(annotation);
                    string scriptClass = (string)scriptClassField.GetValue(annotation);
                    setGizmoEnabled.Invoke(null, new object[] { classId, scriptClass, val });
                    setIconEnabled.Invoke(null, new object[] { classId, scriptClass, val });
                }
            }
        }
    
        #endregion
    }
  • 相关阅读:
    《python核心编程第二版》第8章习题
    《python核心编程第二版》第7章习题
    虚拟Ip技术如何实现备机容灾
    LeetCode算法编程连载之五
    GIT使用入门篇(管理自已的代码)
    LeetCode算法编程之连载四(二分法)
    LeetCode算法编程之连载三
    LeetCode算法编程之连载二
    LeetCode算法编程之连载一
    Python 使用flush函数将缓冲区数据立即写磁盘
  • 原文地址:https://www.cnblogs.com/murongxiaopifu/p/7131596.html
Copyright © 2020-2023  润新知