首页 > 其他分享 >Unity用户手册-EditorWindow

Unity用户手册-EditorWindow

时间:2022-11-29 22:02:45浏览次数:63  
标签:窗口 void 扩展 EditorWindow Unity EditorGUILayout using 用户手册 public


Unity Editor扩展概览

unity editor是一个通用的编辑器,提供了unity内部对象的创建,预览,编辑的功能及可视化界面。但对于特定类型的游戏开发可能还不能完全满足需求,还要根据程序,策划和美术的需求来进行扩展。常用的一些扩展包括打包界面,特定游戏对象的编辑界面,技能编辑器界面,自定义的场景编辑界面,美术资源导入批量设置等等。unity提供了丰富的接口来帮助开发者定制需求的功能。

用于扩展editor的类需要放到名字为“Editor"的文件夹中,这个文件夹可以直接放到”Assets“文件夹下,也可以是项目目录任何文件夹下的子文件夹,比如”Assets/BigWorld/Editor"。

几种类型的扩展

unity提供了由简单到复制的多种编辑器扩展功能,下面给大家进行介绍常用的4种。

扩展工具栏菜单

​ 使用​​MenuItem​​特性扩展工具栏菜单。此扩展方法可以单独使用执行某些功能,也可以和其他窗口扩展功能一起使用,打开其他窗口。

using UnityEngine;
using System.Collections;
using UnityEditor;

public class ArtResChecker
{

[MenuItem("ArtResChecker/CheckArtRes")]
static public void ATestCheckArtResFunction()
{
CheckTextures();
CheckMeshes();
...
}
}

代码1-1

代码1-1是一个简单的示例。使用"MenuItem"需要引入"UnityEditor"命名空间。这样会在菜单栏中出现"ArtResChecker"菜单,点击下拉菜单中的"CheckArtRes"项,会执行”ATestCheckArtResFunction"函数。

也可以扩展在已有的菜单中进行扩展,如代码1-2所示在“GameObject"菜单中增加了一项"AddChild"。

using UnityEngine;
using System.Collections;
using UnityEditor;

public class ArtResChecker
{
[MenuItem("GameObject/AddChild")]
static void ATestAddChildFunction()
{
Transform[] transforms = Selection.GetTransforms(SelectionMode.Unfiltered);
foreach(var tf in transforms)
{
GameObject newGo = new GameObject("_Child");
newGo.transform.parent = tf;
}
}
}

代码1-2

这个扩展脚本从菜单的“GameObject->Add Child”启动,功能是给Hierarchy窗口中选中的对GameObject添加一个名字为“_Child”的子GameObject,这样可以免去从Hierarchy窗口的根节点拖拽新创建的GameObject到当前选中节点的麻烦,因为在Unity3D编辑器中,创建一个EmptyObject会在Hierarchy窗口的根节点出现,无论当前选中的节点对象是哪个。

使用​​ScriptableWizard​​类进行扩展

​ unity提供的一个编辑器向导窗口扩展模板,继承这个类并重写里面的几个消息响应函数就可以快速创建一个编辑器窗口类。通过​​ScriptableWizard​​.DisplayWizard函数可以快速创建这个向导窗口。

​ 这个向导窗口只支持小于或等于两个按钮的定制(即提供的消息响应函数只有两个按钮的)。显示的按钮名字通过​​ScriptableWizard.DisplayWizard​​函数传入。下面介绍API中的消息响应函数:

  • ​OnWizardCreate​​ 两个按钮事件中的一个,当传入ScriptableWizard.DisplayWizard函数中"createButtonName"参数对应的按钮被点击时调用。
  • ​OnWizardOtherButton​​ 两个按钮事件中的一个,当传入ScriptableWizard.DisplayWizard函数中"otherButtonName"参数对应的按钮被点击时调用。
  • ​OnWizardUpdate​​ 当向导窗口打开时或者用户改变窗口内容时都会被调用。一般会在这里显示帮助文字和进行内容有效性验证。也可以动态改变按钮状态。

还有一个可能被复写的函数是​​DrawWizardGUI​​当向导窗口需要更新用户界面时会被调用来绘制内容。

下面看一个使用ScriptableWizard类进行扩展的例子:

// 当点击"Info"按钮时显示两个对象的距离,当点击"Finish!"按钮时关闭窗口
using UnityEngine;
using UnityEditor;

public class ScriptableWizardOnWizardOtherButton : ScriptableWizard
{
public Transform firstObject = null;
public Transform secondObject = null;

[MenuItem("Example/Show OnWizardOtherButton Usage")]
static void CreateWindow()
{
ScriptableWizard.DisplayWizard("Click info to know the distance between the objects",
typeof(ScriptableWizardOnWizardOtherButton), "Finish!", "Info");
}

void OnWizardUpdate()
{
if (firstObject == null || secondObject == null)
{
isValid = false;
errorString = "Select the objects you want to measure";
}
else
{
isValid = true;
errorString = "";
}
}

// Called when you press the "Info" button.
void OnWizardOtherButton()
{
float distanceObjs = Vector3.Distance(firstObject.position, secondObject.position);
EditorUtility.DisplayDialog(
"The distance between the objects is: " + distanceObjs + " Units",
"",
"Ok");
}

// Called when you press the "Finish!" button.
void OnWizardCreate()
{
}
}

