当前位置: 首页 > news >正文

在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 &&registeredMethod.MonoInstance.enabled &&registeredMethod.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 &&registeredMethod.MonoInstance.enabled &&registeredMethod.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]修饰&#xff0c;这样Mono中的Awake&#xff0c;Update等等都可以在编辑模式下按照原本的时机运行。 [ExecuteAlways] public class TestScript : MonoBehaviour {void TestMethod(){Debug.Log("TestMe…...

Y20030028 JAVA+SSM+MYSQL+LW+基于JAVA的考研监督互助系统的设计与实现 源代码 配置 文档

基于JAVA的考研监督互助系统 1.项目描述2. 课题开发背景及意义3.项目功能4.界面展示5.源码获取 1.项目描述 随着高等教育的普及和就业竞争的加剧&#xff0c;越来越多的学生选择继续深造&#xff0c;参加研究生入学考试。考研人数的不断增加&#xff0c;使得考研过程中的学习监…...

MATLAB期末复习笔记(下)

目录 五、数据和函数的可视化 1.MATLAB的可视化对象 2.二维图形的绘制 3.图形标识 4.多子图绘图 5.直方图的绘制 &#xff08;1&#xff09;分类 &#xff08;2&#xff09;垂直累计式 &#xff08;3&#xff09;垂直分组式 &#xff08;4&#xff09;水平分组式 &…...

「Mac畅玩鸿蒙与硬件37」UI互动应用篇14 - 随机颜色变化器

本篇将带你实现一个随机颜色变化器应用。用户点击“随机颜色”按钮后&#xff0c;界面背景会随机变化为淡色系颜色&#xff0c;同时显示当前的颜色代码&#xff0c;页面还会展示一只猫咪图片作为装饰&#xff0c;提升趣味性。 关键词 UI互动应用随机颜色生成状态管理用户交互…...

MySql:理解数据库

目录 一、什么是数据库 第一层理解 第二层理解 第三层理解 二、Linux下的数据库 三、基本认识 登录数据库时&#xff0c; mysql -u root -h 127.0.0.1 -P 3306 -p -h指定MySql服务器所在主机&#xff0c;若在本地则为回环地址。-P表示目标主机上MySql服务端口号 一般简单…...

学习笔记051——SpringBoot学习2

文章目录 Spring Boot 原理1、SpringBootConfiguration2、ConfigurationProperties3、ComponentScan4、EnableAutoConfiguration Spring Boot 原理 Spring Boot 可以自动读取配置文件&#xff0c;将项目所需要的组件全部自动加载到 IoC 容器中&#xff0c;包括两部分 开发者自…...

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节 高级主题 在这一节中&#xff0c;我们将探讨一些 Python 中的高级主题&#xff0c;包括装饰器、生成器、上下文管理器、元类以及常用的设计模式。这些高级特性能够帮助你编写更强大、更灵活的代码。 10.1 装饰器 装饰器是一种特殊类型的函数&#xff0c;可以修改其他函数…...

harbor常见问题及解决方法分享

harbor常见问题及解决方法分享 参考自《harbor权威指南》。 1. harbor配置文件不生效 问题现象 无论是在生产环境下还是在测试环境下&#xff0c;都会有对配置文件进行修改的场景。很多用户在停掉Harbor容器后&#xff0c;都会修改配置文件然后启动Harbor&#xff0c;发现配…...

行列式与线性方程组解的关系

线性方程组是数学中一个重要的概念&#xff0c;它描述了多个变量之间的线性关系。行列式作为方阵的一个特殊值&#xff0c;对于判断线性方程组解的存在性和唯一性有着重要的作用。本文将探讨行列式与线性方程组解之间的关系&#xff0c;并区分齐次和非齐次方程组的情况。 齐次…...

四、自然语言处理_02RNN基础知识笔记

1、RNN的定义 RNN&#xff08;Recurrent Neural Network&#xff0c;循环神经网络&#xff09;是一种专门用于处理序列数据的神经网络架构&#xff0c;它与传统的前馈神经网络&#xff08;Feedforward Neural Network&#xff09;不同&#xff0c;主要区别在于它能够处理输入数…...

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. 简介 日志记录是应用故障排除中早已确立的部分,也是可观测性的三大支柱之一,另外两个是指标和追踪。在生产环境中,没有人喜欢盲目行事,而当故障发生时,开发…...

信号和槽思维脑图+相关练习

将登录框中的取消按钮使用信号和槽的机制&#xff0c;关闭界面。 将登录按钮使用信号和槽连接到自定义的槽函数中&#xff0c;在槽函数中判断ui界面上输入的账号是否为"admin"&#xff0c;密码是否为"123456",如果账号密码匹配成功&#xff0c;当前界面关…...

Unity Feel插件快速入门

What is Feel? Feel是一个即用型解决方案&#xff0c;让你的Unity项目提高游戏体验&#xff0c;增强玩家获得的反馈感,例如相机震动,屏幕闪烁,淡入淡出,等等几十种效果。这是一个模块化、用户友好、易于扩展的系统。 本文旨在让你快速入门,从全局快速了解这个插件,以及基本用…...

数据链路层(四)---PPP协议的工作状态

1 PPP链路的初始化 通过前面几章的学习&#xff0c;我们学了了PPP协议帧的格式以及组成&#xff0c;那么对于使用PPP协议的链路是怎么初始化的呢&#xff1f; 当用户拨号上网接入到ISP后&#xff0c;就建立起了一条个人用户到ISP的物理链路。这时&#xff0c;用户向ISP发送一…...

