Unity 编辑器扩展

可以在unity做窗口啊 编辑器啊 还有菜单栏自己的功能实现 一般都放在Editor文件里


image.png

在这个文件里面的东西不会被打包

using UnityEditor;
using UnityEngine;
public class Tools
{
    [MenuItem("Tools/test/test1")]//在菜单栏Tools 的test点击使用方法
    static void Test()//要用静态才能被调用到
    {
        Debug.Log("Test1");
    }

    [MenuItem("Tools/test/test2")]
    static void Test2()
    {
        Debug.Log("Test2");
    }
    //每一个类都有横线分割 默认是第四类 如果在第一类就也可以在Hierarchy右键出来
    //每一个菜单栏的priority优先级默认为1000 小于10按大小排序 大于10是分到另外一组
    [MenuItem("GameObject/my tool",false,10)]
    static void Test3()
    {
        Debug.Log("Test3");
    }

    [MenuItem("Assets/assetbtn"]
    static void Test4()
    {
        Debug.Log("Test4");
    }
}

接下来是效果图



image.png

image.png

然后下个Unity官方的项目方便 做编辑器扩展 需要一个unity账号申请一个就可以了 不用翻墙


image.png

搜索Survival 就是下面这个官方教学
image.png
image.png

点击下载
然后提示加载覆盖
没有提示的话可以再C盘固定目录找到 要显示隐藏的项目 用户后面的名字是你的当前计算机用户的名字默认就我这个
这下面就是每一个下载的package


image.png

image.png

找到sence试玩一下还算不错

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
public class PlayerEditor
{
    //CONTEXT 组件名 PlayerHealth脚本名 第三个组件btn名
    [MenuItem("CONTEXT/PlayerHealth/InitHealthAndSpeed")]
    static void InitHealthAndSpeed(MenuCommand cmd)//是当前正在操作的组件对象 系统调用不用传
    {
        //输出挂载物体的名字
        Debug.Log(cmd.context.name);
        //()转不行就报错 as 不管是不是空是不是能转类型都不会报错
        CompleteProject.PlayerHealth health = (CompleteProject.PlayerHealth)cmd.context;
        health.startingHealth = 200;
        health.flashSpeed = 10;
    }
}

找到物体挂的PlayerHealth脚本右键就有了


image.png

image.png

右键点击之后就修改了


image.png

再来设置一个rigidbody的质量和不受重力

[MenuItem("CONTEXT/Rigidbody/Clear")]
    static void ClearMassAndGravity(MenuCommand cmd)
    {
        Rigidbody rgd = cmd.context as Rigidbody;
        rgd.mass = 0;
        rgd.useGravity = false;
    }
image.png
 [MenuItem("GameObject/my delete", false,11)]
    static void Test6()
    {
        foreach (var item in Selection.objects)
        {
            //编辑器模式下的删除 Ctrl Z无法恢复
            //GameObject.DestroyImmediate(item);

            //需要把删除的操作注册到操作记录里 这个可以撤销的
            Undo.DestroyObjectImmediate(item);
        }
    }

然后我们删除


image.png

添加快捷键
% – CTRL on Windows / CMD on OSX

– Shift

& – Alt
LEFT/RIGHT/UP/DOWN – Arrow keys
F1…F2 – F keys
HOME, END, PGUP, PGDN

  //要有空格 然后加_
    [MenuItem("Tools/test3 _t")]
    static void Test7()
    {
        Debug.Log("Test3");
    }

    //%=ctrl #=shift &=alt 
    [MenuItem("Tools/test4 %q")]
    static void Test8()
    {
        Debug.Log("Test3");
    }
image.png

image.png

第二个参数是验证判断条件

