Unity inspector绘制按钮与Editor下生成与销毁物体的方法 反射 协程 Editor

应美术要求,实现一个在编辑环境下,不运行,可以实例化预制体的脚本
在这里插入图片描述
效果如上图所示
1.去实现一个简单的 行、列实例化物体脚本
2.在Inspector下提供按钮
3.将方法暴露出来(通过自定义标签实现

需求一
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FX_init : MonoBehaviour
{
    // Start is called before the first frame update
    public GameObject PreGameObject;
    public int numCol = 4;

    public float spaceCol = 2.0f;
    
    public int numRow = 4;

    public float spaceRow = 2.0f;

    private List<GameObject> cubeTemp;
    void Start()
    {
        SetInit();
    }
    public void SetInit()
    {
        for (int i = 0; i < numCol; i++)
        {
            for (int j = 0; j< numRow; j++)
            {
                float xPos = i * spaceRow;
                float yPos = j * spaceCol;
                GameObject newObject = Instantiate(PreGameObject, new Vector3(xPos, yPos, 0), Quaternion.identity);
                cubeTemp.Add(newObject);
            }
        }

    }
    public void Clear()
    {
        for (int i = 0; i < cubeTemp.Count; i++)
        {
            DestroyImmediate(cubeTemp[i]);
        }
    }
}

上述是,一个简单的for循环实例化脚本,用数组存储他们方便后续销毁

using UnityEngine;

[System.AttributeUsage(System.AttributeTargets.Method)]
public class InspectorButtonAttribute : PropertyAttribute
{
    public readonly string Name;

    public InspectorButtonAttribute()
    {
    }

    public InspectorButtonAttribute(string name)
    {
        Name = name;
    }
}

InspectorButtonAttribute继承自PropertyAttribute。在Unity中,PropertyAttribute用于在检视器中自定义显示属性。
Name字段,用于指定按钮在检视器中显示的名称。
构造函数:提供了两个构造函数,一个是无参数的,另一个带有一个字符串参数。通过这两个构造函数,可以选择性地为按钮指定名称。如果没有指定名称,将使用方法的名称作为按钮的显示名称。
这个属性的主要目的是为了在方法上提供标记,使这些方法能够在Unity检视器中以按钮的形式显示出来。在InspectorButton自定义编辑器中,通过检查方法上是否有InspectorButtonAttribute来确定哪些方法应该被显示为按钮,以及按钮的显示名称是什么。

Base class to derive custom property attributes from. Use this to create custom attributes for script variables.

A custom attributes can be hooked up with a custom PropertyDrawer class to control how a script variable with that attribute is shown in the Inspector.
PropertyAttribute

using System;
using System.Collections;
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(MonoBehaviour), true)]
[CanEditMultipleObjects]
public class InspectorButton : Editor
{
    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();

        var mono = target as MonoBehaviour;
        if (mono == null)
            return;

        var methods = mono.GetType()
            .GetMethods(
                BindingFlags.Public | BindingFlags.NonPublic |
                BindingFlags.Instance | BindingFlags.Static
            ).Where(method =>
                Attribute.IsDefined(method, typeof(InspectorButtonAttribute))
            ).ToArray();

        foreach (var method in methods)
        {
            var attr = method.GetCustomAttribute<InspectorButtonAttribute>();
            DrawButton(method, attr.Name);
        }
    }

    private void DrawButton(MethodInfo methodInfo, string methodName)
    {
        if (string.IsNullOrEmpty(methodName))
            methodName = methodInfo.Name;

        EditorGUILayout.BeginHorizontal();

        if (GUILayout.Button(
                methodName,
                GUILayout.ExpandWidth(true)
            ))
        {
            foreach (var targetObj in targets)
            {
                var mono = targetObj as MonoBehaviour;
                if (mono == null)
                    continue;

                var val = methodInfo.Invoke(mono, new object[] { });
                if (val is IEnumerator coroutine)
                    mono.StartCoroutine(coroutine);
                else if (val != null)
                    Debug.Log($"{methodName}调用结果: {val}");
            }
        }

        EditorGUILayout.EndHorizontal();
    }
}

1.重写了OnInspectorGUI方法,以在默认检视器下方添加自定义GUI元素(按钮)。
// 获取目标 MonoBehaviour 的类型
var methods = mono.GetType()
// 获取该类型的所有方法
.GetMethods(
// 指定搜索标志,以获取公共、非公共、实例和静态方法
BindingFlags.Public | BindingFlags.NonPublic |
BindingFlags.Instance | BindingFlags.Static
)
// 使用 LINQ 过滤出标记了 InspectorButtonAttribute 的方法
.Where(method =>
Attribute.IsDefined(method, typeof(InspectorButtonAttribute))
)
// 将结果转换为数组
.ToArray();