代码1-3

运行时窗口如图1-1所示:

图1-1

使用​​Editor Windows​​类进行扩展

​ 完全自定义窗口,根据需求定义窗口内容和布局。使用时继承​​EditorWindow​​类,重写“OnGUI”函数。例子如代码1-4

using UnityEngine;
using UnityEditor;

public class MyWindow : EditorWindow
{
string myString = "Hello World";
bool groupEnabled;
bool myBool = true;
float myFloat = 1.23f;

// Add menu named "My Window" to the Window menu
[MenuItem("Window/My Window")]
static void Init()
{
// Get existing open window or if none, make a new one:
MyWindow window = (MyWindow)EditorWindow.GetWindow(typeof(MyWindow));
window.Show();
}

void OnGUI()
{
GUILayout.Label("Base Settings", EditorStyles.boldLabel);
myString = EditorGUILayout.TextField("Text Field", myString);

groupEnabled = EditorGUILayout.BeginToggleGroup("Optional Settings", groupEnabled);
myBool = EditorGUILayout.Toggle("Toggle", myBool);
myFloat = EditorGUILayout.Slider("Slider", myFloat, -3, 3);
EditorGUILayout.EndToggleGroup();
}
}

代码1-4

窗口打开是如图1-2所示:

图1-2

扩展自定义组件的Inspector窗口

​ 自己写的继承于"MonoBehaviour"的类,在Inspector窗口中有默认的显示方式,但有些情况下不直观,也无法满足编辑的需求,需要显示上进一步。这是可以继承​​Editor​​类,对自己扩展的组件的编辑界面进行定制。

using UnityEngine;
using System.Collections;

// This is not an editor script.
public class MyPlayer : MonoBehaviour
{
public int armor = 75;
public int damage = 25;
public GameObject gun;

void Update()
{
// Update logic here...
}
}

代码1-5

比如代码1-5所示定义了一个组件,其显示方式默认如图1-3所示,但如果想要显示如果1-4所示就要对其进行扩展。如代码1-6所示

图1-3

图1-4

using UnityEditor;
using UnityEngine;
using System.Collections;

// Custom Editor using SerializedProperties.
// Automatic handling of multi-object editing, undo, and prefab overrides.
[CustomEditor(typeof(MyPlayer))]
[CanEditMultipleObjects]
public class MyPlayerEditor : Editor
{
SerializedProperty damageProp;
SerializedProperty armorProp;
SerializedProperty gunProp;

void OnEnable()
{
// Setup the SerializedProperties.
damageProp = serializedObject.FindProperty("damage");
armorProp = serializedObject.FindProperty("armor");
gunProp = serializedObject.FindProperty("gun");
}

public override void OnInspectorGUI()
{
// Update the serializedProperty - always do this in the beginning of OnInspectorGUI.
serializedObject.Update();

// Show the custom GUI controls.
EditorGUILayout.IntSlider(damageProp, 0, 100, new GUIContent("Damage"));

// Only show the damage progress bar if all the objects have the same damage value:
if (!damageProp.hasMultipleDifferentValues)
ProgressBar(damageProp.intValue / 100.0f, "Damage");

EditorGUILayout.IntSlider(armorProp, 0, 100, new GUIContent("Armor"));

// Only show the armor progress bar if all the objects have the same armor value:
if (!armorProp.hasMultipleDifferentValues)
ProgressBar(armorProp.intValue / 100.0f, "Armor");

EditorGUILayout.PropertyField(gunProp, new GUIContent("Gun Object"));

// Apply changes to the serializedProperty - always do this in the end of OnInspectorGUI.
serializedObject.ApplyModifiedProperties();
}

// Custom GUILayout progress bar.
void ProgressBar(float value, string label)
{
// Get a rect for the progress bar using the same margins as a textfield:
Rect rect = GUILayoutUtility.GetRect(18, 18, "TextField");
EditorGUI.ProgressBar(rect, value, label);
EditorGUILayout.Space();
}
}

代码1-6

​ 使用​​CustomEditor​​​特性把继承于​​Editor​​​的类绑定到自己定义的组件类上。并重写"OnInspectorGUI"函数。如果需要自动处理多个对象的编辑,undo和prefab的覆盖,可以用​​SerializedObject​​​和​​SerializedProperty​​来关联原来类中的要进行编辑的成员。如果不需要上面说的自动处理功能也可以不用关联而直接用自定义组件中的成员变量。

​ 如果需要在"Scene"视图中显示相应内容,需要重写​​OnSceneGUI​​​。可以参考​​Unity Manual Custom Editors​​中“Scene View Additions”。