 //除了bool都一样
    [MenuItem("GameObject/my delete", true, 11)]
    static bool MyDeleteValidate()
    {
        if (Selection.objects.Length>0)
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    //第二个参数 是验证方法是否可用
    [MenuItem("GameObject/my delete", false,11)]
    static void Test6()
    {
        foreach (var item in Selection.objects)
        {
            //编辑器模式下的删除 Ctrl Z无法恢复
            //GameObject.DestroyImmediate(item);

            //需要把删除的操作注册到操作记录里 这个可以撤销的
            Undo.DestroyObjectImmediate(item);
        }
    }
image.png

然后没有选中就不让点 但是project界面是亮的

 //在不是Editor脚本中创建按钮
        [ContextMenu("SetColor")]
        void SetColor()
        {
            flashColour = Color.green;
        }
image.png

这样也可以添加

在某个属性上添加按钮 这个也不用unityEditor


image.png
  //按钮名 方法名
        [ContextMenuItem("Add hp", "AddHp")]
        public int startingHealth = 100;
        void AddHp()
        {

        }

然后创建对话框

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
//可编程的对话框
public class EnemyChange : ScriptableWizard
{
    [MenuItem("Tools/CreateWizard")]
    static void CreateWizard()
    {
        //泛型是做对话框的类 第一个参数是对话框名字 第二个是改变的btn名字
        ScriptableWizard.DisplayWizard("统一修改敌人", "Change Value");
    }

    public int changeHealthValue = 10;
    public int changeSinkSpeedValue = 1;

    //按钮点击 之后触发的事件
    private void OnWizardCreate()
    {
        //objects 是场景中 这个包含预制体
        GameObject[] enemyP = Selection.gameObjects;
        for (int i = 0; i < enemyP.Length; i++)
        {
            CompleteProject.EnemyHealth e = enemyP[i].GetComponent();
            //编辑器记录下可以撤回 放在改变之前
            Undo.RecordObject(e, "change health and speed");
            e.startingHealth += 10;
            e.sinkSpeed += 1;

        }
    }
}


image.png

点击之后就改变了

添加提示报错 还有保存上次调整信息

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
//可编程的对话框
public class EnemyChange : ScriptableWizard
{
    [MenuItem("Tools/CreateWizard")]
    static void CreateWizard()
    {
        //泛型是做对话框的类 第一个参数是对话框名字 第二个是改变的btn名字
        ScriptableWizard.DisplayWizard("统一修改敌人", "Change And Close", "Change");
    }

    public int changeHealthValue = 10;
    public int changeSinkSpeedValue = 1;

    const string changeHealthValueKey= "EnemyChange.changeHealthValue";
    const string changeSinkSpeedValueKey = "EnemyChange.changeSinkSpeedValue";
    //被创建出来调用
    private void OnEnable()
    {
        //一开始调用参数
        changeHealthValue= EditorPrefs.GetInt(changeHealthValueKey, changeHealthValue);
        changeSinkSpeedValue = EditorPrefs.GetInt(changeSinkSpeedValueKey, changeSinkSpeedValue);
    }
    //按钮点击 之后触发的事件
    private void OnWizardCreate()
    {
        //objects 是场景中 这个包含预制体
        GameObject[] enemyP = Selection.gameObjects;
        //进度条
        EditorUtility.DisplayProgressBar("进度", "0/" + enemyP.Length + "完成修改值", 0);
        int count = 0;
        for (int i = 0; i < enemyP.Length; i++)
        {
            CompleteProject.EnemyHealth e = enemyP[i].GetComponent();
            //编辑器记录下可以撤回 放在改变之前
            Undo.RecordObject(e, "change health and speed");
            e.startingHealth += 10;
            e.sinkSpeed += 1;
            count++;
            EditorUtility.DisplayProgressBar("进度", "0/" + enemyP.Length + "完成修改值", (float)i/enemyP.Length);
        }
        //清空进度条
        //EditorUtility.ClearProgressBar();
        ShowNotification(new GUIContent($"{ Selection.gameObjects.Length}个游戏的值被修改了"));
    }

    private void OnWizardOtherButton()
    {
        OnWizardCreate();
    }

    //自带的Update 打开 改变值调用
    private void OnWizardUpdate()
    {
        if (Selection.gameObjects.Length>0)
        {
            helpString = $"您当前选择了{Selection.gameObjects.Length}个敌人";
        }
        else
        {
            //提示
            errorString = "请选择至少一个敌人";
        }

        //自动保存改变后的字段 下次还是改变的值
        EditorPrefs.SetInt(changeHealthValueKey, changeHealthValue);
        EditorPrefs.SetInt(changeSinkSpeedValueKey, changeSinkSpeedValue);
    }
    //选择物体发生改变
    private void OnSelectionChange()
    {
        OnWizardUpdate();
    }
}



image.png
image.png
image.png

创建常用的窗口 长时间存在的

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
//继承这个类
public class MyWindow : EditorWindow
{
    [MenuItem("Window/Show My Window")]
    static void ShowMyWindow()
    {
        EditorWindow.GetWindow().Show();
    }

    string name1="";
    //绘制 循环调用的
    private void OnGUI()
    {
        //Text
        GUILayout.Label("这是我的窗口");
        //输入框
        name1 = GUILayout.TextField(name1);

        if (GUILayout.Button("创建"))
        {
            GameObject go = new GameObject(name1);
            //登记撤销记录
            Undo.RegisterCreatedObjectUndo(go,"Create obj");
        }       
    }
}

image.png

可以拖到这里


image.png

输入名字

image.png

然后就创建了一堆
这个是源码
https://github.com/1004019267/EditorTest/tree/master

你可能感兴趣的:(Unity 编辑器扩展)