mono.GetType(): 获取 target(即 MonoBehaviour 对象)的类型信息。

.GetMethods(…): 获取该类型的所有方法。BindingFlags 参数指定了搜索标志,其中包括公共方法、非公共方法、实例方法和静态方法。
2.使用反射检索带有InspectorButtonAttribute的方法。假定此属性不在提供的代码中定义,但假定它是一个自定义属性,用于标记应显示为按钮的方法。

.Where(method => Attribute.IsDefined(method, typeof(InspectorButtonAttribute))): 使用 LINQ 过滤出那些标记了 InspectorButtonAttribute 的方法。Attribute.IsDefined 方法用于检查方法是否应用了指定的属性。

.ToArray(): 将过滤后的方法结果转换为数组,以便后续使用。

  1. 方法调用
    var val = methodInfo.Invoke(mono, new object[] { });
    if (val is IEnumerator coroutine)
    mono.StartCoroutine(coroutine);
    else if (val != null)
    Debug.Log($“{methodName}调用结果: {val}”);
    使用反射(methodInfo.Invoke)调用方法。如果方法返回IEnumerator,则假定它是协程,并使用StartCoroutine启动。非空返回值记录到Unity控制台。

遇到的报错
在这里插入图片描述

在Editor下直接调用GammeObject的destory方法有如下报错
Destroy may not be called from edit mode! Use DestroyImmediate instead.
Destroying an object in edit mode destroys it permanently.
UnityEngine.Object:Destroy (UnityEngine.Object)
大意是:不能从编辑模式调用销毁!请改用 DestroyImmediate。
在编辑模式下销毁对象会永久销毁它。
问题解决
所以改用DestroyImmediate
在这里插入图片描述

即可(标签见上图)

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

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

相关文章

单片机Freertos入门(二)任务的创建、删除

1、串口配置 首先将串口进行配置&#xff0c;后续经常会应用&#xff0c;具体步骤点击&#xff1a;串口配置。 2、任务 创建一个任务&#xff0c;就是开辟一个空间、每个任务中都会有while&#xff08;1&#xff09;死循环。 2.1相关函数 动态创建&#xff1a;xTaskCreate…

PostgreSQL常用命令

数据库版本 :9.6.6 注意 :PostgreSQL中的不同类型的权限有 SELECT,INSERT,UPDATE,DELETE,TRUNCATE,REFERENCES,TRIGGER,CREATE,CONNECT,TEMPORARY,EXECUTE 和 USAGE。 1. 登录PG数据库 以管理员身份 postgres 登陆,然后通过 #psql -U postgres #sudo -i -u postgres …

【强化学习-读书笔记】表格型问题的 Model-Free 方法

参考 Reinforcement Learning, Second Edition An Introduction By Richard S. Sutton and Andrew G. Barto无模型方法 在前面的文章中&#xff0c;我们介绍的是有模型方法&#xff08;Model-Based&#xff09;。在强化学习中&#xff0c;"Model"可以理解为算法…

AcWing 1250. 格子游戏(并查集)

题目链接 活动 - AcWing本课程系统讲解常用算法与数据结构的应用方式与技巧。https://www.acwing.com/problem/content/1252/ 题解 当两个点已经是在同一个连通块中&#xff0c;再连一条边&#xff0c;就围成一个封闭的圈。一般用x * n y的形式将&#xff08;x, y&#xff0…

数据持久化与临时存储的对决:localStorage 与 sessionStorage(下)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

泛型的相关内容

首先我们来了解一下什么是泛型&#xff0c;泛型的作用又是什么。 泛型的形式是 ArrayList<Object> objects new ArrayList<>(); 这里的<Object>这个就是泛型&#xff0c;添加泛型的作用又是什么呢&#xff0c;它可以限制添加对象的类型&#xff0c;比如A…

爬虫akamai案例:DHL国际物流

声明&#xff1a; 该文章为学习使用&#xff0c;严禁用于商业用途和非法用途&#xff0c;违者后果自负&#xff0c;由此产生的一切后果均与作者无关 一、Akamai简介 Akamai是一家提供内容传递网络&#xff08;CDN&#xff09;和云服务的公司。CDN通过将内容分发到全球各地的服…

系统运行占用过高

1、CPU过高的问题排查 示例代码&#xff1a; public class Test { static class MyThread extends Thread { public void run() { // 死循环&#xff0c;消耗CPU int i 0; while (true) { i; } } } public static void main(String args[]) throws InterruptedException { ne…

跟随鼠标动态显示线上点的值(基于Qt的开源绘图控件QCustomPlot进行二次开发)

