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

news2024/11/17 22:38:32

应美术要求,实现一个在编辑环境下,不运行,可以实例化预制体的脚本
在这里插入图片描述
效果如上图所示
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
在这里插入图片描述

即可(标签见上图)

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Springboot+vue的公寓报修管理系统(有报告)。Javaee项目,springboot vue前后端分离项目

演示视频&#xff1a; Springbootvue的公寓报修管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot vue前后端分离项目 项目介绍&#xff1a; 本文设计了一个基于Springbootvue的前后端分离的公寓报修管理系统&#xff0c;采用M&#xff08;model&…

SpringBoot接入企微机器人

1、企业微信创建机器人&#xff08;如何创建不懂的请自行百度&#xff0c;很简单的&#xff09;&#xff0c;成功后能获取到一个Webhook地址&#xff1a;https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key693a91f6-7xxx-4bc4-97a0-0ec2sifa5aaa 2、创建一个SpringBoot项…

Linux 内存池源码剖析

1 传统的分配与释放内存的函数缺点: void *malloc(size_t size); void *calloc(size_t nmemb,size_t size);void *realloc(void *ptr, size_t size);void free(void *ptr);缺点1: 高并发时较小内存块使用导致系统调用频繁,降低了系统的执行效率 缺点2: 频繁使用时增加了系统…

java导出excel通用工具(POI,类注解形式)

