Unity 编辑器扩展(Editor)
学习记录
using UnityEditor;
using UnityEngine;
public class Tools
{
[MenuItem("Tools/Test")]
static void Test()
{
//选中的场景里面的游戏对象(多选)
GameObject[] gameObjects = Selection.gameObjects;
GameObject obj = Selection.activeGameObject;
Debug.Log(obj);
//删除游戏对象
//GameObject.DestroyImmediate();
//删除游戏对象(可以按Ctrl + Z 进行撤销的)
//Undo.DestroyObjectImmediate();
//Debug.Log("Click Tools/Test Button");
}
//第三个参数,层级,类似于先实现后显示,
//GameObject/Test3 _S 空格_S 快捷键,直接点击快捷键就可以执行此方法
//% = Ctrl # = Shift & = Alt
//GameObject/Test3 %Q = Ctrl + Q
[MenuItem("GameObject/Test3 _S", false, 41)]
static void Test3()
{
Debug.Log("Click Tools/Test Button");
}
//% = Ctrl # = Shift & = Alt
//GameObject/Test3 %Q = Ctrl + Q
[MenuItem("GameObject/Test3 %Q", false, 41)]
static void Test4()
{
Debug.Log("Click Tools/Test Button");
}
//鼠标右键点击游戏对象上挂载的PlayerHealth脚本,执行的方法
//CONTEXT 固定的
//PlayerHealth 脚本名字
//Init 右键点击显示的方法名字
//CONTEXT/PlayerHealth/Init
[MenuItem("CONTEXT/PlayerHealth/Init")]
static void Init(MenuCommand cmd)
{
//参数
//MenuCommand 当前正在操作的组件,现在操作的组件应该是PlayerHealth脚本
//cmd.context 鼠标右键点击游戏对象上挂载的PlayerHealth脚本
Debug.Log(cmd.context.name);
Debug.Log(cmd.context.GetType().FullName);
//当前项目里有两个PlayerHealth脚本,当前脚本的命名空间为CompleteProject,所以需要加上命名空间
CompleteProject.PlayerHealth playerHealth = cmd.context as CompleteProject.PlayerHealth;
playerHealth.startingHealth = 200;
playerHealth.flashSpeed = 10;
Debug.Log("Init");
}
[MenuItem("CONTEXT/Rigidbody/ClearAllMassAndGravity")]
static void ClearMassAndGravity(MenuCommand cmd)
{
Rigidbody ri = cmd.context as Rigidbody;
ri.mass = 0;
ri.useGravity = false;
}
//第二个参数的介绍
//如果返回True,在面板上显示此方法,如果返回False,在面板上不显示此方法(点击右键)
//如果返回True,可以执行此方法(黑色),如果返回False,不能执行(灰色)(菜单栏里GameObject/MyDelete)
[MenuItem("GameObject/MyDelete %W", false, 41)]
static void MyDelete()
{
Debug.Log("Click Tools/Test Button");
}
//[MenuItem(这里必须保持高度的一致,除了第二个参数由False变为True,其他的,都必须保持一致)]
//[MenuItem("GameObject/MyDelete %W", false, 41)]的验证方法
//返回True,执行[MenuItem("GameObject/MyDelete %W", false, 41)]的方法
//返回False,不执行
[MenuItem("GameObject/MyDelete %W", true, 41)]
static bool MyDeleteValidate()
{
if (Selection.gameObjects.Length > 0)
return true;
else
return false;
}
}
using UnityEngine;
using UnityEditor;
public class MyWindow : EditorWindow
{
//生成窗口
[MenuItem("Window/ShowMyWindow")]
static void ShowMyWindow()
{
//必须使用此方法创建
MyWindow window = GetWindow<MyWindow>();
//创建窗口
window.Show();
}
private string TextField = "";
private void OnGUI()
{
GUILayout.Label("这是我的窗口");
TextField = GUILayout.TextField(TextField);
if (GUILayout.Button("创建"))
{
GameObject go = new GameObject(TextField);
//保存游戏对象,可以进行Ctrl + Z 撤回处理
Undo.RegisterCreatedObjectUndo(go,"create ");
Debug.Log("点击了创建按钮,并且创建的游戏对象的名字为:" + TextField);
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
/*
此脚本为面板类
在面板里显示的数据,以及执行的方法
*/
public class EnemChange : ScriptableWizard
{
//生成EnemChange脚本的面板
[MenuItem("Tools/CreateWinWizard")]
static void CreateWinWizard()
{
//必须使用ScriptableWizard.DisplayWizard
//参数1为面板的名字
//参数2为修改createButtonName,可以设置为自己想要的名字,createButtonName为按钮的名字
//参数3为新增加一个按钮,设置新增加按钮的名字
ScriptableWizard.DisplayWizard<EnemChange>("标题:统一修改敌人的ChangeHealthValue", "Change And Close", "Change");
}
public int _ChangeHealthValue = 10;
public int _ChangeSinkSpeedValue = 1;
//当脚本显示出来的时候调用此方法
//包含创建此脚本的时候也会调用
private void OnEnable()
{
//Editor模式下数据的读取
_ChangeHealthValue = EditorPrefs.GetInt("EnemChange._ChangeHealthValue", _ChangeHealthValue);
_ChangeSinkSpeedValue = EditorPrefs.GetInt("EnemChange._ChangeSinkSpeedValue", _ChangeSinkSpeedValue);
}
//名字固定,点击 Change And Close 按钮的时候,执行的方法
//监测createButton点击事件
//点击此按钮之后,面板会直接关闭
private void OnWizardCreate()
{
//进度条显示
//第一次调用开启进度条
//第一个参数,标题
//第二个参数,内容
//第三个参数,进度,0到1
//需要手动关闭进度条,调用 EditorUtility.ClearProgressBar()方法
EditorUtility.DisplayCancelableProgressBar("进度","0/" + Selection.gameObjects.Length + " 完成修改值",0);
//休眠1毫秒
System.Threading.Thread.Sleep((int)(1f));
GameObject[] gameObjects = Selection.gameObjects;
//计数器
int count = 0;
foreach (var item in gameObjects)
{
if (item.GetComponent<CompleteProject.EnemyHealth>())
{
CompleteProject.EnemyHealth enemyHealth = item.GetComponent<CompleteProject.EnemyHealth>();
//记录一下,可以按Ctrl + Z 执行撤回的操作
//必须是在修改之前进行调用
Undo.RecordObject(enemyHealth, "change heal and speed");
enemyHealth.sinkSpeed += _ChangeSinkSpeedValue;
enemyHealth.startingHealth += _ChangeHealthValue;
//Debug.Log(count);
count++;
//进度条显示
//第一个参数,标题
//第二个参数,内容
//第三个参数,进度,0到1
EditorUtility.DisplayCancelableProgressBar("进度", count +"/" + Selection.gameObjects.Length + " 完成修改值",
((float)count) / ((float)gameObjects.Length));
//休眠1毫秒
System.Threading.Thread.Sleep((int)(1f));
}
}
EditorUtility.DisplayCancelableProgressBar("进度", count + "/" + Selection.gameObjects.Length + " 完成修改值",
((float)count) / ((float)gameObjects.Length));
Debug.Log(((float)count) / ((float)gameObjects.Length));
Debug.Log("CreateButton Click");
ShowNotification(new GUIContent(Selection.gameObjects.Length + "个游戏对象的值被修改了。"));
//休眠1毫秒
System.Threading.Thread.Sleep((int)(1f));
//关闭进度条
EditorUtility.ClearProgressBar();
}
//弹出面板后会调用一次 OnWizardUpdate 方法
//弹处面板后,修改EnemChange里面属性的值的时候会调用 OnWizardUpdate 方法,修改一次,调用一次
//其他时间不会调用
private void OnWizardUpdate()
{
Debug.Log("WizardUpdate");
PromptInformation();
}
//当选择的游戏对象发生改变时,调用OnSelectionChange方法
private void OnSelectionChange()
{
PromptInformation();
}
//自己写的方法,用来显示提示信息的
void PromptInformation()
{
//helpString 为提示信息(灰色)
//errorString 为报错信息(红色)
//不需要定义,直接使用就行
errorString = null;
helpString = null;
if (Selection.gameObjects.Length > 0)
{
helpString = "您当前选择了" + Selection.gameObjects.Length + "个敌人。";
}
else
{
errorString = "请选择至少一个敌人。";
}
//Editor模式下数据的保存
EditorPrefs.SetInt("EnemChange._ChangeHealthValue", _ChangeHealthValue);
EditorPrefs.SetInt("EnemChange._ChangeSinkSpeedValue", _ChangeSinkSpeedValue);
}
//新建面板的时候,第三个参数生成的按钮,点击的时候调用的方法,名字固定
//点击此按钮之后,面板不会关闭
private void OnWizardOtherButton()
{
Debug.Log("ChangeButton Click");
OnWizardCreate();
}
}
using System.Threading;
using UnityEditor;
using UnityEngine;
// Shows a cancellable progress bar for the specified number of seconds.
public class EditorUtilityDisplayCancelableProgressBar : EditorWindow
{
public float secs = 5f;
[MenuItem("Examples/Progress Bar Usage")]
static void Init()
{
var window = GetWindow(typeof(EditorUtilityDisplayCancelableProgressBar));
window.Show();
}
void OnGUI()
{
secs = EditorGUILayout.Slider("Time to wait:", secs, 1.0f, 20.0f);
if (GUILayout.Button("Display bar"))
{
var step = 0.1f;
for (float t = 0; t < secs; t += step)
{
if (EditorUtility.DisplayCancelableProgressBar("Cancelable", "Doing some work...", t / secs))
break;
// Normally, some computation happens here.
// This example uses Sleep.
Thread.Sleep((int)(step * 1000.0f));
}
EditorUtility.ClearProgressBar();
}
}
}
Demo,百度网盘地址:
链接:https://pan.baidu.com/s/19jDYyJ5dSvAeN1vctcev5g
提取码:o6rl