本文为转载 原文链接&#xff1a; 采用Qt快速绘制多条曲线&#xff08;折线&#xff09;&#xff0c;跟随鼠标动态显示线上点的值&#xff08;基于Qt的开源绘图控件QCustomPlot进行二次开发&#xff09; 内容如下 QCustomPlot是一个开源的基于Qt的第三方绘图库&#xff0c;能…

docker镜像与容器的迁移

docker容器迁移有两组命令&#xff0c;分别是 save & load &#xff1a;操作的是images&#xff0c; 所以要先把容器commit成镜像export & import&#xff1a;直接操作容器 我们先主要看看他们的区别&#xff1a; 一 把容器打包为镜像再迁移到其他服务器 如把mysq…

大模型学习之GPT系列

GPT系列 预备知识GPT-1无监督预训练有监督的微调训练 GPT-2数据集&#xff1a;输入表示模型实验 GPT-3模型数据集实验局限性 InstructGPTGPT-4GPT-4 新特性基础能力 参考文献 大模型 GPT演进路线图 预备知识 Transformer 结构图 GPT-1 首先使用未标注的数据训练一个预训练…

mac电脑html文件 局域网访问

windows html文件 局域网访问 参考 https://blog.csdn.net/qq_38935512/article/details/103271291mac电脑html文件 局域网访问 开发工具vscode 安装vscode插件 Live Server 完成后打开项目的html 右键使用Live Server打开页面 效果如下&#xff0c;使用本地ip替换http://12…

LVS负载均衡器(nat模式)+nginx(七层反向代理)+tomcat(多实例),实现负载均衡和动静分离

目录 前言 一、配置nfs共享存储 二、配置2个nginx节点服务的网页页面 节点1:192.168.20.10 步骤一&#xff1a;修改网关指向调度器的内网ip地址 步骤二&#xff1a;将nfs共享的目录进行挂载&#xff0c;并修改nginx的配置文件中location的root指向挂载点 步骤三&#xff…

lua安装

lua安装 1.Lua介绍 特点&#xff1a;轻量、小巧。C语言开发。开源。 设计的目的&#xff1a;嵌入到应用程序当中&#xff0c;提供灵活的扩展和定制化的功能。 luanginx&#xff0c;luaredis。 2.windows安装lua windows上安装lua&#xff1a; 检查机器上是否有lua C:\U…

Shopee ERP:提升电商管理效率的终极解决方案

Shopee ERP&#xff08;Enterprise Resource Planning&#xff0c;企业资源规划&#xff09;是一款专为Shopee卖家设计的集成化电商管理软件。通过使用Shopee ERP系统&#xff0c;卖家可以更高效地管理他们的在线商店&#xff0c;实现库存管理、订单处理、物流跟踪、财务管理、…

[Knowledge Distillation]论文分析:Distilling the Knowledge in a Neural Network

文章目录 一、完整代码二、论文解读2.1 介绍2.2 Distillation2.3 结果 三、整体总结 论文&#xff1a;Distilling the Knowledge in a Neural Network 作者&#xff1a;Geoffrey Hinton, Oriol Vinyals, Jeff Dean 时间&#xff1a;2015 一、完整代码 这里我们使用python代码进…

vue 使用 Echarts做地图及飞线效果

前言&#xff1a; 效果图 一. 项目中安装以及引入Echarts 1.1 npm 命令安装echarts库 npm install echarts --save 1.2 yarn命令安装echarts库 yarn add echarts 1.3 引用 a. 在使用页面上引入 在Vue组件的script标签中引入echarts库 使用 echarts import * as echarts f…

Kafka-Kafka基本原理与集群快速搭建(实践)

Kafka单机搭建 下载Kafka Apache Download Mirrors 解压 tar -zxvf kafka_2.12-3.4.0.tgz -C /usr/local/src/software/kafkakafka内部bin目录下有个内置的zookeeper(用于单机) 启动zookeeper&#xff08;在后台启动&#xff09; nohup bin/zookeeper-server-start.sh conf…

MySQL运维5-Mycat配置

一、schema.xml 1.1 简介 schema.xml作为Mycat中最重要的配置文件之一&#xff0c;涵盖了Mycat的逻辑库、逻辑表、分片规则、分片节点即数据源的配置。主要包括一下三组标签 schema标签 datanode标签 datahost标签 1.2 schema标签 用于定于Mycat实例中的逻辑库&#xff0c;一个…

如何用 Cargo 管理 Rust 工程系列 丙

以下内容为本人的学习笔记&#xff0c;如需要转载&#xff0c;请声明原文链接 微信公众号「ENG八戒」https://mp.weixin.qq.com/s/viSsCaFR2x9hZOvo1PoRqA 添加依赖项 前面已经提到过在 cargo 配置文件 Cargo.toml 中如何手动添加工程依赖项&#xff0c;cargo 同样提供了 add …