​ 如果组件中用到了自定义的C#类,也可以自定义其在组件中的显示方式,这时就用到了​​Property Drawers​​​。具体使用方法也可以参考​​Unity Manual Property Drawers​​。

常用布局API

​ 在上面的介绍中介绍了几种扩展编辑器的方法,有的有窗口显示,有的没有。在有窗口显示的扩展方法中,又要如何定义自己的窗口布局呢?下面介绍两个常用的类:​​EditorGUI​​​和​​EditorGUILayout​​​类。​​EditorGUILayout​​​类是自动布局的​​EditorGUI​​​类。​​EditorGUI​​​类的API都需要传入​​Rect​​​参数来定义控件的显示范围,​​EditorGUILayout​​类会根据样式来自动对齐控件。具体的API请自行查阅unity文档,​​这里​​汇总了一些控件的API和其功能。

其他编辑器API

上面介绍了编辑器如何扩展,下面介绍在编辑器扩展过程中经常会用到的一些类。

​ 我们在做编辑器时常用到"Undo"和"Redo"功能。​​Undo​​类提供了给特定对象注册"undo"操作。

​ unity中的shader都有自己的默认显示界面,如果想自定义shader的显示界面,可以继承​​ShaderGUI​​​并重写"OnGUI"函数。具体用法详见​​ShaderGUI​​ 。

​ Prefab是unity中经常用到的资源,用​​PrefabUtility​​可以方便的对其进行创建,修改及其他常用操作。

​ 编辑器中也常对场景进行操作,​​EditorSceneManager​​提供了常用的打开,关闭,保存,设置成未保存状态,合并场景等一系列对场景的操作。

​ 当想获得当前选中对象时可以用​​Selection​

 

标签:窗口,void,扩展,EditorWindow,Unity,EditorGUILayout,using,用户手册,public
From: https://blog.51cto.com/u_6871414/5897136

相关文章

  • Unity用户手册-Mesh合批
    Mesh合批把很多静止的模型,标记为BatchingStatic,原本需要把模型一个个送到GPU渲染,Unity会把相同材质相同纹理相同Shader的模型合批成一个大的模型,送到GPU进行渲染,这样就减少......
  • Unity用户手册-Unity与Android、iOS互相调用
        C#是以Assembly(汇编集)为一个基本单位组织代码的,dll就是一个assemble,dll之间有加载依赖顺序。dll是windows平台上的动态库,而so是linux平台上的动态库,最后.a是IOS......
  • 【Unity插件】NGUI核心组件之UIAtlas
    NGUI:UIAtlasUIAtlas是一个容器,他包含了许多sprite的坐标信息。如果你对这个概念不是很熟悉,你可以这样理解:与使用很多小的贴图来渲染UI相比,使用一张包含了所有小贴图的大......
  • Unity游戏的GC(garbage collection)优化
     Unity版本:5.5引言游戏运行时使用内存来存储数据,当这些数据不再被使用时,存储这些数据的内存被释放以便于之后这些内存可以被复用。垃圾(Garbage)是存储无用数据的内存的术语......
  • Unity--Cinemachine官方实例详解
    1.2DCamera搭建一个快速场景,MainCamera选择Orthographic。在Cinemachine下有Create2DCamera,在生成的相机中设置follow,同时注意body的设置,如下图所示在虚拟相机中还需要......
  • Unity Animator -- Apply Root Motion
    Animator.ApplyRootMotion这个属性是用来控制物体在播放骨骼动画的时候是否应用骨骼根节点的运动参数。一、当没有骨骼根节点的情况时,比如只是一个Cube立方体,如果勾选了Appl......
  • 【详细解析版】Unity UGUI Mask组件实现原理
    MaskingisimplementedusingthestencilbufferoftheGPU.即Mask是利用了GPU的模板缓冲来实现的,关于模板,打个简单的比方,就像一个面具,可以挡住一部分“脸”的显示一样。......
  • Unity-利用SkinnedMeshRenderer和Mesh的BindPose实现骨骼动画
    SkinnedMeshRenderer蒙皮网格渲染器。蒙皮是指将Mesh中的顶点附着(绑定)在骨骼之上,而且每个顶点可以被多个骨骼所控制。骨骼是皮肤网格内的不可见对象,它们影响动画过程中网格......
  • Unity判断对象是否在视野内
    判断对象是否在视野内,有两种方式:第一种:不设置固定的目标,使用LayerMask,设置寻找对象的Layer,使用Physics.OverlapSphere方法,以给定的位置为圆心,按照设定距离投射一个球体,返回......
  • Unity--Physics.OverlapSphere的参数LayerMask和GameObject的layer
    Layer介绍:Unity中是用int32来表示32个Layer层。int32表示二进制一共有32位(0—31)在Unity中每个GameObject都有Layer属性,默认的Layer都是Default。在Unity中可编辑的Layer共......