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

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.mzph.cn/pingmian/18101.shtml

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

相关文章

QA测试开发工程师面试题满分问答25: JVM瓶颈分析,举例说明

回答思路 JVM 性能瓶颈概述: JVM (Java Virtual Machine)是 Java 程序运行的基础环境,其性能直接影响到应用程序的整体性能。在实际项目中,我们经常会遇到 JVM 性能瓶颈,导致应用程序出现响应缓慢、CPU 利用率高、内存溢出等问题。因此,分析和诊断 JVM 瓶颈是非常重要的工作,有…

SpringValidation

一、概述&#xff1a; ​ JSR 303中提出了Bean Validation&#xff0c;表示JavaBean的校验&#xff0c;Hibernate Validation是其具体实现&#xff0c;并对其进行了一些扩展&#xff0c;添加了一些实用的自定义校验注解。 ​ Spring中集成了这些内容&#xff0c;你可以在Spri…

小程序使用vant组件库

一:下载组件库 在小程序内npm下载的包 vant组件库官网:快速上手 - Vant Weapp (youzan.github.io) 1)首先有有package.json文件,没有的话则先初始化 即使通过package.json去下载包,也需要有,可以观察下载的包. 2)下载包 3)构建npm包 下载包之后存储在node_modules内,但是我们…

初学者必读:Midjourney AI创作工具的简易使用手册!

在数字化时代&#xff0c;AI的应用不断推动着各个领域的发展。在这些领域中&#xff0c;AI在艺术和设计方面的应用引起了广泛的关注。AI绘画软件作为今年的热门&#xff0c;Midjourney 通过其独特的原理和方便的使用方法&#xff0c;为创作者提供了一个全新的创作逼真绘画的平台…

大模型日报|今日必读的 5 篇大模型论文

大家好&#xff0c;今日必读的大模型论文来啦&#xff01; 1.Meta 领衔&#xff1a;一文读懂视觉语言建模&#xff08;VLM&#xff09; 人们正在尝试将大型语言模型&#xff08;LLMs&#xff09;扩展到视觉领域。从可以引导我们穿越陌生环境的视觉助手&#xff0c;到仅使用高…

富港银行 优惠链接 邀请码 兑换码 优惠码 分享

首次记得一定要点击链接注册&#xff0c;注册开户费50美金 限时&#xff01;优惠开通国际银行账户&#xff01; cbi帐户管理费&#xff1a;10美元/月&#xff0c;余额>500美元&#xff0c;1美元/月/&#xff0c;余额>2000美元&#xff0c;0美元/月。 一定要显示50的时候…

一分钟学习数据安全——数字身份的三种模式

微软首席身份架构师金卡梅隆曾说&#xff1a;互联网的构建缺少一个身份层。互联网的构建方式让你无法得知所连接的人和物是什么。这限制了我们对互联网的使用&#xff0c;并让我们面临越来越多的危险。如果我们坐视不管&#xff0c;将面临迅速激增的盗窃和欺诈事件&#xff0c;…

短视频内容创意方法有哪些?成都科成博通文化传媒公司

短视频内容创意方法有哪些&#xff1f; 随着移动互联网的迅猛发展&#xff0c;短视频平台已成为人们日常生活中不可或缺的一部分。短视频以其短平快的特点&#xff0c;迅速吸引了大量用户。然而&#xff0c;面对海量的短视频内容&#xff0c;如何让自己的作品脱颖而出&#xf…

web自动化-下拉框操作/键鼠操作/文件上传

在我们做UI自动化测试的时候&#xff0c;会有一些元素需要特殊操作&#xff0c;比如下拉框操作/键鼠操作/文件上传。 下拉框操作 在我们很多页面里有下拉框的选择&#xff0c;这种元素怎么定位呢&#xff1f;下拉框分为两种类型&#xff1a;我们分别针对这两种元素进行定位和…

Nocobase快速上手 -第一个collection

本文记录Nocobase中如何创建collection&#xff0c;以及如何将collection展示到页面中&#xff0c;并且配置CRUD相应的操作. Collection 在NocoBase中&#xff0c;collection&#xff08;集合&#xff09;是用来组织和存储各种数据的容器&#xff0c;如订单、产品、用户、评论…

汽车电子零部件(14):TMS热管理系统

前言: TMS(thermal management system)热管理系统,这是新能源汽车诞生后随之而产生的一种新汽车零部件,一旦热管理失控会触发自燃,这种现象也是对EV来说是件头疼的事。汽车的热管理系统(TMS)是一个关键部件,有助于调节汽车电池组、车厢和其他车辆系统的温度。TMS的主要…

M功能-分布式锁-支付平台(五)

target&#xff1a;离开柬埔寨倒计时-218day 珍藏的图片又拿出来了 前言 M系统中的撮合引擎是最最核心的功能&#xff0c;第一版的撮合引擎不是我写的&#xff0c;也没有做交易对的动态分配这样的功能&#xff0c;都是基于抢锁方式来决定谁拥有该交易对的撮合权限&#xff0c;所…

MySQL--复合查询

之前学过了基本的查询&#xff0c;虽然已经够80%的使用场景了&#xff0c;但是依旧需要了解剩下的20%。 一、多表笛卡尔积&#xff08;多表查询&#xff09; 以前我们使用基本查询的时候&#xff0c;from后面就跟一张表名&#xff0c;在多表查询这里&#xff0c;from后面可以跟…

13 VUE学习:组件v-model

基本用法 v-model 可以在组件上使用以实现双向绑定。 从 Vue 3.4 开始&#xff0c;推荐的实现方式是使用 [defineModel()]宏&#xff1a; <!-- Child.vue --> <script setup> const model defineModel()function update() {model.value } </script><te…

GitLab的安装及基础操作

1. 项目目标 &#xff08;1&#xff09;熟练使用rpm包安装gitlab &#xff08;2&#xff09;熟练配置gitlab &#xff08;3&#xff09;熟练创建gitlab群组、成员、项目 &#xff08;4&#xff09;熟练使用gitlab推送和拉取代码 2. 项目准备 2.1. 规划节点 主机名 主机I…

Gb 2024-05-22开源项目日报Top10

根据Github Trendings的统计,今日(2024-05-22统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目3非开发语言项目2Jupyter Notebook项目2Rust项目2JavaScript项目1Lua项目1编程面试大学:成为软件工程师的全面学习计划 创建周期:2…

查询DQL

016条件查询之等量关系 条件查询语法格式 select ... from... where过滤条件;等于 select empno, ename from emp where sal3000;select job, sal from emp where enameFORD;select grade, losal, hisal from salgrade where grade 1;不等于 <> 或 ! selectempno,en…

德比软件携手亚马逊云科技,用生成式AI赋能旅游行业降本增效

旅游行业是最早被数字化技术赋能的行业之一。比如&#xff0c;消费者早已习惯在携程、艺龙、Booking等OTA平台根据实时酒店信息预订酒店。 这种丝滑的消费者体验背后&#xff0c;离不开领先的管理软件支撑。实际上大型酒店集团与OTA平台之间的系统对接非常复杂&#xff0c;酒店…

Go GORM介绍

GORM 是一个功能强大的 Go 语言 ORM&#xff08;对象关系映射&#xff09;库&#xff0c;它提供了一种方便的方式来与 SQL 数据库进行交互&#xff0c;而不需要编写大量的 SQL 代码。 GORM的关键特性 全功能的ORM&#xff1a;支持几乎所有的ORM功能&#xff0c;包括模型定义、基…