UnityEditor研究学习之自定义Editor
UnityEditor研究学习之自定义Editor
今天我们来研究下Unity3d中自定义Editor,这个会让物体的脚本在Inspector视窗中,产生不同的视觉效果。
什么意思,举个例子,比如游戏中我有个角色Player,他有攻击力,护甲,装备等属性。
所以我定义一个脚本:MyPlayer.cs:
using UnityEngine;
using System.Collections; public class MyPlayer : MonoBehaviour
{
public int armor = 100;
public int attack = 100;
public GameObject equipment;
void Start()
{ }
void Update()
{ }
}
这边我定义了三个变量,分别是护甲、攻击力还有GameObject类型的装备。
将这个脚本赋值给GameObject,可以看到Inspector视窗:
那么,如果我想要修改下护甲,攻击力的显示效果,那么就可以自定义Editor:
using UnityEngine;
using UnityEditor;
using System.Collections;
[CustomEditor(typeof(MyPlayer))]
public class MyPlayerEditor : Editor
{
public override void OnInspectorGUI()
{
var target = (MyPlayer)(serializedObject.targetObject);
target.attack = EditorGUILayout.IntSlider("攻击力",target.attack,0,100);
ProgressBar(target.attack, "攻击力"); target.equipment =
EditorGUILayout.ObjectField("装备",target.equipment,typeof(GameObject));
}
private void ProgressBar(float value, string label)
{
Rect rect = GUILayoutUtility.GetRect(18, 18, "TextField");
EditorGUI.ProgressBar(rect, value, label);
EditorGUILayout.Space();
}
}
是不是一下子就好看了不少,操作性也变强了。这个就是编辑器的魅力所在。
还有一种写法就是,通过SerializedObject的SerializedProperty
我个人不是很推荐,因为更加复杂,但是效果跟上面第一种完全一样:
using UnityEngine;
using UnityEditor;
using System.Collections;
[CustomEditor(typeof(MyPlayer))]
public class MyPlayerEditor2 : Editor
{
SerializedProperty attack;
void OnEnable()
{
attack = serializedObject.FindProperty("attack");
}
public override void OnInspectorGUI()
{
serializedObject.Update();
EditorGUILayout.IntSlider(attack, 0, 100, new GUIContent("攻击力"));
ProgressBar(attack.intValue/100, "攻击力");
serializedObject.ApplyModifiedProperties();
}
private void ProgressBar(float value, string label)
{
Rect rect = GUILayoutUtility.GetRect(18, 18, "TextField");
EditorGUI.ProgressBar(rect, value, label);
EditorGUILayout.Space();
}
}
接下来开始具体学Editor的变量和方法等:
Editor.serializedObject
自定义编辑器所需要序列化的物体。看下官方的描述:
Description
A SerializedObject representing the object or objects being inspected.
The serializedObject can be used inside the OnInspectorGUI function of a custom Editor as described on the page about the Editor class.
The serializedObject should not be used inside OnSceneGUI or OnPreviewGUI. Use the target property directly in those callback functions instead.
就是说serializedObject只能在OnInspectorGUI方法里面使用,其他地方是不行的,还有在OnSceneGUI和OnPreviewGUI使用target来代替serializedObject。
接着来看看Editor有哪些方法:
1.Editor.DrawDefaultInspector
Description
Draw the built-in inspector.
Call this function from inside OnInspectorGUI method to draw the automatic inspector. It is useful you don't want to redo the entire inspector, but you want to add a few buttons to it.
这个方法,我们要在OnInspectorGUI()方法里面调用,用来绘制一些平常的UI,比如滑块,按钮等等。反正只要记住在OnInspectorGUI()方法最后调用这个方法就行。
2.Editor.OnPreviewGUI
Parameters
r | Rectangle in which to draw the preview. |
background | Background image. |
Description
Implement to create your own custom preview for the preview area of the inspector, primary editor headers and the object selector.
If you implement OnInteractivePreviewGUI then this will only be called for non-interactive custom previews. The overidden method should use the rectangle passed in and render a preview of the asset into it. The default implementation is a no-op.
Note: Inspector previews are limited to the primary editor of persistent objects (assets), e.g., GameObjectInspector, MaterialEditor, TextureInspector. This means that it is currently not possible for a component to have its own inspector preview.
这个方法是创建我们自己的物体的Preview窗口的表现。我们接下来做个试验看下这个Preview窗口长啥样子。
首先,我们先创建一个窗口,然后在窗口中传入我们需要想看的物体。
using UnityEngine;
using System.Collections;
using UnityEditor;
public class MyPreviewWindow : EditorWindow
{
static EditorWindow myWindow;
GameObject gameObject;
Editor gameObjectEditor;
[MenuItem("Window/MyPreviewWindow")]
public static void Init()
{
myWindow = (MyPreviewWindow)EditorWindow.GetWindow(typeof(MyPreviewWindow), false, "MyPreviewWindow", false);
myWindow.Show();
}
void OnGUI()
{
gameObject = (GameObject)EditorGUILayout.ObjectField(gameObject, typeof(GameObject), true);
if (gameObject != null)
{
if (gameObjectEditor == null)
{
gameObjectEditor = Editor.CreateEditor(gameObject);
}
gameObjectEditor.OnPreviewGUI(GUILayoutUtility.GetRect(500, 500), EditorStyles.whiteLabel);
}
}
}
这里我直接拖入一个Cube,然后观察下,下面的Preview窗口:
可以从下面的Preview窗口中看到Cube的模样。
所以我们想要观察一个物体,可以先为他创建他本身的Editor,然后直接修改他的OnPreviewGUI()方法就可以
了。
3.Editor.DrawPreview
Parameters
previewPosition | The available area to draw the preview. |
Description
The first entry point for Preview Drawing.
Draws a grid of previews if there are multiple targets available. Override this method if you want to customize this behaviour.
这个方法是绘制Preview视图,我们可以重写这个方法来完成当我们调用这个方法的时候会有不同的显示效果。
using UnityEngine;
using System.Collections;
using UnityEditor;
public class MyPreviewWindow : EditorWindow
{
static EditorWindow myWindow;
GameObject gameObject;
Editor gameObjectEditor;
[MenuItem("Window/MyPreviewWindow")]
public static void Init()
{
myWindow = (MyPreviewWindow)EditorWindow.GetWindow(typeof(MyPreviewWindow), false, "MyPreviewWindow", false);
myWindow.Show();
}
void OnGUI()
{
gameObject = (GameObject)EditorGUILayout.ObjectField(gameObject, typeof(GameObject), true);
if (gameObject != null)
{
if (gameObjectEditor == null)
{
gameObjectEditor = Editor.CreateEditor(gameObject);
}
gameObjectEditor.OnPreviewGUI(GUILayoutUtility.GetRect(500, 500), EditorStyles.whiteLabel);
gameObjectEditor.DrawPreview(GUILayoutUtility.GetRect(500, 500));
}
}
}
我们在原先的代码中添加
gameObjectEditor.DrawPreview(GUILayoutUtility.GetRect(500, 500));
来看下会有啥不同的变化:
可以看到有两个Cube,但是他们的背景不同,主要是我们没有重写DrawPreview()。
UnityEditor研究学习之自定义Editor的更多相关文章
- UnityEditor研究学习之EditorWindow
在unity使用过程中,其实我们都是在各个不同功能的Window下工作. 比如在Scene窗口中操作物体,在Inspector中操作物体属性,在Game视窗中观察游戏状态. 所以窗口是Unity的灵魂 ...
- 日常学习随笔-自定义了一个MyArrayListDefin集合(数组扩容+迭代器+JDK1.8新方法+详细说明)
一.自定义了一个ArrayList的模拟集合(源码+详细说明) 前段时间分析了下ArrayList集合的源码,总觉得如果不自己定义一个的话,好像缺了点什么,所以有了如下的代码. 代码可以说是逐行注释了 ...
- 强化学习实战 | 自定义Gym环境之井字棋
在文章 强化学习实战 | 自定义Gym环境 中 ,我们了解了一个简单的环境应该如何定义,并使用 print 简单地呈现了环境.在本文中,我们将学习自定义一个稍微复杂一点的环境--井字棋.回想一下井字棋 ...
- Java虚拟机JVM学习06 自定义类加载器 父委托机制和命名空间的再讨论
Java虚拟机JVM学习06 自定义类加载器 父委托机制和命名空间的再讨论 创建用户自定义的类加载器 要创建用户自定义的类加载器,只需要扩展java.lang.ClassLoader类,然后覆盖它的f ...
- 利用Mono.Cecil动态修改程序集来破解商业组件(仅用于研究学习)
原文 利用Mono.Cecil动态修改程序集来破解商业组件(仅用于研究学习) Mono.Cecil是一个强大的MSIL的注入工具,利用它可以实现动态创建程序集,也可以实现拦截器横向切入动态方法,甚至还 ...
- 【转】手把手教你读取Android版微信和手Q的聊天记录(仅作技术研究学习)
1.引言 特别说明:本文内容仅用于即时通讯技术研究和学习之用,请勿用于非法用途.如本文内容有不妥之处,请联系JackJiang进行处理! 我司有关部门为了获取黑产群的动态,有同事潜伏在大量的黑产群 ...
- 手把手教你读取Android版微信和手Q的聊天记录(仅作技术研究学习)
1.引言 特别说明:本文内容仅用于即时通讯技术研究和学习之用,请勿用于非法用途.如本文内容有不妥之处,请联系JackJiang进行处理! 我司有关部门为了获取黑产群的动态,有同事潜伏在大量的黑产群 ...
- 基于python的opcode优化和模块按需加载机制研究(学习与个人思路)(原创)
基于python的opcode优化和模块按需加载机制研究(学习与思考) 姓名:XXX 学校信息:XXX 主用编程语言:python3.5 个人技术博客:http://www.cnblogs.com/M ...
- WebAPI调用笔记 ASP.NET CORE 学习之自定义异常处理 MySQL数据库查询优化建议 .NET操作XML文件之泛型集合的序列化与反序列化 Asp.Net Core 轻松学-多线程之Task快速上手 Asp.Net Core 轻松学-多线程之Task(补充)
WebAPI调用笔记 前言 即时通信项目中初次调用OA接口遇到了一些问题,因为本人从业后几乎一直做CS端项目,一个简单的WebAPI调用居然浪费了不少时间,特此记录. 接口描述 首先说明一下,基于 ...
随机推荐
- 一些你可能需要的okhttp实现
https://blog.csdn.net/qq_17766199/article/details/53186874 今天分享一些我在项目中使用到的okhttp实现,由简至难.(以下内容均在okhtt ...
- 浅谈jvm
1 .说起jvm,很多人感觉jvm离我们开发实际很远.但是,我们开发缺每时每刻都离不开jvm. a: java源码 编译后成.class字节码文件, b:根据classpath找到这个字节码文件, c ...
- bzoj 1271
思路:因为被占奇数次的点只有一个, 那么我们可以将数轴分成两部分,奇数次点之前的前缀和为偶数,之后的前缀和为奇数, 然后就可以二分了. #include<bits/stdc++.h> #d ...
- lnmp 一键安装包
系统需求: CentOS/RHEL/Fedora/Debian/Ubuntu/Raspbian Linux系统 需要5GB以上硬盘剩余空间 需要128MB以上内存(如果为128MB的小内存VPS,Xe ...
- 解问 lambda表达式
目录 1.0 何为Lambda 1.1 Lambda语法特征 1.2 Lambda实例 1.3 Lambda中的stream 1.4 Lambda 中的 stream 效率 1.0 何为Lambda ...
- Ajax与传统Web开发的区别
基本概念 1.1,Ajax AJAX:即“Asynchronous Javascript And XML”(异步的JavaScript和XML),是指一种创建交互式网页应用的网页开发技术,尤其是在一种 ...
- 切换 NPM 镜像源
转载:快速切换NPM源 我们介绍过cnpmjs.org和淘宝 npm 两个 NPM 镜像.除此之外,还有一些国外的 NPM 镜像.不同地区访问不同的镜像速度可能有差异,因此有时候需要切换 NPM 镜像 ...
- 机器学习<1>:基础概念
本文是笔者学习李航老师的经典教材<统计学习方法>第一章的学习笔记,分享在此,作为机器学习系列的开篇文章,在本系列中,将会逐一总结介绍主要的机器学习算法的基本原理.基于Python的具体实现 ...
- [BZOJ4237]稻草人/[JOISC2014]かかし
[BZOJ4237]稻草人/[JOISC2014]かかし 题目大意: 平面上\(n(n\le2\times10^5)\)个点,若一个矩形各边与坐标轴平行,左下角和右上角都在\(n\)个点之中,且内部不 ...
- CI下php操作memcached 的问题
CI下php操作memcached 的时候,获取memcached里不存在的key时候,会出错,然而放在程序的最后一行就不会出错,不知何故,mark一下.