Editor:
对编辑器进行一些拓展开发
关于继承Mono类的扩展开发
 
特性:
[特性]:声明性的标签(类,方法,结构体,变量)
特性只对字段声明有效,后面必须接字段;多个特性,可以修饰一个字段
 
修饰变量:
[Tooltip("玩家名字")]:在Inspector面板鼠标悬停在修饰的变量上时,显示一个提示性的信息
[Range(1, 50)]:修饰整型和浮点类型的变量,生成一个滑动条,范围是最小值和最大值之间
----第一个参数:最小值
----第二个参数:最大值
[Header("玩家的信息")]:显示一个标题,只修饰字段
[Space(10)]:可以与上面形成一个空白区域
[Multiline(5)]:只能修饰string类型的变量,可以让string类型的变量在Inspector面板显示多行
参数就是显示几行
[TextArea()]:只能修饰string类型的变量,在Inspector面板显示带滚动的文本区域
[TextArea(2, 5)]:同上,最少显示2行,最多显示5行,文本内容超过5行出现滑动条
[Delayed()]:
[HideInInspector]:把公共的变量在Inspector面板隐藏,但是还是可序列化的。
[SerializeField]:可以让私有变量可以被序列化,在Inspector面板显示
[System.NonSerialized]:让公有的变量不可序列化
[ContextMenuItem("function", "Test")]:是修饰的字段当右键点击时,出现一个自定义的方法的菜单,选中这个方法菜单时,执行这个方法,可以用于还原重置字段
----第一个参数:显示的名字
----第二个参数:方法名,这个方法必须是非静态的方法
[Delayed()]:修饰的变量,只有当按下回车键或鼠标失焦时,才会把新输入的值赋值给变量
 
修饰方法:
[ContextMenu("重置方法")]:可以让组件在面板的该组件的齿轮设置菜单里多出一个选项,如果选中了该选项,执行该特性修饰的方法,参数显示在面板的名字,修饰的方法是非静态的方法。
[UnityEditor.MenuItem("Menu/Open")]:添加菜单项,在编辑器的上方跟File,Edit等同级的菜单项,修饰的必须是静态的方法。
 
修饰类:
[System.Serializable]:让该类的对象是可序列化的。
[AddComponentMenu("Lesson/MonoEditor")]:修饰继承Mono的类,在Add Component按钮添加选项,当选中该选项时,就把该特性修饰的脚本添加到了该物体上,支持层级化的结构(用"/"分隔)
名字可以和类名不一样,只对继承Mono的类有效
[ExecuteInEditMode]:可以在编辑模式下执行该脚本,与运行时执行不一样,运行时Updata一直每帧执行一次,只有场景中的某个物体发生改变时,才执行一次Updata
与[Delayed()]:不同,只要值发生改变,就把新值赋给变量
[RequireComponent(typeof(Rigidbody))]:使脚本依赖于一个组件,当把脚本添加到一个物体上时,该脚本先判断该物体上是否有依赖的组件,如果没有,添加上依赖的组件,如果有,不会多次添加组件
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(Rigidbody))]
[ExecuteInEditMode]
//[AddComponentMenu("LessonMonoEditor")]
[AddComponentMenu("Lesson/MonoEditor")]
public class LessonMonoEditor : MonoBehaviour {
[Header("玩家的信息")]//显示标题
[Space()]
[Tooltip("玩家名字")]//鼠标悬停,显示信息
public string playerName;
[Delayed()]
public int id;
[HideInInspector]//面板隐藏(可序列化)
public int id1;
[SerializeField]//面板显示(可序列化标识)
private bool sex;
[System.NonSerialized]//面板隐藏(不可序列化标识)
public bool sex1;
[Range(, )]//滑动条
public float hp;
[Range(, )]
public int level;
[Multiline()]
public string message;//多行显示
[TextArea()]
public string message1;//带滑动条的多行显示
[ContextMenuItem("function", "Test")]
[TextArea(, )]
public string message2;
// Use this for initialization
void Start() {
hp = ;
Debug.Log("hp:" + hp);
}
// Update is called once per frame
void Update() {
Debug.Log(id);
}
void Test()
{
Debug.Log("Test方法执行");
message2 = "这是一个玩家信息";
}
[ContextMenu("重置方法")]
private void ResetPosition()//必须是非静态的方法
{
Debug.Log("ResetPosition");
}
[UnityEditor.MenuItem("Menu/Open")]
static void OpenMenu()
{
Debug.Log("OpenMenu");
}
[System.Serializable]
public class A
{
public string name;
}
}
 