【C++】入门【六】

本节目标 一、继承的概念及定义 二、基类和派生类对象赋值转换 三、继承中的作用域 四、派生类的默认成员函数 五、继承与友元 六、继承与静态成员 七、复杂的菱形继承及菱形虚拟继承 八、继承的总结和反思 九、笔试面试题 一、继承的概念及定义 1.继承的概念 继承是面向对象…...

UE5 C++ 不规则按钮识别,复选框不规则识别 UPIrregularWidgets

插件名称&#xff1a;UPIrregularWidgets 插件包含以下功能 你可以点击任何图片&#xff0c;而不仅限于矩形图片。 UPButton、UPCheckbox 基于原始的 Button、Checkbox 扩展。 复选框增加了不规则图像识别功能&#xff0c;复选框增加了悬停事件。 欢迎来到我的博客 记录学习过…...

避坑指南:在华为Atlas 200DK A2上部署YOLOv8-pose模型前,如何用ONNX Runtime在CPU/GPU上验证推理流程

边缘部署前的关键验证&#xff1a;YOLOv8-pose模型在CPU/GPU环境下的ONNX Runtime推理实战 在AI模型边缘部署的实践中&#xff0c;一个经常被忽视却至关重要的环节是本地验证。许多工程师在将模型部署到华为Atlas 200DK A2等边缘设备时&#xff0c;常常跳过这一步骤直接进入板端…...

JeecgBoot启动配置

一、引入maven指定自己的maven仓库 二、指定JDK 记得apply&#xff01;&#xff01;&#xff01;&#xff01;然后OK 三、配置MySQL数据库(尽量≥5.7版本) 四、运行db文件夹下的SQL文件 五、后端本地环境&#xff08;application-dev.yml&#xff09;指定好数据源 1、M…...

AI报告文档审核助力本地化升级:IACheck如何支撑食品加工行业数据安全与质量协同发展

在食品加工行业不断强化质量控制与数据安全要求的背景之下&#xff0c;“本地部署”正逐渐成为企业数字化转型中的关键路径之一&#xff0c;尤其是在涉及检测数据与质量报告的场景中&#xff0c;数据不仅需要具备高度准确性&#xff0c;还必须满足合规与安全要求&#xff0c;因…...

MySQL 事务与并发控制:从日志底层到 MVCC 哲学

MySQL 事务与并发控制&#xff1a;从日志底层到 MVCC 哲学 文章目录 MySQL 事务与并发控制&#xff1a;从日志底层到 MVCC 哲学&#x1f4da; 课程大纲规划 &#x1f4d6; 第一讲&#xff1a;基础——事务概念与隔离级别1. &#x1f3ad; 并发带来的三大“幽灵”&#x1f47b; …...

程序员副业指南:从技术到收入的10种变现路径

CSDN程序员副业图谱技术文章大纲副业方向概览技术博客与内容创作&#xff1a;分享技术经验、教程、行业见解在线教育与课程开发&#xff1a;录制视频课程、开设直播讲座开源项目与工具开发&#xff1a;参与或主导开源项目&#xff0c;开发实用工具自由职业与远程工作&#xff1…...

秒杀系统主库宕机不丢单方案-02-半同步AFTER_SYNC

秒杀系统主库宕机不丢单方案&#xff1a;半同步AFTER_SYNC&#xff08;主从确认再提交&#xff09; 方案概述 半同步复制AFTER_SYNC方案是MySQL 5.7版本引入的高级复制机制&#xff0c;通过主从节点之间的确认机制确保数据不丢失。该方案在主库提交事务前&#xff0c;等待至少一…...

DFRobot URM07超声波传感器UART通信与温度补偿详解

1. DFRobot URM07超声波测距传感器技术深度解析1.1 产品定位与工程价值DFRobot URM07&#xff08;SKU: SEN0153&#xff09;是一款面向嵌入式系统设计的工业级超声波距离传感器模块&#xff0c;其核心价值在于将高精度测距、环境温度补偿、超低功耗与UART标准化接口四者深度融合…...

突破Wallpaper Engine资源壁垒:RePKG工具全方位应用指南

突破Wallpaper Engine资源壁垒&#xff1a;RePKG工具全方位应用指南 【免费下载链接】repkg Wallpaper engine PKG extractor/TEX to image converter 项目地址: https://gitcode.com/gh_mirrors/re/repkg 一、RePKG&#xff1a;解锁创意资源的技术钥匙 在数字创意领域…...

当相机位姿已知:利用COLMAP从稀疏到稠密重建的实战指南

1. 环境准备与数据格式转换 在开始COLMAP重建之前&#xff0c;我们需要确保环境配置正确&#xff0c;并完成相机位姿数据的格式转换。COLMAP支持Windows、Linux和macOS系统&#xff0c;但为了获得最佳性能&#xff0c;建议使用配备NVIDIA显卡的机器&#xff0c;并安装CUDA加速版…...

LCC-LCC无线充电恒流/恒压闭环移相控制仿真 Simulink仿真模型,LCC-LCC谐振...

LCC-LCC无线充电恒流/恒压闭环移相控制仿真 Simulink仿真模型&#xff0c;LCC-LCC谐振补偿拓扑&#xff0c;闭环移相控制 1. 输入直流电压350V&#xff0c;负载为切换电阻&#xff0c;分别为50-60-70Ω&#xff0c;最大功率3.4kW&#xff0c;最大效率为93.6% 2. 闭环PI控制&…...