【Unity学习笔记】反射

在这里插入图片描述


文章目录

  • 前言
  • 反射
    • 通过反射获取类型
  • Unity中的反射
  • 用反射在Unity中动态加载


前言

在我平时做项目的时候,由于我们做的项目都是很简单的,所以不怎么接触反射机制。最早了解反射机制是关于Invoke的时候,知道可以通过方法名来直接进行Invoke调用,但是由于反射调用存在性能开销较大的问题,因此就没打算深入了解

不过反射作为C#的高级特性,可以不用,但是不能不了解

反射(Reflection) 的含义和用法

反射

反射是.NET中的重要机制,通过反射可以得到*.exe或*.dll等程序集内部的接口、类、方法、字段、属性、特性等信息,还可以动态创建出类型实例并执行其中的方法。
反射指程序可以访问、检测和修改它本身状态或行为的一种能力。
程序集包含模块,而模块包含类型,类型又包含成员。反射则提供了封装程序集、模块和类型的对象。
可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型。然后,可以调用类型的方法或访问其字段和属性。

简单来说,反射能实现的功能极其强大,可以直接通过读取exe或者dll程序集获取其中的接口、类、方法、字段、属性、特性等信息。

通过反射获取类型

反射获取类型的方式有三种:

  1. 通过typeof获取某个值的类型
Type personType=typeof(Person);

2.通过一个对象获取该对象所对应的类的类型

Type=Person.GetType();

3.通过类的名称字符串获取对应的类型

Type strType =Type.GetType("Person");

注意,上述说的三种方法不止包括获取class,只需要换成对应的方法就能获取接口、方法、字段、属性、特性等等信息。这意味这只要使用反射就可以获取代码中的几乎任何信息。甚至私有的变量成员和方法都能获取

反射(Reflection) 的含义和用法

只需查看上文就可以知道反射的功能有多全面,返回所需的类型的信息,根据访问修饰符获取类型成员信息,通过反射直接构造实例化对象,通过反射获取类中的所有属性,字段,事件,方法,构造函数等等。私有的都可以随便访问。

优点:

  • 反射提高了程序的灵活性和扩展性。
  • 降低耦合性,提高自适应能力。
  • 它允许程序创建和控制任何类的对象,无需提前硬编码目标类。

缺点:

  1. 性能问题:使用反射基本上是一种解释操作,用于字段和方法接入时要远慢于直接代码。因此反射机制主要应用在对灵活性和拓展性要求很高的系统框架上,普通程序不建议使用。
  2. 使用反射会模糊程序内部逻辑;程序员希望在源代码中看到程序的逻辑,反射却绕过了源代码的技术,因而会带来维护的问题,反射代码比相应的直接代码更复杂。

实际上反射的优点也是它的缺点。为什么我们不用反射来解耦,不用反射做拓展呢?除了反射本身调用时需要查找解释造成过高的性能开销之外,反射本身绕过了程序内部逻辑,可读性太差了。如果我们要使用反射调用函数,不还是需要知道函数方法实现了什么吗?而解耦这一目的完全可以从设计模式上来解决。

Unity中的反射

反射在Unity中实现的功能主要是:

  • 使用反射,我们可以动态的访问代码中的成员,或是进行动态实例化。例如我们想要实现游戏中的控制台Debug功能,让用户可以使用简单的指令就能创建一些游戏实例,例如用户可以用指令add ObjName 100来为场景中增加100个对应名称的游戏物体实例,我们就可以用反射机制,获取ObjName字符串对应的Type并生成物体:
Type type = typeof(ObjName);
object instance = Activator.CreateInstance(type);
  • 另一种想法是,使用反射,我们可以实现一些热更新的功能。例如对于若要生成一个物体,我们可以把它封装在dll程序集中,并通过反射机制,用物体的名称来直接实例化dll中的该物体。而如果此时客户端要实现不停机热更新该物体的数值,只需下载替换dll文件即可,因为物体名称并没变,我们通过反射机制获取直接获取更新的成员并更新数值。

合理使用反射机制,可以简单的实现一些麻烦的功能,而且将程序集之间进行分离,也有助于减少程序的耦合性。


用反射在Unity中动态加载

想要在unity中创建并加载程序集,我们需要在文件夹内生成一个Assembly Definition

在这里插入图片描述
在这里插入图片描述
我们会发现创建了一个拼图icon的文件,这个文件就是我们的程序集,但它目前是未编译的状态,格式是asmdef,只有在被导出后才会被编译为dll

官方文档——程序集定义
Unity程序集定义(Assembly Definition File)功能详解

我们在与它同目录下所创建的脚本都会被编译到这个程序集中
在这里插入图片描述

在面板中可以查看它的属性,首先程序集的名称是在面板上的Name定义的,而不是该文件本身的名称

