当前位置: 首页 > 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;复选框增加了悬停事件。 欢迎来到我的博客 记录学习过…...

X86与ARM架构深度解析:从指令集到生态的全面对比

1. 项目概述&#xff1a;为什么我们需要重新审视X86与ARM最近几年&#xff0c;无论是选购新电脑、关注手机芯片&#xff0c;还是围观科技新闻&#xff0c;你肯定没少听到“X86”和“ARM”这两个词。苹果的Mac电脑全面转向自研的M系列芯片&#xff0c;让“ARM架构”从手机、平板…...

TegraRcmGUI终极指南:Windows上最简单的Switch注入工具免费使用教程

TegraRcmGUI终极指南&#xff1a;Windows上最简单的Switch注入工具免费使用教程 【免费下载链接】TegraRcmGUI C GUI for TegraRcmSmash (Fuse Gele exploit for Nintendo Switch) 项目地址: https://gitcode.com/gh_mirrors/te/TegraRcmGUI TegraRcmGUI是一款专为Windo…...

剪映专业版教程:制作冒泡排序算法原理演示视频

前言 今天教大家用剪映制作冒泡排序算法的原理演示视频。冒泡排序的原理是&#xff1a;从左到右&#xff0c;依次比较相邻两个元素&#xff0c;如果左边的元素大于右边的元素&#xff0c;就交换位置。这样&#xff0c;一轮比较下来&#xff0c;最大的元素会被“冒泡”到最右边…...

Vivado 2022.2的.xsa文件,真能通吃Petalinux 2019.2到2022.2吗?我的混搭实测记录

Vivado与Petalinux版本混搭实战&#xff1a;打破常规的.xsa文件兼容性探索 在FPGA开发领域&#xff0c;Xilinx工具链的版本匹配一直被视为金科玉律。但当我们手头只有高版本Vivado&#xff0c;却需要兼容旧版Petalinux环境时&#xff0c;是否真的必须严格遵循官方版本对应表&a…...

Chrome-Charset:3步彻底解决网页乱码问题,告别天书般的浏览体验![特殊字符]

Chrome-Charset&#xff1a;3步彻底解决网页乱码问题&#xff0c;告别天书般的浏览体验&#xff01;&#x1f680; 【免费下载链接】Chrome-Charset An extension used to modify the page default encoding for Chromium 55 based browsers. 项目地址: https://gitcode.com/…...

如何快速配置Live Server Web Extension:提升开发效率的完整指南

如何快速配置Live Server Web Extension&#xff1a;提升开发效率的完整指南 【免费下载链接】live-server-web-extension It makes your existing server live. This is a browser extension that helps you to live reload feature for dynamic content (PHP, Node.js, ASP.N…...

Steam Deck Tools 终极指南:Windows 掌机的完美伴侣

Steam Deck Tools 终极指南&#xff1a;Windows 掌机的完美伴侣 【免费下载链接】steam-deck-tools (Windows) Steam Deck Tools - Fan, Overlay, Power Control and Steam Controller for Windows 项目地址: https://gitcode.com/gh_mirrors/st/steam-deck-tools 还在为…...

动手实验:在QEMU上模拟调试ATF安全启动全流程(含常见错误排查)

在QEMU虚拟环境中实战调试ATF安全启动全流程指南 1. 实验环境搭建与工具链配置 构建ATF调试环境需要精心准备工具链和依赖组件。我们推荐使用Ubuntu 20.04 LTS作为基础系统&#xff0c;这是目前对ARM虚拟化支持最完善的Linux发行版之一。以下是关键组件的版本要求&#xff1a; …...

Wayback Machine浏览器扩展:时光倒流神器,一键保存网页历史

Wayback Machine浏览器扩展&#xff1a;时光倒流神器&#xff0c;一键保存网页历史 【免费下载链接】wayback-machine-webextension A web browser extension for Chrome, Firefox, Edge, and Safari 14. 项目地址: https://gitcode.com/gh_mirrors/wa/wayback-machine-webex…...

专科英语A级和B级考试历年真题试卷及答案PDF电子版

高等学校英语应用能力考试&#xff08;PRETCO&#xff09;A 级、B 级历年真题试卷及答案 PDF 电子版&#xff0c;专为高职高专、大专在校生备考整理。内容涵盖2022年、2023年、2024年、2025年 6 月、12 月全套真题&#xff0c;含听力原文、答案解析、写作范文&#xff0c;题型覆…...