通过给类定义注解(设置名称&#xff0c;设置kv转换值)&#xff0c;然后利用设置的名称和传入的数据进行导出。 只需要在项目添加两个工具类就可以实现excel导出功能。 1、单sheet 步骤&#xff1a;1、根据业务需求定义导出的类&#xff0c;并设置表头名称。 …

计算机网络快速刷题

自用//奈奎斯特定理和香农定理计算题 参考博客&#xff1a;UDP协议是什么&#xff1f;作用是什么&#xff1f; 肝了&#xff0c;整理了8张图详解ARP原理 【网络协议详解】——FTP系统协议&#xff08;学习笔记&#xff09; 在OSI参考模型中&am…

论文自己改过后怎么降重 papergpt

大家好&#xff0c;今天来聊聊论文自己改过后怎么降重&#xff0c;希望能给大家提供一点参考。 以下是针对论文重复率高的情况&#xff0c;提供一些修改建议和技巧&#xff0c;可以借助此类工具&#xff1a; 论文自己改过后如何降重 在论文修改过程中&#xff0c;我们往往会对…

力扣785.判断二分图

存在一个 无向图 &#xff0c;图中有 n 个节点。其中每个节点都有一个介于 0 到 n - 1 之间的唯一编号。给你一个二维数组 graph &#xff0c;其中 graph[u] 是一个节点数组&#xff0c;由节点 u 的邻接节点组成。形式上&#xff0c;对于 graph[u] 中的每个 v &#xff0c;都存…

[蓝桥杯刷题]合并区间、最长不连续子序列、最长不重复数组长度

前言 ⭐Hello!这里是欧_aita的博客。 ⭐今日语录: 成功的关键在于对目标的持久追求。 ⭐个人主页&#xff1a;欧_aita ψ(._. )>⭐个人专栏&#xff1a; 数据结构与算法 数据库 文章目录 前言合并区间问题&#x1f4d5;现实应用大致思路代码实现代码讲解 最长不连续子序列&a…

Python封装ADB获取Android设备wifi地址的方法

一、代码实现 import subprocessimport re import subprocessfrom common.logger import loggerdef get_device_wifi_address(udid):ip_command fadb -s {udid} shell ip routeresult subprocess.check_output(ip_command, shellTrue, textTrue)# 提取 IP 地址ip_address r…

Python多态原理及实现

对于弱类型的语言来说&#xff0c;变量并没有声明类型&#xff0c;因此同一个变量完全可以在不同的时间引用不同的对象。当同一个变量在调用同一个方法时&#xff0c;完全可能呈现出多种行为&#xff08;具体呈现出哪种行为由该变量所引用的对象来决定&#xff09;&#xff0c;…

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

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

功能测试转向自动化测试 。10 年 心路历程——愿测试人不再迷茫

十年测试心路历程&#xff1a; 由于历史原因&#xff0c;大部分测试人员&#xff0c;最开始接触都是纯功能界面测试&#xff0c;随着工作年限&#xff0c;会接触到一些常用测试工具&#xff0c;比如抓包&#xff0c;数据库&#xff0c;linux 等。 我大学学的计算机专业&#…

Linux环境下HTTP请求的代码详解与实例

嘿&#xff0c;Linux狂热者们&#xff0c;是时候让我们在这个充满激情的平台上探索一下HTTP协议的奥秘了。我知道&#xff0c;对于这个我们每天都在使用&#xff0c;但却可能没深入了解过的HTTP&#xff0c;你们一定充满了好奇和期待。那么&#xff0c;让我们一起踏上这趟探索之…

【Docker】实战:nginx、redis

▒ 目录 ▒ &#x1f6eb; 导读开发环境 1️⃣ Nginx 拉取 Nginx 镜像nginx.conf启动 Nginx访问 Nginx 2️⃣ redis拉取 Redis 镜像启动 Redis 容器测试 Redis &#x1f4d6; 参考资料 &#x1f6eb; 导读 开发环境 版本号描述文章日期2023-12-15操作系统Win10 - 22H222621.2…

VR虚拟仿真技术应用到外事警察岗位技能培训的场景及优势

VR治安民警常态化工作实战教学演练是一种利用VR虚拟现实制作和web3d开发技术进行治安民警培训和实战演练的新型教学模式。相较于传统的培训方式&#xff0c;VR治安民警常态化工作实战教学演练具有以下优点&#xff1a; VR实战是一种完全虚拟的实战训练方式&#xff0c;他可以根…

Apache Flume(4):日志文件监控

1 案例说明 企业中应用程序部署后会将日志写入到文件中&#xff0c;可以使用Flume从各个日志文件将日志收集到日志中心以便于查找和分析。 2 使用Exec Soucre Exec Source Exec Source通过指定命令监控文件的变化&#xff0c;加粗属性为必须设置的。 属性名默认值说明chan…

如何用DETR(detection transformer)训练自己的数据集,并推理图片

前言 这里我分享一下官方写的DETR的预测代码&#xff0c;其实就是github上DETR官方写的一个Jupyter notebook&#xff0c;可能需要梯子才能访问&#xff0c;这里我贴出来。因为DETR比较难训练&#xff0c;我觉得可以用官方的预训练模型来看看效果。 如果要用自己训练的模型来…

MYSQl基础操作命令合集与详解

MySQL入门 先来个总结 SQL语言分类 DDL&#xff08;Data Definition Language&#xff09; - 数据定义语言: 用于定义和管理数据库结构&#xff0c;包括创建、修改和删除数据库对象。 示例&#xff1a;CREATE, ALTER, DROP等语句。 DML&#xff08;Data Manipulation Lan…

FC-13A(用于汽车应用的kHz范围晶体单元,低轮廓贴片)

FC-13A晶体非常适合用在汽车导航系统设计中的应用&#xff0c;是一种具有优异的频率性能和AEC-Q200标准认证的汽车工业级高精度晶体,FC-13A是一款尺寸为3.2 1.5 0.9mm&#xff0c;频率范围32.768KHz耐高温晶振&#xff0c;频率温度系数仅为-0.04ppm/℃&#xff0c;并且其老化…

Java基础面试题小结

基础面试题 Java语言简介 Java是1995年由sun公司推出的一门高级语言&#xff0c;该语言具备如下特点: 简单易学&#xff0c;相较于C语言和C&#xff0c;没有指针的概念&#xff0c;所以操作和使用是会相对容易一些。平台无关性&#xff0c;即Java程序可以通过Java虚拟机在不…