Unity3D插件开发教程(二):制作批处理工具

news2024/11/26 1:55:03

Unity3D插件开发教程(二):制作批处理工具

文章来源:Unity3D插件开发教程(二):制作批处理工具 - 知乎 (zhihu.com)

声明:
  • 题图来自于Gratisography | Free High Resolution Pictures
  • 欢迎分享本文
  • 本文未经允许不能以任何形式转载。

俗语说:工欲善其事,必先利其器。

一个好的工具能让你的工作进度加快不少。

在制作关卡时,很多时候会遇到同一个物体可能需要复制多份,然后分布在不同地方。如果 一个个复制太浪费时间了,而美术和策划又不会使用代码批量复制。这时候,就需要做一个批量工具来加快制作的效率了。

首先来看一下我们今天要做的批量工具面板,并且可以根据输入的变量,批量的变更每个的位移,旋转和缩放:

知识要点:

  • EditorWindow
  • GUI/GUILayout/EditorGUI/EditorGUILayout
  • Selection
  • Undo

使用版本:

  • Unity3D 5.3.3

目标:

  • 学习创建EditorWindow面板,然后使用GUI等工具绘制面板,最后批量复制对象。

整个插件的结构:

和上一篇教程一样,在Editor目录下创建我们的批处理面板脚本————BatchingLiteWindow.cs,然后继承EditorWindow

EditorWindow是所有编辑器面板的基类,绘制面板必须要继承它。

然后我们使用MenuItem和静态函数添加启动面板的菜单。

MenuItem的使用方法请看 上一篇教程的最后部分。
public class BatchingLiteWindow : EditorWindow
{
    [MenuItem("Tools/BatchingLite")]
    public static void ShowWindow()
    {
        //GetWindow函数的意思是创建一个面板
        //类型为BatchingLiteWindow
        //第一个参数是面板的标题
        EditorWindow.GetWindow<BatchingLiteWindow>("Batcking");
    }
}

然后我们定义几个变量,用于后面使用。

/// <summary>
/// 位移增量
/// </summary>
private Vector3 _position;

/// <summary>
/// 旋转增量
/// </summary>
private Vector3 _rotation;

/// <summary>
/// 缩放增量
/// </summary>
private Vector3 _scale;

/// <summary>
/// 复制的数量
/// </summary>
private int _number;

好了,接下来,就是本文的重点之一,绘制面板了。 首先,我们定义一个函数叫OnGUI,返回值为void。

说到OnGUI,用过老版本Unity引擎的朋友应该很清楚了。这是一套Unity最早的UI引擎。这套UI系统有别于现在流行的 UGUINGUI,是一套 imGUI(Immediate Mode GUI)。如果需要深入展开imGUI的原理来讲,那么可能需要好几个篇章,所以在此只讲一下怎么使用。 如果有兴趣的朋友可以上网搜索资料,或者到看这个回答  如何用 C++ 从零编写 GUI? - 回答作者: 文刀秋二
首先,绘制面板,一定要使用这套GUI,并且需要在特定函数内使用,例如 OnGUIOnSceneGUIOnInspectorGUIOnHeaderGUIOnPreviewGUI等。 其次,imGUI其中一个特性是不保存状态的,例如 UGUINGUI的按钮类都会保存按钮当前是按下状态还是松开状态,可 imGUI的按钮是不保存这个的。
imGUI有四个绘制类。分别是 GUIGUILayoutEditorGUIEditorGUILayout,他们有相同的地方和不同的地方。
  • GUI:多用与应用/游戏内绘制UI。(编辑器绘制也可使用)
  • GUILayout:GUI的功能上增加了布局的功能。
  • EditorGUI:用于编辑器内绘制UI。(仅限于编辑器内使用)
  • EditorGUILayout:EditorGUI的功能上增加了布局的功能。

好了,接下就开始写绘制面板的逻辑了。