这里显示了三个选项(高版本还有其他选项),AutoReferenced代表了该程序集会自动引用其他程序集,导致其他程序集更新后该程序集也被自动重编译,如果我们不希望这个程序集在其他程序集更新后被重编译,就关闭它

override References代表了我们指定该程序集会引用哪些程序集,并在Assembly Definition References里选择添加对应的Dll

最下面的面板Platforms约定在导出到哪些平台时该程序集会被编译

Define Constraints代表了该程序集会在哪些宏被定义的时候被编译,只有当代码中使用了指定宏时才会使用该程序集。例如我下面的代码:

using System.IO;
using System.Reflection;
using UnityEngine;

public class TestClass : MonoBehaviour
{
	private string _localPath;

	private void Start()
	{

#if UNITY_EDITOR
		// 我不知道如何在项目中直接加载未编译的程序集,只能导出后加载了
		_localPath = Path.Combine(Path.GetDirectoryName(Application.dataPath),"Apps");
		string[] DataFloder = Directory.GetDirectories(_localPath, "*_Data");
		_localPath = Path.Combine(DataFloder[0], "Managed", "Test.dll");
#else
		LocalPath = Path.Combine(Application.dataPath, "Managed", "Test.dll");
#endif
		// 可笑的是程序集只能加载不能卸载,导致程序关闭后程序集依然被访问
		Assembly _assembly = Assembly.LoadFrom(_localPath);
		var t = _assembly.GetType("TestReflect");
		gameObject.AddComponent(t);
	}
}

public class TestReflect : MonoBehaviour
{
    void Start()
    {
        Debug.Log("反射成功调用");
    }
}

由于我定义了!UNITY_EDITOR,也就是非编辑器中被编译,经测试,导出时会正常编译dll,然后在编辑器状态,代码是正常执行的。

但是如果定义的是UNITY_EDITOR,则导出时不会编译为Dll,猜想是由于导出时的bulidPipeline使用了!UNITY_EDITOR宏,因此若定义了!UNITY_EDITOR的引用约束,则导出时会编译。

当然我们还可以定义其他的编译引用约束,根据具体使用情况来判断

导出后的Dll路径在GameScence_Data\Managed\路径下

执行结果:

在这里插入图片描述
在这里插入图片描述

导出后的结果也是一样的

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/684902.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数字人动作解决方案,塑造逼真动作

在品牌形象塑造、市场推广及客户服务等领域,企业正面临着前所未有的挑战和机遇。为满足企业的需求,美摄科技凭借其在人工智能和计算机视觉领域的深厚积累,推出了面向企业的数字人动作解决方案,助力企业轻松打造逼真、灵活的虚拟形…

apple开发者账户证书删除与下载

1.打开并登陆: Sign In - Apple 选择证书 证书管理页面 证书详情 删除或者下载证书 下载证书 删除证书

【实战】kafka3.X kraft模式集群搭建

文章目录 前言kafka2.0与3.x对比准备工作JDK安装kafka安装服务器增加hosts 修改Kraft协议配置文件格式化存储目录 启动集群停止集群测试Kafka集群创建topic查看topic列表查看消息详情生产消息消费消息查看消费者组查看消费者组列表 前言 相信很多同学都用过Kafka2.0吧&#xf…

【MySQL03】【 Buffer Pool】

文章目录 一、前言二、缓冲池(Buffer Pool )1. 缓冲池的概念2. LRU List、Free List 和 Flush List2.1 Free 链表2.1.1 缓冲页的哈希处理 2.2 Flush 链表2.3 LRU 链表2.3.1 简单 LRU 链表2.3.2 优化后的 LRU 列表2.3.3 更进一步的优化 3. 脏页的刷新4. 多…

【最新鸿蒙应用开发】——Want信息载体

信息传递载体Want 1、概述 上一章节我们学习了UIAbility组件 【最新鸿蒙应用开发】——一篇搞懂什么是UIAbility-CSDN博客 ,其中组件间的交互传递信息的媒介就是Want,本章节我们来更加深入学习Want的相关知识。 Want是一种对象,用于在应用组…

性能狂飙:SpringBoot应用优化实战手册

在数字时代,速度就是生命,性能就是王道!《极速启航:SpringBoot性能优化的秘籍》带你深入SpringBoot的内核,探索如何打造一个飞速响应、高效稳定的应用。从基础的代码优化到高级的数据库连接池配置,再到前端…

恭喜!Z医生喜提世界顶级梅奥诊所访问学者邀请函

➡️【院校简介】 梅奥诊所(Mayo clinic),于1863年在美国明尼苏达州罗彻斯特创立,是全球规模最大的综合性非营利医生执业组织。它是以不断创新的医学教育和世界领先的医学研究为基础,建立起来的全美规模最大、设备最先…

YashanDB携手宏杉科技助力国产软件生态发展

