大家都知道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內封裝的非公共方法來實現。
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
}