void OnGUI()
{
    //使用Vector3Field方法绘制Vector3的输入框,第一个为输入框的标签(显示的名字),第二个参数需要传入需要显示的Vector3值。
    //返回值为一个Vector3,当没有修改的时候,这个值为原来的值,当有修改的时候,这个返回值就是修改后的值。
    //例如,把返回值赋予给_position,这样,输入框有修改的时候,_position能够拿到最新的值。
    _position = EditorGUILayout.Vector3Field("Position", _position);

    _rotation = EditorGUILayout.Vector3Field("Rotation", _rotation);

    _scale = EditorGUILayout.Vector3Field("Scale", _scale);

    //Space的作用是空一行
    EditorGUILayout.Space();

    //然后使用IntField方法绘制一个int类型的输入框,使用与Vector3相似
    //由于复制的数量不能为负数,所以我们要限制一下修改后的数值
    _number = Mathf.Max(EditorGUILayout.IntField("Number", _number), 0);

    EditorGUILayout.Space();

    //BeginHorizontal方法和EndHorizontal是成对存在的,然后他们的作用是水平布局,在两个函数内绘制的UI会限制在一个水平位置。
    //相似的方法还有BeginVertical和EndVertical,是垂直布局。
    EditorGUILayout.BeginHorizontal();

    //绘制一个Generate Button,这里使用GUILayout而不使用EditorGUILayout是因为EditorGUILayout没有Button(不知道原因)。
    //Button方法第一个参数是button显示的label。
    //返回值为Button是否为点击,
    if (GUILayout.Button("Generate"))
    {
        Generate();
    }

    //这里缓存Cancel按钮的状态,在EndHorizontal之后再调用Cancel方法。
    bool isCancel = GUILayout.Button("Cancel");

    EditorGUILayout.EndHorizontal();

    if (isCancel)
    {
        Cancel();
    }
}

绘制完面板,然后就开始写复制部分的逻辑

/// <summary>
/// 生成复制对象
/// </summary>
private void Generate()
{
    //上一篇有介绍过Selection.activeGameObject是选中的对象,然后Selection.gameObjects是多选时,所有选中的对象。
    //因为有可能是多个对象同时复制,所以使用选中对象组
    GameObject[] selectGameObjects = Selection.gameObjects;

    int len = selectGameObjects.Length;

    for (int i = 0; i < len; i++)
    {
        GameObject selectGameObject = selectGameObjects[i];

        for (int j = 0; j < _number; j++)
        {
            //根据选中对象,实例化对象,然后根据索引和增量,设置移动、旋转、缩放
            GameObject gameObject = GameObject.Instantiate<GameObject>(selectGameObject);

            gameObject.transform.SetParent(selectGameObject.transform.parent);

            gameObject.transform.localPosition = selectGameObject.transform.localPosition + _position * j;

            gameObject.transform.localRotation = selectGameObject.transform.localRotation * Quaternion.Euler(_rotation * j);

            gameObject.transform.localScale = selectGameObject.transform.localScale + _scale * j;

            gameObject.name = selectGameObject.name;

            //Undo是Unity3d用于设置步骤,执行/撤销等
            //RegisterCreatedObjectUndo是注册一个新创建的对象的步骤,然后名字为“Batching Create GameObject”,用于
            Undo.RegisterCreatedObjectUndo(gameObject, "Batching Create GameObject");
        }
    }
}

最后是Cancel方法

/// <summary>
/// 取消操作
/// 同ctrl + z
/// </summary>
private void Cancel()
{
    //PerformUndo作用跟ctrl + z一样
    Undo.PerformUndo();
}
解释一下,为啥OnGUI时, Cancel为什么要 EditorGUILayout.EndHorizontal之后才调用,这是因为 Cancel会导致之前 EditorGUILayout.StartHorizontal的标记没了,然后执行 EditorGUILayout.EndHorizontal会报错。

最后可以试一下面板的效果:

增加一个彩蛋,做了一个100*100*100的正方体矩阵然后直接占满8g内存.......

源码:L-Lawliet/UnityEditorTutorial

==========================分割线==========================

如果大家有什么意见和建议,或者是有什么疑问,或者是有想看的知识点内容,都欢迎到评论区发上你们的评论。

