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内封装的非公共方法来实现。

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
}
UnityTips:使用反射调用内部方法拓展编辑器的更多相关文章
- VS2010 F5调试时出现:“ 尝试运行项目时出错:未捕获通过反射调用的方法引发的异常”解决
VS2010 F5调试时出现 尝试运行项目时出错:未捕获通过反射调用的方法引发的异常 两个解决方法:1) 打开项目属性,选择调试选项卡,将“启用非托管代码调试”一项钩上.2) 打开项目属性,选择调试选 ...
- 反射-优化及程序集等(用委托的方式调用需要反射调用的方法(或者属性、字段),而不去使用Invoke方法)
反射-优化及程序集等(用委托的方式调用需要反射调用的方法(或者属性.字段),而不去使用Invoke方法) 创建Delegate (1).Delegate.CreateDelegate(Type, ...
- JNI C反射调用java方法
前面记录了调用C的学习笔记,现在来记录一下C反射调用Java的笔记.JNI开发学习之调用C方法 Android开发中调用一个类中没有公开的方法,可以进行反射调用,而JNI开发中C调用java的方法也是 ...
- java动态载入指定的类或者jar包反射调用其方法
序言 有时候.项目中会用到java动态载入指定的类或者jar包反射调用其方法来达到模块的分离,使各个功能之间耦合性大大减少,更加的模块化.代码利用率更高.模式中的代理模式就用到java的这一机制. 下 ...
- 从vs2010的UnitTestFramework类库提取私有方法反射调用的方法
背景 年龄大点的程序员都知道在vs2010中创建单元测试非常的简单,鼠标定位在方法名字,右键创建单元测试,就会创建一个测试方法,即使是在私有方法上也可以创建测试方法. VS2010以后就没这么简单了, ...
- 对JAVA Bean使用PropertyDescriptor反射调用JAVA方法低耦合
对于符合JAVA Bean规范的bean,调用其方法应优先使用java.beans.PropertyDescriptor获取Method进行方法调用,以获得更大的可维护性. public void g ...
- 将对象转为数组方法:延伸array_map函数在PHP类中调用内部方法
public static function objectToArray($d) { if (is_object($d)) { $d = get_object_vars($d); } if (is_a ...
- 对JAVA Bean使用PropertyDescriptor反射调用JAVA方法
对于符合JAVA Bean规范的bean,调用其方法应优先使用java.beans.PropertyDescriptor获取Method进行方法调用,以获得更大的可维护性. 示比例如以下: NonCo ...
- java反射调用私有方法和修改私有属性
//调用私有方法package com.java.test; public class PrivateMethod { private String sayHello(String name) { r ...
随机推荐
- formValidator 插件 使用总结
1. 大小写的问题, formvalidator 的属性 大小写问题一定要注意, 在踩过的坑里就包括这个, 把所有属性的第二个字母的开头全部写成大写 ,导致提示信息不能用,这个问题纠结了好久 2.er ...
- 部署harbor仓库相关问题总结
切换到harbor目录docker-compose down 停止所有服务 docker-compose up -d 启动所用服务 卸载:停止服务后 使用:docker rmi --force $(d ...
- 机器学习入门:Linear Regression与Normal Equation -2017年8月23日22:11:50
本文会讲到: (1)另一种线性回归方法:Normal Equation: (2)Gradient Descent与Normal Equation的优缺点: 前面我们通过Gradient Desce ...
- Spring Cloud Eureka的集群配置(六)
1.再次创建2个Eureka工程 工程名:microservicecloud-eureka-7002 工程名:microservicecloud-eureka-7003 2.pom.xml文件 < ...
- 【aardio】如何让edit控件只能输入数字、小数点及 - 号
import win.ui; /*DSG{{*/ var winform = win.form(parent=...; text="aardio Form";right=349;b ...
- HTML5新增表单验证
HTML5新增属性: 属性 描述 placeholder 提供一种提示,输入域为空时显示,获得焦点输入内容后消失 required 规定输入域不能为空 pattern 规定验证input域的模式(正则 ...
- python第十九天 关于方法,函数
1.先从简单的函数说起 from inspect import isfunction 导入判断是否是function def foo():pass 定义了一个函数 print(foo) <fun ...
- python基础之Day21
对象整合了操作数据的方法 1.init方法 调用类时自动触发,为对象初始化自己独有的特征 class people: def __init__(self,name,age,sex): self.nam ...
- java线程中的notifyAll唤醒操作
注意: java中的notifyAll和notify都是唤醒线程的操作,notify只会唤醒等待池中的某一个线程,但是不确定是哪一个线程,notifyAll是针对指定对象里面的所有线程执行唤醒操作,指 ...
- short s=1;s=s+1;short s=1;s+=1;有什么区别?
short s = 1; s = s + 1; 这个编译一定是不通过的,会提示损失精度. short s = 1; s += 1: 这个编译反而可以通过. 隐式类型转换可以由小到大自动转,即byte ...