项目打包报错问题:脚本中有UnityEditor特性,工程将无法打包
解决方法:把UnityEditor的代码放在Editor文件夹下
 
特殊文件夹
Resources:可以Resources.Load加载资源
StreamingAssets:一起打包,不会压缩
Editor:引用了UnityEditor命名空间或使用UnityEditor下的方法,这个类如果没放在Editor文件夹下,打包的时候会报错。Editor文件夹下的所有脚本都不会打进发布的包,并且该脚本一般都是在编辑时使用的。只要使用了UnityEditor命名空间,那么这个脚本一定要放在Editor文件夹下。
Editor文件夹不一定在根目录,子目录也可以,可以有多个Editor文件夹
 
关于Inspector面板界面的编辑器开发
1、引用命名空间using UnityEditor;
2、继承Editor类
3、关联该类扩展开发的脚本[CustomEditor(typeof(类名))]
4、利用OnEnable和OnDisable做一些初始化和清理的工作,
----OnEnable选择挂着关联脚本的物体时执行一次
----OnDisable当取消选择挂着关联脚本的物体时执行一次
5、利用Target来获取选中物体身上的关联的脚本的对象
6、重写OnInspectorGUI方法,对关联脚本的Inspector界面进行重新绘制
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;//1、引用命名空间
[CustomEditor(typeof(Player))]//3、关联该类扩展开发的脚本
public class PlayerEditor : Editor//2、继承Editor类
{
public Player player;
//4、利用OnEnable和OnDisable做一些初始化和清理的工作
private void OnEnable()
{
//5、利用Target来获取到你选择的物体上的LessonPlayer对象
player = (Player)target;
Debug.Log("OnEnable:" + player.gameObject.name);
}
//6、重写OnInspectorGUI,在这个方法内对LessonPlayer里的变量等进行重写操作
public override void OnInspectorGUI()
{
//base.OnInspectorGUI();
//针对字符串变量
//第一个参数:输入框前面显示的文本内容
//第二个参数:输入框里面显示的文本内容
//返回值:每次输入的内容
player.playerName = EditorGUILayout.TextField("玩家名字:", player.playerName);
//针对int类型
player.id = EditorGUILayout.IntField("玩家ID:", player.id);
//针对float类型
player.hp = EditorGUILayout.FloatField("玩家血量:", player.hp);
//针对bool类型
player.sex = EditorGUILayout.Toggle("玩家性别:", player.sex);
//针对枚举的单选
player.type = (Player.PlayerType)EditorGUILayout.EnumPopup("玩家职业:", player.type);
//针对枚举的多选,对于每个枚举值对应的int值是2的n次方,类似标签和层级的枚举
player.work = (Player.PlayerWork)EditorGUILayout.EnumMaskField("玩家职业:", player.work);
//针对向量类型
player.birthPosition = EditorGUILayout.Vector3Field("玩家出生位置", player.birthPosition);
//针对颜色类型
player.color = EditorGUILayout.ColorField("玩家颜色", player.color);
//对于基类是Object类型的对象,我们可以使用这种方式去查找相应的变量
//第一个参数,显示的标签
//第二个参数,要找的变量
//第三个参数,该变量的类型,一般使用typeof(类型)
//第四个参数,是否可以使用场景中的物体
player.weaponObj = (GameObject)EditorGUILayout.ObjectField("武器的对象", player.weaponObj, typeof(GameObject), true);
player.tex = (Texture)EditorGUILayout.ObjectField("玩家的贴图", player.tex, typeof(Texture), true);
player.weapon = (Weapon)EditorGUILayout.ObjectField("武器的脚本", player.weapon, typeof(Weapon), false);
//终极方法,支持各种类型
//通过变量的名字来获取序列化的对象
SerializedProperty items = serializedObject.FindProperty("items");
//绘制序列化的对象,
//第二个参数:显示的名字
//第三个参数:true证明该对象里的所有的属性也是可以序列化的
EditorGUILayout.PropertyField(items, new GUIContent("物品:"), true);
//针对类的
SerializedProperty pet = serializedObject.FindProperty("pet");
EditorGUILayout.PropertyField(pet, new GUIContent("宠物:"), true);
//用于保存序列化的对象,如果没有这个方法,对对象的修改无效
serializedObject.ApplyModifiedProperties();
//布局调整
EditorGUILayout.BeginHorizontal();//开始水平布局
player.playerName = EditorGUILayout.TextField("玩家名字:", player.playerName);
player.id = EditorGUILayout.IntField("玩家ID:", player.id);
EditorGUILayout.EndHorizontal();//结束水平布局
//针对float类型的滑动条,第三个和第四个参数,最小值和最大值
player.maxHp = EditorGUILayout.Slider("玩家的最大血量:", player.maxHp, , );
//针对float类型的
player.hp = EditorGUILayout.FloatField("玩家血量:", player.hp);
//获取自动布局的位置信息,按照顺序往后的位置
Rect rect = GUILayoutUtility.GetRect(, );
//绘制一个进度条
EditorGUI.ProgressBar(rect, player.hp / player.maxHp, "玩家的血量");
//绘制提示信息
player.atk = EditorGUILayout.FloatField("攻击力", player.atk);
if (player.atk > )
{
EditorGUILayout.HelpBox("攻击力太高了", MessageType.Error);
}
else if (player.atk < )
{
EditorGUILayout.HelpBox("攻击力太低了", MessageType.Warning);
}
else
{
EditorGUILayout.HelpBox("攻击力适中", MessageType.Info);
}
}
private void OnDisable()
{
Debug.Log("OnDisable");
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour {
public string playerName;
public int id;
public float hp;
public float maxHp;
public bool sex;
public PlayerType type;
public PlayerWork work;
public Vector3 birthPosition;
public Color color;
public GameObject weaponObj;
public Texture tex;
public Weapon weapon;
public Pet pet;
public List<string> items;
public float atk;
[ContextMenu("打印")]
private void DebugMessage()
{
Debug.Log(playerName);
Debug.Log("宠物的名字:" + pet.name);
}
public enum PlayerType//针对枚举的单选
{
战士,//战士,0,0000
法师,//法师,1,0001
牧师,//牧师,2,0010
术士,//术士,3,0011 = 0001或上0010,针对枚举的多选时,选择刺客会同时选上法师和道士
盗贼,//盗贼,4,0100
猎人,//猎人,5,0101
}
public enum PlayerWork//针对枚举的多选,对于每个枚举值对应的int值是2的n次方
{
分解师 = ,//分解师,0,0001
炼金师 = ,//炼金师,0,0010
采矿师 = ,//采矿师,0,0100
锻造师 = ,//锻造师,0,1000
}
[System.Serializable]
public class Pet
{
public string name;
public float hp;
}
}
 
 
关于Window界面的编辑器开发
1、创建一个处理窗口的类
2、该类需要引用命名空间UntiyEditor
3、该类需要继承EditorWindow
4、利用EditorWindow.GetWindow<当前处理窗口类的名字>();创建一个窗口(使用这种方式[MenuItem("MyMenu/创建窗口")])
5、利用OnEnable和OnDisable去初始化工作和清理工作
6、利用OnGUI方法,对窗口显示自定义的绘制
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;//2、引用命名空间UnityEditor
//1、先创建一个处理窗口的类
public class WindowEditor : EditorWindow//3、继承EditorWindow类
{
[MenuItem("MyMenu/创建窗口")]
static void CreateWindow()
{
//4、创建一个创建
EditorWindow.GetWindow<WindowEditor>();
}
//5、利用OnEnable方法和OnDisable方法,实现初始化和清理工作
public void OnEnable()
{
Debug.Log("OnEnable");
}
public GameObject obj;
private Vector2 scrollPosition;
//6、利用OnGUI方法实现对窗口内容的绘制
private void OnGUI()
{
//Debug.Log("OnGUI");
EditorGUILayout.LabelField("我的窗口");
//绘制一个进度条
Rect rect = GUILayoutUtility.GetRect(,);
EditorGUI.ProgressBar(rect, 0.5f, "玩家血量");
//对于基类是Object类型的对象
obj = (GameObject)EditorGUILayout.ObjectField("GameObject", obj, typeof(GameObject), true);
//绘制滚动窗口
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
for (int i = ; i < ; i++)
{
EditorGUILayout.LabelField("我的窗口");
}
EditorGUILayout.EndScrollView();
}
public void OnDisable()
{
Debug.Log("OnDisable");
}
}
 
使用EditorWindow快速开发Json
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BagData
{
private static BagData instance;
public static BagData Instance
{
get { return instance; }
}
public static void SetInstance(BagData bag)
{
if (bag == null)
{
instance = new BagData();
instance.items = new List<ItemData>();
}
else
{
instance = bag;
}
}
private BagData() { }
public List<ItemData> items;
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class BagDataWindow : EditorWindow
{
[MenuItem("MyMenu/背包数据窗口")]
static void CreateWindow()
{
EditorWindow.GetWindow<BagDataWindow>();
}
private void OnEnable()
{
string json = FileTools.ReadJson(Application.streamingAssetsPath + "/BagJson.txt");
if (json == "")
{
BagData.SetInstance(null);
}
else
{
BagData.SetInstance(JsonUtility.FromJson<BagData>(json));
}
Debug.Log(BagData.Instance.items.Count);
data = new ItemData();
}
private Vector2 scrollPosition;
private ItemData data;
private Texture itemTex;
private void OnGUI()
{
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
GUI.skin.label.fontSize = ;
GUILayout.Label("背包数据");
GUILayout.Space();
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
for (int i = ; i < BagData.Instance.items.Count; i++)
{
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("ID:" + BagData.Instance.items[i].ID);
EditorGUILayout.LabelField("ID:" + BagData.Instance.items[i].itemName);
EditorGUILayout.LabelField("ID:" + BagData.Instance.items[i].iconName);
if (GUILayout.Button("删除"))
{
BagData.Instance.items.Remove(BagData.Instance.items[i]);
}
EditorGUILayout.EndHorizontal();
}
EditorGUILayout.EndScrollView();
EditorGUILayout.BeginHorizontal();
data.ID = EditorGUILayout.IntField("物品ID:", data.ID);
data.itemName = EditorGUILayout.TextField("物品名字:", data.itemName);
itemTex = (Texture)EditorGUILayout.ObjectField("物品图片:", itemTex, typeof(Texture), false);
if (GUILayout.Button("添加"))
{
bool isFindID = false;
for (int i = ; i < BagData.Instance.items.Count; i++)
{
if (BagData.Instance.items[i].ID == data.ID)
{
isFindID = true;
break;
}
}
if (isFindID)
{
Debug.LogError("ID重复了");
}
else
{
data.iconName = itemTex.name;
BagData.Instance.items.Add(data);
data = new ItemData();
for (int i = ; i < BagData.Instance.items.Count; i++)
{
if (data.ID < BagData.Instance.items[i].ID)
{
data.ID = BagData.Instance.items[i].ID;
}
}
data.ID++;
}
}
EditorGUILayout.EndHorizontal();
bool isID = false;
for (int i = ; i < BagData.Instance.items.Count; i++)
{
if (BagData.Instance.items[i].ID == data.ID)
{
isID = true;
break;
}
}
if (isID)
{
EditorGUILayout.HelpBox("ID重复了", MessageType.Error);
}
}
private void OnDisable()
{
//关闭界面时,需要把数据写入到Json
string json = JsonUtility.ToJson(BagData.Instance, true);
FileTools.WriteJson(Application.streamingAssetsPath + "/BagJson.txt", json);
}
}

Unity3D学习笔记(二十八):Editor的更多相关文章

  1. Java学习笔记二十八:Java中的接口

    Java中的接口 一:Java的接口: 接口(英文:Interface),在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明.一个类通过继承接口的方式,从而来继承 ...

  2. Java基础学习笔记二十八 管家婆综合项目

    本项目为JAVA基础综合项目,主要包括: 熟练View层.Service层.Dao层之间的方法相互调用操作.熟练dbutils操作数据库表完成增删改查. 项目功能分析 查询账务 多条件组合查询账务 添 ...

  3. Unity3D学习笔记(十八):动画内容补充

    动画系统: 旧动画系统(帧动画系统:关键帧驱动,关键帧记录的数据进行插值移动) 1.添加Animation,添加到父物体上 2.添加动画片段 3.添加关键帧(子物体的坐标是相对于父物体的坐标),帧之间 ...

  4. angular学习笔记(二十八-附2)-$http,$resource中的promise对象

    下面这种promise的用法,我从第一篇$http笔记到$resource笔记中,一直都有用到: HttpREST.factory('cardResource',function($resource) ...

  5. angular学习笔记(二十八-附1)-$resource中的资源的方法

    通过$resource获取到的资源,或者是通过$resource实例化的资源,资源本身就拥有了一些方法,$save,$delete,$remove,可以直接调用来保存该资源: 比如有一个$resour ...

  6. angular学习笔记(二十八)-$http(6)-使用ngResource模块构建RESTful架构

    ngResource模块是angular专门为RESTful架构而设计的一个模块,它提供了'$resource'模块,$resource模块是基于$http的一个封装.下面来看看它的详细用法 1.引入 ...

  7. PHP学习笔记二十八【抽象类】

    <?php //定义一个抽象类.主要用来被继承 //如果一个类继承了抽象类,则它必须实现该抽象类的所有抽象方法(除非它自己也是抽象类) // abstract class Animal{ pub ...

  8. Java框架spring 学习笔记(十八):事务管理(xml配置文件管理)

    在Java框架spring 学习笔记(十八):事务操作中,有一个问题: package cn.service; import cn.dao.OrderDao; public class OrderSe ...

  9. python3.4学习笔记(二十六) Python 输出json到文件,让json.dumps输出中文 实例代码

    python3.4学习笔记(二十六) Python 输出json到文件,让json.dumps输出中文 实例代码 python的json.dumps方法默认会输出成这种格式"\u535a\u ...

  10. python3.4学习笔记(二十五) Python 调用mysql redis实例代码

    python3.4学习笔记(二十五) Python 调用mysql redis实例代码 #coding: utf-8 __author__ = 'zdz8207' #python2.7 import ...

随机推荐

  1. 【转】查看sqlserver被锁的表以及如何解锁

    查看被锁表: select request_session_id spid,OBJECT_NAME(resource_associated_entity_id) tableName from sys. ...

  2. Python读取excel数据类型处理

    一.python xlrd读取datetime类型数据:https://blog.csdn.net/y1535766478/article/details/78128574 (1)使用xlrd读取出来 ...

  3. 20155228 2016-2017-2 《Java程序设计》第10周学习总结

    20155228 2016-2017-2 <Java程序设计>第10周学习总结 教材学习内容总结 网络 网络是能够波此通信的计算机的集合根据范}到的宽度,网络可以分为局域网和广域网.LAN ...

  4. 正确把mysql数据库从windows迁移到linux系统上的方法

    (一)用mysqldump命令导出数据库文件: 在windows下cd到Mysql的bin目录: c:/data.txt这个目录和导出的文本名可以自己随便取,-B 后面的是表名,我要导出的表明叫use ...

  5. Unable to open socket file: target process not responding or HotSpot VM not loaded

    Unable to open socket file: target process not responding or HotSpot VM not loaded The -F option can ...

  6. createDocumentFragment()用法总结

    1.createDocumentFragment()方法,是用来创建一个虚拟的节点对象,或者说,是用来创建文档碎片节点.它可以包含各种类型的节点,在创建之初是空的. 2.DocumentFragmen ...

  7. Autel MaxiSys Elite Diagnostic Tool Common problem solving methods

    1. updating MaxiFlash Elite to firmware 3.21? My maxisys communicate with the MaxiFlash J2534 but Ma ...

  8. 模拟ATM的功能

    import java.io.FileReader; import java.io.FileWriter; import java.io.PrintWriter; import java.util.A ...

  9. ubuntu 常见命令整理

    SSH 查看ssh服务的进程是否已经开启ps -e | grep ssh 安装ssh服务组件sudo apt-get install openssh-server 服务启动和关闭 方法1:servic ...

  10. 【题解】Luogu P4679 [ZJOI2011]道馆之战

    原题传送门 码农题树剖好题,口袋妖怪是个好玩的游戏 这道题要用树链剖分,我博客里有对树链剖分的详细介绍 下文左右就代表树的节点按dfs序后的左右,上.下分别表示每个节点的A.B区域 考虑在链上的情况, ...