最后我希望有更多人参与到插件开发的队伍里。也欢迎大家投稿。

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

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

相关文章

区块链的运行原理与演示

目录 前言 具体演示 1、在浏览器中输入区块链演示网址&#xff1a; 2、创建新区块 3、篡改区块信息使其无效 4、新增P2P 网络节点。 5、节点连接。 6、区块信息同步 总结 前言 区块链系统是由一系列分布在全球各地的分布式节点组成的。这些节点互不隶属&#xff0c;通过…

目标检测基础初步学习

目标检测&#xff08;Object Detection&#xff09; 目标检测任务说明 在动手学习深度学习中对目标检测任务有如下的描述。 图像分类任务中&#xff0c;我们假设图像中只有一个主要物体对象&#xff0c;我们只关注如何识别其类别。 然而&#xff0c;很多时候图像里有多个我们…

中心入侵渗透

问题1. windows登录的明文密码&#xff0c;存储过程是怎么样的&#xff1f;密文存在哪个文件下&#xff1f;该文件是否可以打开&#xff0c;并且查看到密文&#xff1f; 回答&#xff1a; Windows登录的明文密码的存储过程是&#xff1a; 当用户尝试登录Windows时&#xff0…

MM模块六(收货)

接到供应商收到的货以后&#xff0c;进行一个收货的动作 收货&#xff1a;MIGO 1.消耗物料的采购订单 数量是供应商的数量 消耗物料的采购订单&#xff0c;收进来的货物直接进入消耗&#xff0c;不会增加库存&#xff0c;所以这里没有库存地点进行选择 点击过账 收货后在采购…

ubuntu 配置用户登录失败尝试次数限制

前言&#xff1a; 通过修改pam配置来达到限制密码尝试次数&#xff01; 1&#xff1a;修改 /etc/pam.d/login 配置&#xff08;这里只是终端登录配置&#xff0c;如果还需要配置SSH远程登录限制&#xff0c;只配置下面的 /etc/pam.d/pam.d/common-auth 即可&#xff09; vim…

go-zero 实战(1)

环境准备 go 版本 go version go1.22.2 linux/amd64 goctl 安装 goctl&#xff08;官方建议读 go control&#xff09;是 go-zero微服务框架下的代码生成工具。使用 goctl 可以显著提升开发效率&#xff0c;让开发人员将时间重点放在业务开发上&#xff0c;其功能有&#xff1a…

【东山派Vision K510开发板试用笔记】WiFi配网问题

目录 概述 WiFi配网的修改 悬而未决的问题 概述 最近试用了百问网提供的东山派Vision开发板&#xff0c;DongshanPI-Vision开发板是百问网针对AI应用开发设计出来的一个RSIC-V架构的AI开发板&#xff0c;主要用于学习使用嘉楠的K510芯片进行Linux项目开发和嵌入式AI应用开发…

手撕C语言题典——返回倒数第 k 个节点(面试题)

前言 依旧力扣&#xff0c;这道题之前有做过类似的题&#xff0c;今天给一个新的思路去做&#xff0c;应对面试时候遇到的奇奇怪怪的问题 面试题 02.02. 返回倒数第 k 个节点 - 力扣&#xff08;LeetCode&#xff09;https://leetcode.cn/problems/kth-node-from-end-of-list-…

英特尔LLM技术挑战记录

英特尔技术介绍&#xff1a; Flash Attention Flash Attention 是一种高效的注意力机制实现&#xff0c;旨在优化大规模 Transformer 模型中的自注意力计算。在深度学习和自然语言处理领域&#xff0c;自注意力是 Transformer 架构的核心组件&#xff0c;用于模型中不同输入元…

PMP报考条件怎么查询?如何判定自己是否符合条件?

PMP报考条件在PMI官网上就可以查询&#xff0c;PMP报考条件只需要符合项目管理培训经历和项目管理经验两个方面的要求即可&#xff0c;大家可以对照下方的规定判断自己是否符合PMP报名条件 PMP报考条件 以下是PMI&#xff08;中国&#xff09;官网对于PMP报名条件的规定&…

