在Unity编辑模式下运行Mono中的方法
[ExecuteAlways]
最简单的方法当然是直接给Mono加上[ExecuteAlways]修饰,这样Mono中的Awake,Update等等都可以在编辑模式下按照原本的时机运行。
[ExecuteAlways]
public class TestScript : MonoBehaviour {void TestMethod(){Debug.Log("TestMethod");}void Update(){TestMethod();}
}
OnValidate
除了ExecuteAlways以外,还可以用OnValidate,OnValidate 方法会在脚本中的变量发生更改时自动调用,适用于与 Inspector 参数联动的逻辑。
public class TestScript : MonoBehaviour {public float value;private void OnValidate(){// 在编辑器中参数变更时自动调用Debug.Log($"Value changed to: {value}");}
}
OnDrawGizmos+SceneView.RepaintAll()
有的时候如果想让某段代码能在编辑模式下像Update一样一直运行,但又不想用[ExecuteAlways]或者觉得没必要,就可以用这个方法,需要在SceneView里打开Gizmos的开关

public class TestScript : MonoBehaviour {void TestMethod(){Debug.Log("TestMethod");}//force update on editormodevoid OnDrawGizmos() {if (!Application.isPlaying) {//call you methodTestMethod();}//force Repaintif (!Application.isPlaying) {UnityEditor.EditorApplication.QueuePlayerLoopUpdate();UnityEditor.SceneView.RepaintAll();}}
}
扩展
一般来说上面提到的几个算是够用了,但我在使用OnDrawGizmos方法的时候,依旧觉得太麻烦,就没有什么更方便的方法吗,于是我想到了C#的Attribute,如果可以像[ExecuteAlways]那样简单的标记一个方法,让这方法可以不断的被调用,那写起来不就方便多了吗,于是
EditorUpdateMethodManager
//==============================================================================
// Filename: EditorUpdateMethodManager
// Description:
//
// Version: 1.0
// Compiler: 2022.3.40f1 (cbdda657d2f0)
// Author: Akota
// CreateTime: 2024-12-02 10:14:40
//==============================================================================
using System;
using UnityEngine;
#if UNITY_EDITOR
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEditor;
#endif[ExecuteAlways]
public class EditorUpdateMethodManager : MonoBehaviour {private void Awake() {if (Application.isPlaying) {Destroy(gameObject);}}
#if UNITY_EDITORprivate List<RegisteredMethod> RegisteredMethods = new List<RegisteredMethod>();private void OnEnable() {if (!Application.isPlaying) { RegisterMethodsFromScene();EditorApplication.hierarchyChanged += RegisterMethodsFromScene; // 监听层级变化}}private void OnDisable() {if (!Application.isPlaying) { EditorApplication.hierarchyChanged -= RegisterMethodsFromScene; // 移除监听}}private void Update() {if (!Application.isPlaying) { foreach (var registeredMethod in RegisteredMethods) {// 仅调用激活的 MonoBehaviour 实例上的方法if (registeredMethod.MonoInstance != null &®isteredMethod.MonoInstance.enabled &®isteredMethod.MonoInstance.gameObject.activeInHierarchy) {registeredMethod.Method.Invoke(registeredMethod.MonoInstance, null);}}}}/// <summary>/// 注册当前场景中的所有标记方法/// </summary>public void RegisterMethodsFromScene() {RegisteredMethods.Clear();// 获取当前场景中所有 MonoBehaviourvar monoBehaviours = FindObjectsOfType<MonoBehaviour>(true); // 包括未激活的对象foreach (var mono in monoBehaviours) {// 查找带有 RegisterEditorUpdateMethodAttribute 的方法var methods = mono.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Where(m => m.GetCustomAttribute<EditorUpdateMethodAttribute>() != null);foreach (var method in methods) {// 记录方法和实例RegisteredMethods.Add(new RegisteredMethod(mono, method));}}}/// <summary>/// 注册方法信息/// </summary>private class RegisteredMethod {public MonoBehaviour MonoInstance { get; }public MethodInfo Method { get; }public RegisteredMethod(MonoBehaviour monoInstance, MethodInfo method) {MonoInstance = monoInstance;Method = method;}}
#endif
}/// <summary>
/// 标记可以被 EditorUpdateMethodManager 调用的方法
/// </summary>
[AttributeUsage(AttributeTargets.Method)]
public class EditorUpdateMethodAttribute : Attribute {
}
原理也很简单,就是利用[ExecuteAlways]来标记EditorUpdateMethodManager,然后在EditorUpdateMethodManager里面查找当前场景下的所有Mono里被EditorUpdateMethod标记的方法,并在Manager的Update中统一调用。
示例
public class TestScript : MonoBehaviour {[EditorUpdateMethod]void TestMethod(){Debug.Log("TestMethod");}
}
要是手动在场景里创建一个Manager还是嫌麻烦的话
EditorUpdateManagerInitializer
//==============================================================================
// Filename: EditorUpdateManagerInitializer
// Description:
//
// Version: 1.0
// Compiler: 2022.3.40f1 (cbdda657d2f0)
// Author: Akota
// CreateTime: 2024-12-02 10:16:02
//==============================================================================
#if UNITY_EDITOR
using System;
using System.Linq;
using System.Reflection;
using UnityEngine;
using UnityEditor;
using UnityEditor.SceneManagement;[InitializeOnLoad]
public static class EditorUpdateManagerInitializer {static EditorUpdateManagerInitializer() {// 监听层级变化EditorApplication.hierarchyChanged += EnsureEditorUpdateMethodManagerExists;EnsureEditorUpdateMethodManagerExists(); // 初次调用}/// <summary>/// 检查场景中是否存在标记方法,并确保 EditorUpdateMethodManager 存在/// </summary>private static void EnsureEditorUpdateMethodManagerExists() {// 检查场景中是否存在 EditorUpdateMethodManagervar existingManager = GameObject.FindObjectOfType<EditorUpdateMethodManager>();if (existingManager == null) { if (HasRegisterEditorUpdateMethodsInScene()) {// 没有 EditorUpdateMethodManager,创建一个var managerObject = new GameObject("EditorUpdateMethodManager");managerObject.AddComponent<EditorUpdateMethodManager>();// 标记场景为脏Undo.RegisterCreatedObjectUndo(managerObject, "Create EditorUpdateMethodManager");EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());Debug.Log("[EditorUpdateManagerInitializer] 自动创建了 EditorUpdateMethodManager");}}else {// 如果不需要且已有 Manager,则移除//Debug.Log("[EditorUpdateManagerInitializer] 场景中没有标记方法,移除了 EditorUpdateMethodManager");//Undo.DestroyObjectImmediate(existingManager.gameObject);//EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());}}/// <summary>/// 检查场景中是否有被 RegisterEditorUpdateMethodAttribute 标记的方法/// </summary>private static bool HasRegisterEditorUpdateMethodsInScene() {// 获取当前场景中所有 MonoBehaviourvar monoBehaviours = GameObject.FindObjectsOfType<MonoBehaviour>(true); // 包括未激活的对象foreach (var mono in monoBehaviours) {// 检查该 MonoBehaviour 类型是否有标记的方法var methods = mono.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Where(m => m.GetCustomAttribute<EditorUpdateMethodAttribute>() != null);if (methods.Any()) {return true;}}return false;}
}
#endif
这段代码会自动检测场景中是否有被EditorUpdateMethod修饰的方法,有的话就自动创建Manager
更新
考虑到要在场景里创建物体,可能显得有点累赘,于是新版放弃[ExecuteAlways],改为利用EditorApplication.update来实现,更精简了
//==============================================================================
// Filename: EditorUpdateMethodManager
// Description:
//
// Version: 1.0
// Compiler: 2022.3.40f1 (cbdda657d2f0)
// Author: Akota
// CreateTime: 2024-12-02 14:13:12
//==============================================================================
#if UNITY_EDITOR
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEngine;public class EditorUpdateMethodManager{public static EditorUpdateMethodManager instance = null;[InitializeOnLoadMethod]public static void Init() {instance = new EditorUpdateMethodManager();}public EditorUpdateMethodManager() {if (!Application.isPlaying) {RegisterMethodsFromScene();}EditorApplication.hierarchyChanged += RegisterMethodsFromScene; // 监听层级变化EditorApplication.update += Update;}private List<RegisteredMethod> RegisteredMethods = new List<RegisteredMethod>();void Update() {if (!Application.isPlaying) {foreach (var registeredMethod in RegisteredMethods) {// 仅调用激活的 MonoBehaviour 实例上的方法if (registeredMethod.MonoInstance != null &®isteredMethod.MonoInstance.enabled &®isteredMethod.MonoInstance.gameObject.activeInHierarchy) {registeredMethod.Method.Invoke(registeredMethod.MonoInstance, null);}}}}/// <summary>/// 注册当前场景中的所有标记方法/// </summary>public void RegisterMethodsFromScene() {RegisteredMethods.Clear();// 获取当前场景中所有 MonoBehaviourvar monoBehaviours = Object.FindObjectsOfType<MonoBehaviour>(true); // 包括未激活的对象foreach (var mono in monoBehaviours) {// 查找带有 RegisterEditorUpdateMethodAttribute 的方法var methods = mono.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Where(m => m.GetCustomAttribute<EditorUpdateMethodAttribute>() != null);foreach (var method in methods) {// 记录方法和实例RegisteredMethods.Add(new RegisteredMethod(mono, method));}}}/// <summary>/// 注册方法信息/// </summary>private class RegisteredMethod {public MonoBehaviour MonoInstance { get; }public MethodInfo Method { get; }public RegisteredMethod(MonoBehaviour monoInstance, MethodInfo method) {MonoInstance = monoInstance;Method = method;}}
}
#endif
/// <summary>
/// 标记可以被 EditorUpdateMethodManager 调用的方法
/// </summary>
[System.AttributeUsage(System.AttributeTargets.Method)]
public class EditorUpdateMethodAttribute : System.Attribute {
}
其他
还有其他的一些,比如编写CustomEditor,在Editor中一直调用方法,又或者用Editor画个按钮,通过在Inspector上手动点击来调用代码,当然也可以用Odin插件,直接用Button修饰Mono中的方法,就会在Inspector上出现按钮了。
结语
代码写的很随便也很丑陋,望包涵
相关文章:
在Unity编辑模式下运行Mono中的方法
[ExecuteAlways] 最简单的方法当然是直接给Mono加上[ExecuteAlways]修饰,这样Mono中的Awake,Update等等都可以在编辑模式下按照原本的时机运行。 [ExecuteAlways] public class TestScript : MonoBehaviour {void TestMethod(){Debug.Log("TestMe…...
Y20030028 JAVA+SSM+MYSQL+LW+基于JAVA的考研监督互助系统的设计与实现 源代码 配置 文档
基于JAVA的考研监督互助系统 1.项目描述2. 课题开发背景及意义3.项目功能4.界面展示5.源码获取 1.项目描述 随着高等教育的普及和就业竞争的加剧,越来越多的学生选择继续深造,参加研究生入学考试。考研人数的不断增加,使得考研过程中的学习监…...
MATLAB期末复习笔记(下)
目录 五、数据和函数的可视化 1.MATLAB的可视化对象 2.二维图形的绘制 3.图形标识 4.多子图绘图 5.直方图的绘制 (1)分类 (2)垂直累计式 (3)垂直分组式 (4)水平分组式 &…...
「Mac畅玩鸿蒙与硬件37」UI互动应用篇14 - 随机颜色变化器
本篇将带你实现一个随机颜色变化器应用。用户点击“随机颜色”按钮后,界面背景会随机变化为淡色系颜色,同时显示当前的颜色代码,页面还会展示一只猫咪图片作为装饰,提升趣味性。 关键词 UI互动应用随机颜色生成状态管理用户交互…...
MySql:理解数据库
目录 一、什么是数据库 第一层理解 第二层理解 第三层理解 二、Linux下的数据库 三、基本认识 登录数据库时, mysql -u root -h 127.0.0.1 -P 3306 -p -h指定MySql服务器所在主机,若在本地则为回环地址。-P表示目标主机上MySql服务端口号 一般简单…...
学习笔记051——SpringBoot学习2
文章目录 Spring Boot 原理1、SpringBootConfiguration2、ConfigurationProperties3、ComponentScan4、EnableAutoConfiguration Spring Boot 原理 Spring Boot 可以自动读取配置文件,将项目所需要的组件全部自动加载到 IoC 容器中,包括两部分 开发者自…...
crush rule 20 type does not match pool
问题 kubectl describe CephObjectStore ceph-objectstoreEvents:Type Reason Age From Message---- ------ ---- ---- -------Warning ReconcileFailed 14m …...
BA是什么?
目录 1.EKF的步骤 一、问题定义与模型建立 二、线性化处理 三、应用卡尔曼滤波 四、迭代与收敛 五、结果评估与优化 注意事项 2.BA问题的步骤 一、问题定义与数据准备 二、构建优化模型 三、选择优化算法 四、执行优化过程 五、结果评估与优化 六、应用与验证 1.…...
通过docker 搭建jenkins环境;
一、官网简介使用安装说明: How to use this image docker run -p 8080:8080 -p 50000:50000 jenkins This will store the workspace in /var/jenkins_home. All Jenkins data lives in there - including plugins and configuration. You will probably want to make that …...
10-高级主题
第10节 高级主题 在这一节中,我们将探讨一些 Python 中的高级主题,包括装饰器、生成器、上下文管理器、元类以及常用的设计模式。这些高级特性能够帮助你编写更强大、更灵活的代码。 10.1 装饰器 装饰器是一种特殊类型的函数,可以修改其他函数…...
harbor常见问题及解决方法分享
harbor常见问题及解决方法分享 参考自《harbor权威指南》。 1. harbor配置文件不生效 问题现象 无论是在生产环境下还是在测试环境下,都会有对配置文件进行修改的场景。很多用户在停掉Harbor容器后,都会修改配置文件然后启动Harbor,发现配…...
行列式与线性方程组解的关系
线性方程组是数学中一个重要的概念,它描述了多个变量之间的线性关系。行列式作为方阵的一个特殊值,对于判断线性方程组解的存在性和唯一性有着重要的作用。本文将探讨行列式与线性方程组解之间的关系,并区分齐次和非齐次方程组的情况。 齐次…...
四、自然语言处理_02RNN基础知识笔记
1、RNN的定义 RNN(Recurrent Neural Network,循环神经网络)是一种专门用于处理序列数据的神经网络架构,它与传统的前馈神经网络(Feedforward Neural Network)不同,主要区别在于它能够处理输入数…...
Spring 容器管理 Bean
Bean是什么 Bean 是指 Java 中的可重用软件组件,容器会根据提供的元数据来创建和管理这些 Bean,也包括它们之间的依赖关系。Spring 容器对 Bean 并没有太多的要求,无须实现特定接口或依赖特定库,只要是最普通的 Java 对象即可,这类对象也被称为 POJO(Plain Old Java Obj…...
SpringBoot开发——Spring Boot3.4 强大的结构化日志记录
文章目录 1. 简介2. 实战案例2.1 环境依赖2.2 快速入门2.3 输出到文件2.4 添加附加字段2.5 自定义日志格式总结1. 简介 日志记录是应用故障排除中早已确立的部分,也是可观测性的三大支柱之一,另外两个是指标和追踪。在生产环境中,没有人喜欢盲目行事,而当故障发生时,开发…...
信号和槽思维脑图+相关练习
将登录框中的取消按钮使用信号和槽的机制,关闭界面。 将登录按钮使用信号和槽连接到自定义的槽函数中,在槽函数中判断ui界面上输入的账号是否为"admin",密码是否为"123456",如果账号密码匹配成功,当前界面关…...
Unity Feel插件快速入门
What is Feel? Feel是一个即用型解决方案,让你的Unity项目提高游戏体验,增强玩家获得的反馈感,例如相机震动,屏幕闪烁,淡入淡出,等等几十种效果。这是一个模块化、用户友好、易于扩展的系统。 本文旨在让你快速入门,从全局快速了解这个插件,以及基本用…...
数据链路层(四)---PPP协议的工作状态
1 PPP链路的初始化 通过前面几章的学习,我们学了了PPP协议帧的格式以及组成,那么对于使用PPP协议的链路是怎么初始化的呢? 当用户拨号上网接入到ISP后,就建立起了一条个人用户到ISP的物理链路。这时,用户向ISP发送一…...
【C++】入门【六】
本节目标 一、继承的概念及定义 二、基类和派生类对象赋值转换 三、继承中的作用域 四、派生类的默认成员函数 五、继承与友元 六、继承与静态成员 七、复杂的菱形继承及菱形虚拟继承 八、继承的总结和反思 九、笔试面试题 一、继承的概念及定义 1.继承的概念 继承是面向对象…...
UE5 C++ 不规则按钮识别,复选框不规则识别 UPIrregularWidgets
插件名称:UPIrregularWidgets 插件包含以下功能 你可以点击任何图片,而不仅限于矩形图片。 UPButton、UPCheckbox 基于原始的 Button、Checkbox 扩展。 复选框增加了不规则图像识别功能,复选框增加了悬停事件。 欢迎来到我的博客 记录学习过…...
ECharts折线图入门学习:从基础到实战的完整指南
引言 折线图是数据可视化中最常用的图表类型之一,特别适合展示数据随时间变化的趋势。ECharts作为一款功能强大的JavaScript可视化库,提供了丰富的配置选项和交互功能,能够轻松创建出专业、美观的折线图。本文将带领大家从零开始学习ECharts折…...
程序员副业指南:从技术到收入的10种变现路径
CSDN程序员副业图谱技术文章大纲副业方向概览技术博客与内容创作:分享技术经验、教程、行业见解在线教育与课程开发:录制视频课程、开设直播讲座开源项目与工具开发:参与或主导开源项目,开发实用工具自由职业与远程工作࿱…...
AI命理工具实测:主流大模型八字紫微能力对比及避坑指南
1. AI命理新风向:当大模型碰撞传统术数 最近身边刮起了一阵“AI命理”的热潮:做开发的朋友电脑里存着排盘工具包,运营岗的同事午休时在研究紫微斗数星曜含义,就连开策划会的间隙,都有人拿着AI输出的六爻结果讨论项目走…...
Agent在零售行业能解决哪些痛点?——深度解析零售企业智能自动化转型路径
在2026年零售行业加速迈向智能化的背景下,AI Agent(人工智能智能体)已不再仅仅是技术实验室的产物,而是演变为重构行业价值链的核心驱动力。传统的零售运营长期受困于人力密集型模式,面临着全球化运营复杂度高、数据孤…...
保姆级教程:在OpenEuler 22.03 LTS-SP4上,用cephadm搞定Ceph Pacific集群部署
在OpenEuler 22.03 LTS-SP4上部署Ceph Pacific集群的完整指南 OpenEuler作为国产操作系统的代表,凭借其高性能和安全性,正逐渐成为企业级应用的首选。而Ceph作为开源的分布式存储解决方案,以其高可靠性和可扩展性赢得了广泛认可。本文将详细介…...
I.MX6U-MINI开发板系统固化全流程:从uboot编译到rootfs烧录(附网络配置技巧)
I.MX6U-MINI开发板系统固化实战指南:从零构建到网络调优 第一次拿到I.MX6U-MINI开发板时,面对系统固化的多个环节总有种无从下手的感觉。作为嵌入式Linux开发的入门门槛,系统固化不仅关系到后续应用开发的基础环境,更是理解嵌入式…...
人工智能|大模型——模型——大模型蒸馏详解(定义/原理/关键技术/落地)
摘要大模型蒸馏(Model Distillation),即知识蒸馏(Knowledge Distillation),是一种将大型教师模型(如BERT、GPT-4o、DeepSeek-R1)的“隐含知识”高效迁移至轻量级学生模型(…...
【手把手教学】使用stitch 生成ui图,导入figma,再用codebuddy生成工程代码
目录 一.stich使用 1.1 关键词生成 1.2 生成ui图 1.3 导出figma编辑 二. codebuddy使用 编辑2.1打开figma 编辑 2.2 复制ui到设计面板 2.3生成工程代码 三. 结语 一.stich使用 stich官网地址 Google Stitch 是 Google Labs 推出的、基于 Gemini 大模型驱动的A…...
Windows屏幕取色器ColorWanted:设计师和开发者的效率神器
Windows屏幕取色器ColorWanted:设计师和开发者的效率神器 【免费下载链接】ColorWanted Screen color picker for Windows (Windows 上的屏幕取色器) 项目地址: https://gitcode.com/gh_mirrors/co/ColorWanted 你是否经常需要在设计软件、网页开发或UI设计中…...
[STM32问题解决(2)]编译错误:Error: L6218E的深度解析与实战排查指南
1. 认识Error: L6218E编译错误 当你正在Keil MDK环境下开发STM32项目时,突然弹出一个红色错误提示:"Error: L6218E: Undefined symbol xxx (referred from xxx.o)",这可能是每个STM32开发者都会遇到的经典问题。我第一次遇到这个错…...