近日,深圳计算科学研究院崖山数据库系统YashanDB与宏杉科技系列存储、系列服务器与数据库一体机等多款产品顺利完成兼容性互认证。经严格测试,双方产品完全兼容,稳定运行,共同提供高效、稳定、安全的国产软硬件一体化解决方案&…

Spring异步任务@Async的默认线程池执行器是如何初始化的

Spring异步任务Async的默认线程池执行器,是从哪里来?是如何初始化的? 结论先行 异步任务Async的默认线程池执行器是通过TaskExecutionAutoConfiguration#applicationTaskExecutor自动注入的。 异步任务的线程池执行器是如何初始化的&#…

查看Linux端口占用和开启端口命令

查看端口的使用的情况 lsof 命令 比如查看80端口的使用的情况 lsof -i tcp:80列出所有的端口 netstat -ntlp查看端口的状态 /etc/init.d/iptables status开启端口以开启端口80为例。 1 用命令开启端口 iptables -I INPUT -p tcp --dport 80 -j accpet --写入要开放的端口/…

【Vue】scoped解决样式冲突

默认情况下写在组件中的样式会 全局生效 → 因此很容易造成多个组件之间的样式冲突问题。 全局样式: 默认组件中的样式会作用到全局,任何一个组件中都会受到此样式的影响 局部样式: 可以给组件加上scoped 属性,可以让样式只作用于当前组件 一、代码示例 BaseOne…

龙迅#LT8711H支持TYPE-C/DP/EDP转HDMI功能应用,分辨率支持 1080p@60Hz,芯片内置固件!

1. 概述 LT8711H是一款高性能 Type-C/DP1.2/EDP 转 HD-DVI1.3 转换器,设计用于将 USB Type-C 源或 DP1.2 源连接到 HD-DVI1.3 接收器。 该LT8711H集成了符合 DP1.2 标准的接收器和符合 HD-DVI1.3 标准的发射器。此外,还包括两个用于 CC 通信的 CC 控制器…

Linux服务器扩容及磁盘分区(LVM和非LVM)

Linux扩容及磁盘分区(LVM和非LVM) 本文主要介绍了阿里云服务器centos的扩容方法:非LVM分区扩容方法(系统盘),以及磁盘改LVM并分区(数据盘)。主要是ext4文件系统及xfs磁盘scsi MBR分…

springcloud Feign调用拦截器(统一处理拷贝请求头实现透传信息、内部调用鉴权、打印feign调用)

springcloud Feign调用拦截器(统一处理拷贝请求头实现透传信息、内部调用鉴权、打印feign调用日志) 实现接口Feign.RequestInterceptor 实现接口 feign.RequestInterceptor 并注入到IOC容器即可生效 示范代码如下 拷贝请求头,将原请求信…

Redis:Redis的数据类型介绍

Redis 支持多种数据类型,每种数据类型都有其特定的用途和优势。以下是 Redis 中主要数据类型的介绍: 1. String(字符串) 介绍:最基本的 Redis 数据类型,通常用于缓存和存储经常需要读取的数据。 示例&am…

病理级Polymer酶标二抗IHC试剂盒上线!

免疫组织化学 Immunohistochemistry,lHC 是利用抗体与抗原特异性识别原理,对组织样本中的抗原进行定位/定性分析的实验技术。组织切片保留了样品的解剖学结构特征,从而可以高分辨率地显现蛋白在细胞,甚至细胞器中的定位。基于以上特性&…

开源Mamba-2性能狂飙8倍!多个Mamba超强进化体拿下顶会

MambaOut的热度刚过去没多久,Mamba-2就带着它狂飙8倍的性能炸场了。 Mamba-2的核心层是对Mamba的选择性SSM的改进,同等性能下,模型更小,消耗更低,速度更快。与Mamba不同,新一代的Mamba-2再战顶会&#xff…

JVM垃圾收集器和性能调优

目标: 1.JVM垃圾收集器有哪几种? 2.CMS垃圾收集器回收步骤。 一、JVM常见的垃圾回收器 为什么垃圾回收的时候需要STW? 标记垃圾的时候,如果不STW,可能用户线程就会不停的产生垃圾。 1.1 单线程收集 Serial和SerialOld使用单…

windows架设NTP时间服务器进行时间同步

一、windows架设NTP时间服务器 1.win11更改注册表 winR输入regedit 2.HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\Config,找到Config目录,双击Config目录下的AnnounceFlags,设为5。 3.HKEY_LOCAL_MACHINE\SYSTEM\Current…

鸿蒙全栈开发-一文读懂鸿蒙同模块不同模块下的UIAbility跳转详解

前言 根据第三方机构Counterpoint数据,截至2023年三季度末,HarmonyOS在中国智能手机操作系统的市场份额已经提升至13%。短短四年的时间,HarmonyOS就成长为仅次于安卓、苹果iOS的全球第三大操作系统。 因此,对于鸿蒙生态建设而言&a…