Unity 编辑器扩展(Editor)

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

猜你喜欢

转载自blog.csdn.net/LWKlwk11/article/details/127889311