C# Unity 面向对象补全计划 之 [反射]自动处理带有自定义[特性]的类

        本文仅作学习笔记与交流,不作任何商业用途,作者能力有限,如有不足还请斧正

        有一些插件就是利用本篇的方法做"自动"处理的

目录

1.情景:

2.介绍与举例:

  自定义特性API与使用

  反射搜索自定义API

3.优化

4.处理带有自定义特性的类


1.情景:

        你肯定见过这个东西,序列化私有字段的特性 将其变量可以显示在编辑器

[SerializeField]
private int hp;

         他是怎么实现的呢?F12进去看 其继承了C#之中的特性 [Atttibute]

        结合以前的知识,特性本质上就是一个标记,肯定还有其他什么代码去处理这个标记

所以就涉及Unity的序列化系统

  • 序列化流程

    1. 收集可序列化字段:Unity在导入脚本时,通过反射分析所有字段,检查是否标记了[SerializeField]或是否为公共字段。
    2. 生成序列化数据:将符合条件的字段(公共字段或标记了[SerializeField]的私有字段)的信息(名称、类型、值)保存到场景或预制体文件中。
    3. 反序列化:加载场景或预制体时,根据字段信息通过反射设置对应字段的值。
  • 私有字段访问

    • Unity使用反射的BindingFlags.NonPublic标志访问私有字段:
      FieldInfo field = type.GetField("_health", BindingFlags.NonPublic | BindingFlags

 其中有一个关键字叫做反射,所以今天就来看看怎么去自己实现[特性----反射处理]这个机制

2.介绍与举例:

  自定义特性API与使用


//参数一: 限定属性的作用对象, 这里是类
//参数二: 是否允许多个属性, 这里是false
//AttributeUsage 不做任何处理, 仅仅作为标记使用,此时Att就是一个特性了
[AttributeUsage(AttributeTargets.Class,AllowMultiple =false)]
public class Att : Attribute
{}
[Att]
public class Test { }

  反射搜索自定义API

using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;public class Rel : MonoBehaviour
{private void Awake(){GetAtt();}private  List<Type> attList = new List<Type>();private  void GetAtt() {//从当前应用程序域中加载所有程序集Assembly[] assArray = AppDomain.CurrentDomain.GetAssemblies();foreach (var ass in assArray){//获取程序集中所有类型Type[] typeArray = ass.GetTypes();foreach (var type in typeArray){Att att = type.GetCustomAttribute<Att>();if (att != null){// 将应用了 Att 特性的类型添加到列表中attList.Add(type);}} }Debug.Log(attList.Count);}
}

当前程序域下的所有程序集:

一个程序集可以包含一个或多个类型(类、接口等)的定义 

        这些是 Unity 引擎提供的程序集,每个模块对应了 Unity 引擎的不同功能部分,比如 UnityEngine.AIModule 可能包含了与人工智能相关的功能,UnityEngine.AnimationModule 包含了动画相关的功能。它们为开发者在 Unity 中创建游戏和互动内容提供了丰富的 API 

然后是单个程序集中的所有内容(因为是foreach遍历)

最后再foreach一遍直到在所有类型中找到想要的那个打了Att特性的类

3.优化

        你也看出来了,几千上万个甚至十几万个类型不断foreach 是很消耗性能的,所以可以用UnityEngine提供的一个方法进行优化

  1. 程序集范围限定
    只处理 Assembly-CSharp,避免无关程序集的反射遍历

  2. 利用 TypeCache
    Unity 内部缓存机制直接获取标记了特性的类型,无需手动反射

  3. 条件编译兼容旧版本
    通过 #if UNITY_2020_1_OR_NEWER 确保代码在旧版 Unity 中仍可运行

using System.Collections.Generic;
using UnityEngine;
using System.Reflection;
using System;#if UNITY_2020_1_OR_NEWER
using UnityEditor; // 需要 Unity 2020.1+ 的 TypeCache
#endifpublic class Rel : MonoBehaviour
{private List<Type> attList = new List<Type>();private void Awake(){GetAtt();}private void GetAtt(){// 优化1:限定在 Assembly-CSharp 程序集Assembly targetAssembly = null;foreach (var ass in AppDomain.CurrentDomain.GetAssemblies()){if (ass.GetName().Name == "Assembly-CSharp"){targetAssembly = ass;break;}}if (targetAssembly == null){Debug.LogError("Assembly-CSharp not found!");return;}// 优化2:使用 TypeCache 替代手动遍历(仅限 Unity 2020.1+)
#if UNITY_2020_1_OR_NEWERvar types = TypeCache.GetTypesWithAttribute<Att>();foreach (var type in types){// 优化3:进一步过滤确保类型属于 Assembly-CSharpif (type.Assembly == targetAssembly){attList.Add(type);}}
#else// 回退方案:手动遍历目标程序集中的所有类型foreach (var type in targetAssembly.GetTypes()){if (type.GetCustomAttribute<Att>() != null){attList.Add(type);}}
#endifDebug.Log(attList.Count);}
}

       你还可以将其作为编辑器下运行的方法 从开发阶段就可以运行获取该特性的类 然后做处理

 [InitializeOnLoadMethod]

4.处理带有自定义特性的类

        只是举一个简单的例子,该例子没有任何实用性

        但是可以突出我们获取到了带有自定义特性的类这一点

#if UNITY_EDITOR
using UnityEditor;
using UnityEngine;
[CustomEditor(typeof(Rel))]
public class RelEditor : Editor
{public override void OnInspectorGUI(){base.OnInspectorGUI();Rel rel = (Rel)target;// 显示所有标记 [Att] 的类型GUILayout.Label("Att-marked Types:");foreach (var type in rel.attList){GUILayout.Label(type.Name);}}
}
#endif

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI-Deepseek + PPT

01--Deepseek提问 首先去Deepseek问一个问题&#xff1a; Deepseek的回答&#xff1a; 在汽车CAN总线通信中&#xff0c;DBC文件里的信号处理&#xff08;如初始值、系数、偏移&#xff09;主要是为了 将原始二进制数据转换为实际物理值&#xff0c;确保不同电子控制单元&…

SpringMVC控制器定义:@Controller注解详解

文章目录 引言一、Controller注解基础二、RequestMapping与请求映射三、参数绑定与数据校验四、RestController与RESTful API五、控制器建议与全局处理六、控制器测试策略总结 引言 在SpringMVC框架中&#xff0c;控制器(Controller)是整个Web应用的核心组件&#xff0c;负责处…

自然语言处理:文本分类

介绍 大家好&#xff0c;我这个热衷于分享知识的博主又来啦&#xff01;之前我们一起深入探讨了自然语言处理领域中非常重要的两个方法&#xff1a;朴素贝叶斯和逻辑斯谛回归。在探索的过程中&#xff0c;我们剖析了朴素贝叶斯如何基于概率原理和特征条件独立假设&#xff0c;…

鸿蒙通过用户首选项实现数据持久化

鸿蒙通过用户首选项实现数据持久化 1.1 场景介绍 用户首选项为应用提供Key-Value键值型的数据处理能力&#xff0c;支持应用持久化轻量级数据&#xff0c;并对其修改和查询。当用户希望有一个全局唯一存储的地方&#xff0c;可以采用用户首选项来进行存储。Preferences会将该…

单元测试-pytest框架实践

文章目录 1. 单元测试用例目录2. 自动化测试用例编写步骤3. 命名规则4. 环境安装5. pytest语法5.1 unittest与pytest对比5.2 pytest运行插件5.3 fixture5.4 装饰器 6. pytest.ini7. conftest.py8. 用例编写步骤8.1 按照以下方式检查用例 9. 单元测试示例10. 运行11. 覆盖率12. …

嵌入式 ARM Linux 系统构成(1):Bootloader层

目录 一、Bootloader 概述 1.1 核心作用 1.2 典型启动流程 二、ARM Bootloader 架构详解 2.1 多阶段启动设计 2.2 关键代码流程 2.3. Bootloader的加载过程 2.4. Bootloader的加载方式 2.5. Bootloader 的移植 三、常见的Bootloader介绍 3.1. U-Boot 3.2. vivi …

Ubuntu20.04双系统安装及软件安装(九):谷歌浏览器

Ubuntu20.04双系统安装及软件安装&#xff08;九&#xff09;&#xff1a;谷歌浏览器 打开终端&#xff0c;下载谷歌浏览器软件包&#xff1a; wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb下载完成后直接在原终端执行&#xff1a; sudo…

【五.LangChain技术与应用】【10.LangChain ChatPromptTemplate(下):复杂场景下的应用】

凌晨两点的西二旗,你盯着监控大屏上跳动的错误日志,智能客服系统在流量洪峰中像纸船一样摇晃。用户骂声塞满弹窗:“等了十分钟就这?”“刚才说的怎么不认了?”“我要人工!!”——这时候你需要的不只是ChatPromptTemplate,而是给对话系统装上航天级操控台。 一、模板组…

Django项目实战

1、安装django 查看包安装的位置 pip镜像源 镜像源名称镜像地址​清华源​https://pypi.tuna.tsinghua.edu.cn/simple​阿里云​https://mirrors.aliyun.com/pypi/simple​腾讯云​https://mirrors.cloud.tencent.com/pypi/simple​华为云​https://repo.huaweicloud.co…

【YOLO V5】目标检测 WSL2 AutoDL VScode SSH

【YOLO V5】目标检测 WSL2 AutoDL VScode SSH 前言整体思路理解向YOLO 目标检测完整流程 环境配置Anaconda 获取 YOLO 代码与预训练模型下载 YOLOv5 代码和预训练模型配置 YOLOV5 工程环境解压 YOLOv5 源代码 并 添加预训练模型调整依赖版本选择对应的 Python 解释器 数据集准备…

PMP项目管理—沟通管理篇—1.规划沟通管理

文章目录 基本信息步骤4W1HITTO输入工具与技术输出 沟通需求分析沟通技术沟通模型沟通噪声障碍的类型 沟通漏斗模型 沟通方法相关方参与度评估矩阵传递方式影响沟通效果沟通管理计划 基本信息 步骤 收集信息&#xff0c;加工信息确定项目沟通需求确定项目沟通的方法编制项目沟…

SCI期刊推荐 | 免版面费 | 计算机领域:信息系统、软件工程、自动化和控制

在学术研究领域&#xff0c;选择合适的SCI期刊对科研成果的传播与认可至关重要。了解SCI期刊的研究领域和方向是基础&#xff0c;确保投稿内容与期刊主题相符。同时&#xff0c;要关注期刊的影响因子和评估标准&#xff0c;选择具有较高影响力和学术认可度的期刊。阅读期刊的投…

EasyDSS视频推拉流系统:清理缓存文件时如何确保缓存读写不受影响?

视频推拉流EasyDSS视频直播点播平台可提供一站式的视频转码、点播、直播、视频推拉流、播放H.265视频等服务&#xff0c;搭配RTMP高清摄像头使用&#xff0c;可将无人机设备的实时流推送到平台上&#xff0c;实现无人机视频推流直播、巡检等应用。 有用户咨询&#xff0c;视频推…

探秘基带算法:从原理到5G时代的通信变革【四】Polar 编解码(二)

文章目录 2.3.3 极化编码巴氏参数与信道可靠性比特混合生成矩阵编码举例 2.3.4 极化译码最小单元译码串行抵消译码&#xff08;SC译码&#xff09;算法SCL译码算法 2.3.5 总结**Polar 码的优势****Polar 码的主要问题****Polar 码的应用前景** 2.3.6 **参考文档** 本博客为系列…

GCC RISCV 后端 -- cc1 入口

GCC编译工具链中的 gcc 可执行程序&#xff0c;实际上是个驱动程序&#xff08;Driver&#xff09;&#xff0c;其根据输入的参数&#xff0c;然后调用其它不同的程序&#xff0c;对输入文件进行处理&#xff0c;包括编译、链接等。可以通过以下命令查看&#xff1a; gcc -v h…

用DeepSeek-R1-Distill-data-110k蒸馏中文数据集 微调Qwen2.5-7B-Instruct!

下载模型与数据 模型下载&#xff1a; huggingface&#xff1a; Qwen/Qwen2.5-7B-Instruct HF MirrorWe’re on a journey to advance and democratize artificial intelligence through open source and open science.https://hf-mirror.com/Qwen/Qwen2.5-7B-Instruct 魔搭&a…

基于编译器特性浅析C++程序性能优化

最近在恶补计算机基础知识&#xff0c;学到CSAPP第五章的内容&#xff0c;在这里总结并且展开一下C程序性能优化相关的内容。 衡量程序性能的方式 一般而言&#xff0c;程序的性能可以用CPE&#xff08;Cycles Per Element&#xff09;来衡量&#xff0c;其指的是处理每个元素…

K8s控制器Deployment详解

回顾 ReplicaSet 控制器,该控制器是用来维护集群中运行的 Pod 数量的&#xff0c;但是往往在实际操作的时候&#xff0c;我们反而不会去直接使用 RS&#xff0c;而是会使用更上层的控制器&#xff0c;比如说 Deployment。 Deployment 一个非常重要的功能就是实现了 Pod 的滚动…

大模型巅峰对决:DeepSeek vs GPT-4/Claude/PaLM-2 全面对比与核心差异揭秘

文章目录 一、架构设计深度解剖1.1 核心架构对比图谱1.2 动态MoE架构实现架构差异分析表 二、训练策略全面对比2.1 训练数据工程对比2.2 分布式训练代码对比DeepSeek混合并行实现GPT-4 Megatron实现对比 2.3 关键训练参数对比 三、性能表现多维评测3.1 基准测试全景对比3.2 推理…

【MySQL_02】安装(8.4.4LTS : Windows + Linux)

文章目录 一、版本说明二、官网下载三、Windows安装3.1 安装和配置3.2 四、Linux安装 历史文章点击&#x1f449;&#xff1a;SQL &#x1f408;‍⬛github&#xff1a;https://github.com/mysql &#x1f4bb;官网&#xff1a; https://www.mysql.com &#x1f30f;维基百科…