Unity[C#] Reflection Use

Reflection一个最有力的工具对于C#程序员。

最常用的例子来说明反射的用处是一个插件系统。假设你正在创建一个 接受用户创建 的扩展程序,有没有办法预先知道哪些方法这个扩展他们有或有扩展的名字将是什么,除非你可以检查编译的程序集,并在运行时提取信息,这正是反射呢,等等

目前,我正在开发一个游戏在Unity(一个多平台的游戏引擎和IDE),在用户 界面是“在游戏中”。这意味着,而是采用Unity提供的API,它提供了相当强大的工具集来创建交互式图形用户界面的,我把3D对象在游戏中的场景,必须响应用户的输入。Unity让你检测鼠标事件,但没有办法编写单个事件处理程序以模块化的方法。

为了得到这个功能,我不得不扩展Unity的Editor和Inspecot 来暴露我的代码,这听起来很复杂,但这些定位方法,并随后调用它们的底层代码很简单。

第1步:暴露你需要的方法

之前,我们接触过C#的Reflection API,我们需要创建一个新的属性,

Attributes allow us to assign metadata to classes, methods, properties, etc. that can be read back by reflection.

属性允许我们指定方法,类属性等等,可以通过反射来读到这些值。

In this case, our attribute is going to be called “ExposeToEditor” and we‘re going to use it to tag instance methods (and classes with static methods) that Unity‘s editor should recognise as valid event handlers.

在这种情况下,我们的属性将被称为:ExposeEditor ,我们打算用它来标记Instance(和类的静态方法)Unity的Editor可以识别出它们是有效的事件处理程序

因此,我们创建了一个新的脚本文件,并确保 using Systm;在顶部,然后我们编写以下代码:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
     public class ExposeToEditor : Attribute { }

这将创建一个标准属性系统,我们现在可以分配给任何方法或类,例如:

[ExposeToEditor]
      public void OnThisButtonClick(object sender) { };

现在,我们可以放在一起,将跟踪标识以这种方式方法的代码

第2步:接下来的工作定位我们的Public的方法

点击上面的图像,将其展开,并期待在最右边的面板中-你会看到一个名为:Interface Click Handler的脚本。这是一个Editor的界面,我们编码,可以让我选择包含我所需要的脚本和方法的特定对象。此图片是更提供上下文是什么,我来解释,而不是使用Reflection的重要组成部分。因此,如果它没有多大,不用担心。

最重要的是这些背后的编辑器界面,它需要定位的方法在脚本的逻辑,下面是关键的部分

var type = t.OnClickMonoBehaviour.GetType();

List<string> methodNames = new List<string>();
List<MethodInfo> methods = new List<MethodInfo>(type.GetMethods());

foreach (MethodInfo mi in methods)
{
    if (mi.IsDefined(typeof(ExposeToEditor), true))
    {
        methods.Add(mi);
        methodNames.Add(mi.Name);
    }
}

让我们把它分解,我们要做的第一件事情就是,获取选定的脚本类型,后者被存储 在 OnClickMonoBehaviour 对象的属性t。然后我们实例化一些List来存储这些方法的信息,foreach 循环遍历获取所有的包含在这个Script Type的public方法,通过type.GetMethods;

.GetMethods为我们提供一个数组的MethodInfo对象,.MethodInfo包含了大量的关于每个方法的信息,我们可以使用甚至该方法MethofInfo.Invoke.然而,这并不是最有效的方式来动态调用一个方法,以后的东西我会介绍。

现在,我们不希望来存储所有的方法,我们只是想通过那些我们先前创建的属性暴露出来,因此,我们使用MethofInfo.IsDefind() 方法来检查是否 ExposeToEditor 连接到该方法。要彻底,我们告诉 IsDefind 检查继承的类型也是如此。

一旦循环完成之后,我们将不得不包含的方法作为字符串不只是名字,但是这些方法本身,在形式列表 MethofInfo 对象。的字符串列表是用来填充的最后一个影像的”关于Click 方法” 下拉列表中,这样我们就可以很容易地选择正是我们所需要的。

第3步:存储和动态调用方法

用方法名存储,所有我们现在需要做的是理清了“Click” 的逻辑,这是用来在游戏中,正如我们前面提到的,要做到这一点最简单的方式是通过使用MethodInfo的动态调用。例如:

MethodInfo mi = VariableContainingMethodInfo;
     mi.Invoke();

并没有什么真的错了,这干得不错,但是,我们可以执行通过使用  Action<T> Delegate 并缓存它

首先,我们在某处定义缓存变量

private Action<object> CacheAction;

然后,当界面元件由玩家互动,我们缓存的方法,并用它在随后的相互作用。

CachedAction = (Action<object>)Delegate.CreateDelegate(typeof(Action<object>),OnClickMonoBehaviour,OnClickMethod);

现在,有几个重载 Delegate.CretaeDelegate ,在这种情况下 OnClickMonoBehaviour 和 OnClickMethod 都是字符串。委托创建并存储在CacheAction ,所以当我们要调用它,我们只是这样做:

CacheAction(object);

在这儿 object 只是一个灵活的参数,我们可以根据需要将信息传递到事件处理程序。

The best way to get more familiar with it is to check it out on MSDN. For more practical examples, Stack Exchange is a valuable resource, providing specific examples of how to get reflection doing what you want it to.

Unity[C#] Reflection Use

时间: 2024-12-29 10:23:30

Unity[C#] Reflection Use的相关文章

Unity[C#] Reflection To Update Scripts

我正在使用Unity 3D的一个项目.这个项目是一个Android的应用,它会下载AssetBundles并加载它们的内容,但由于AssetBundles不能包含脚本,我将使用预编译的C#脚本,并使用Mono反射来加载它(我不知道我会怎样,但看着办吧) .但现在我不知道该如何预编译.cs文件,所以任何人都可以帮助我? 答:把你的脚本通过MonoDevelop / VisualStudio编译成.dll,将你script.dll复制到您的统一项目的资产文件夹,将扩展名从.dll文件到.bytes

Unity5.3官方VR教程重磅登场-系列7 优化VR体验

本文转自:知乎专栏-笨猫快乐学编程,作者:王寒 简介 对于VR应用来说,如果想要让用户获得好的用户体验,特别是免除恶心眩晕的困扰,在VR开发中进行优化是必不可少的,惟其如此才能达到我们期望的游戏运行帧速.和其它平台上的开发不同,对VR应用的优化应该在项目启动的前期就开始,而且应该贯穿始终,而不是像传统项目那样把优化的工作留到最后去做.此外,在目标设备上进行实际测试也是非常有必要的. 相比非VR项目来说,VR项目是非常消耗计算资源的,其主要原因就是所有的画面都必须为每只眼睛单独渲染一次.因此,在开

【Unity|C#】基础篇(12)——反射(Reflection)(核心类:Type、Assembly)

[学习资料] <C#图解教程>(第24章):https://www.cnblogs.com/moonache/p/7687551.html 电子书下载:https://pan.baidu.com/s/1mhOmBG0 [内容] 对以下文章的整合: 详解C#中的反射(主要参考):https://www.cnblogs.com/jiangyunfeng/p/10436520.html C#反射机制                       :https://zhuanlan.zhihu.com/

C# Unity游戏开发——Excel中的数据是如何到游戏中的 (二)

本帖是延续的:C# Unity游戏开发——Excel中的数据是如何到游戏中的 (一) 上个帖子主要是讲了如何读取Excel,本帖主要是讲述读取的Excel数据是如何序列化成二进制的,考虑到现在在手游中应用很广泛的序列化技术Google的ProtoBuf,所以本文也是按照ProtoBuf的方式来操作的.ProtoBuf是一个开源库,简单来说ProtoBuf就是一个能使序列化的数据变得更小的类库,当然这里指的更小是相对的.好了ProtBuf的东西就不在多说,以后会专门写一篇帖子的.本帖其实就相当于上

【Unity Shaders】Shader中的光照

写在前面 自己写过Vertex & Fragment Shader的童鞋,大概都会对Unity的光照痛恨不已.当然,我相信这是因为我们写得少...不过这也是由于官方文档对这方面介绍很少的缘故,导致我们无法自如地处理很多常见的光照变量.这篇我们就来讨论下Unity内置的一些光照变量和函数到底怎么用. 以下内容均建立在Forward Rendering Path的基础上. 自己总结的,如果有硬伤一定要告诉我啊!感激不尽~ 主要参考: http://en.wikibooks.org/wiki/Cg_P

【浅墨Unity3D Shader编程】之二 雪山飞狐篇:Unity的基本Shader框架写法&amp;颜色、光照与材质

本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/40955607 作者:毛星云(浅墨)    微博:http://weibo.com/u/1723155442 邮箱: [email protected] 本篇文章中,我们学习了Unity Shader的基本写法框架,以及学习了Shader中Properties(属性)的详细写法,光照.材质与颜色的具体写法.写了6个Shader作为本文S

运用Unity实现依赖注入[有参构造注入]

上一篇章讲到关于使用Unity实现依赖注入的简单功能,针对有博友提出关于有参构造注入的问题; 本文同样通过一个实例来讲解如何实现此功能,文中一些分层讲解可以看上一文章(运用Unity实现依赖注入[结合简单三层实例]),本文就不在重复; 1:首先我们在IAopBLL层新建一个IPropertyBLL类,我们增加的两个属性:name跟age namespace IAopBLL { public interface IPropertyBLL { string name { set; get; } in

【Unity Shaders】初探Surface Shader背后的机制

转载请注明出处:http://blog.csdn.net/candycat1992/article/details/39994049 写在前面 一直以来,Unity Surface Shader背后的机制一直是刚開始学习的人为之困惑的地方. Unity Surface Shader在Unity 3.0的时候被开放给公众使用.其宣传手段也是号称让所有人都能够轻松地写shader.但因为资料缺乏,非常多人知其然不知其所以然,无法理解Unity Surface Shader在背后为我们做了哪些事情.

unity3d之从3ds max导入素材到unity中的设置

我们制造一个子弹的模型 1 首先设置3d max中参数,设置Customize->Units Setup Metic为厘米 2 建模,这里我们使用plane,一个平面,如图 3 然后导出 4 unity中模型设置,如图 在这里有个参数Scale Factor,这个参数很重要,设置小了,导致在unity里面可能看不到,大了又不合适. 5 创建一个material 6 创建一个shader,把这个shader赋值给刚才创建的material 这里的shader代码如下 Shader "Angr