3D点云焊缝提取 平面交线 投影

文章目录 1. 效果2. 思路3. 源码 1. 效果 2. 思路 计算点云法向量&#xff1b;计算点云位姿Pose;翻转Pose中的Z轴方向&#xff0c;使其一致&#xff1b;通过Pose的Z轴对点云进行方向过滤&#xff1b;对点云聚类&#xff1b;根据目标点云的高度提取目标点云&#xff1b;提取两块…

Unity Dotween 定位点的制作

目录 前言 一、动画预览 二、动画拆分 三、素材准备 四、曲线 OutCirc详解 五、速度分类详解 六、代码 七、组件和设置 八、作者的话 前言 我答应我的粉丝接下来更新Dotween系列&#xff0c;但是我一直没想好&#xff0c;从哪里开始讲。 Dotween的安装我就跳过了&…

Java基础之 API 字符串

文章目录 API字符串String概述创建对象 java的内存模型java的常用方法(比较)练习 API 概念: APl(Application ProgrammingInterface): 应用程序编程接口 简单理解: API就是别人已经写好的东西&#xff0c;我们不需要自己编写&#xff0c;直接使用即可。 Java API: 指的就是J…

三层交换机基本配置,动态路由链接

<Huawei>system-view //进入系统视图[Huawei]undo info-center enable //关日志[Huawei]vlan batch 2 3 //创建vlan2与3[Huawei]display vlan //检查[Huawei]interface GigabitEthernet 0/0/2 //进2口[Huawei-GigabitEthernet0/0/2]port link-type access //配置…

【STM32嵌入式系统设计与开发---传感器拓展】——1_2_蓝牙主从模块_AT配置(HC-05)

一、主机蓝牙设置 # 1、重置模块 ATORGL # 2、设置名字&#xff0c;自己随便设置 ATNAMEMaster # 3、设置连接密码&#xff0c;要和从机一样&#xff0c;密码好像可以不加双引号 ATPSWD"1234" # 4、设置为主机 ROLE 1 为主机 ROLE 0为从机 ATROLE1 # 5、设置波特…

04 FreeRTOS 队列(queue)

1、队列的特性 队列可以理解为一个传送带&#xff0c;一个流水线。 队列可以包含若干个数据&#xff1a;队列中有若干项&#xff0c;这被称为"长度"(length) 每个数据大小固定 创建队列时就要指定长度、数据大小 数据的操作采用先进先出的方法(FIFO&#xff0c;First…

Python OCR 文字检测使用模型:读光-文字检测-DBNet行检测模型-中英-通用领域

介绍 什么是OCR&#xff1f; OCR是“Optical Character Recognition”的缩写&#xff0c;中文意为“光学字符识别”。它是一种技术&#xff0c;可以识别和转换打印在纸张或图像上的文字和字符为机器可处理的格式&#xff0c;如计算机文本文件。通过使用OCR技术&#xff0c;可…

【Python安全攻防】【网络安全】一、常见被动信息搜集手段

一、IP查询 原理&#xff1a;通过目标URL查询目标的IP地址。 所需库&#xff1a;socket Python代码示例&#xff1a; import socketip socket.gethostbyname(www.163.com) print(ip)上述代码中&#xff0c;使用gethostbyname函数。该函数位于Python内置的socket库中&#xf…

xss-labs之level9、level10

一、level9 1、测试分析 尝试了之前的payload&#xff0c;发现都不行&#xff0c;看源码发现多了个strpos函数&#xff0c; strpos() 是一个在 PHP 中用于查找子串首次出现位置的函数。它接受两个参数&#xff1a;要搜索的字符串&#xff08;主字符串&#xff09;和要查找的子…

5.28OpenMV入门

10分钟快速上手 OpenMV中文入门教程 使用的元件 先安装好&#xff0c;上述链接上手 IDE显示颜色阈值&#xff0c;同时也配有示例文件&#xff0c;如下图打开&#xff0c;helloworld 你好&#xff0c;世界&#xff01; OpenMV中文入门教程&#xff0c;在官方也有每一个的详细…