zoukankan      html  css  js  c++  java
  • Unity---编辑器扩展



    1、Unity编辑器扩展介绍

    Unity为开发者们提供了很方便的扩展功能,编辑器扩展主要可以用于在Unity界面中添加属于自己的菜单、插件。有时可以大大的提高开发效率。
    用于编辑器扩展的脚本都放在Editor文件夹中,此文件夹中的资源不会在项目发布时候打包。

    2、具体功能

    在使用扩展功能时,需要引用UnityEditor命名空间

    2.1、在菜单栏中添加扩展

    在菜单栏中的扩展可以自己新创,也可以加在已有的菜单里面。

    using UnityEditor;                 
    public class Tools 
    {    
    	[MenuItem("MyTools/Test1")]    //让其显示在菜单栏MyTools-Test1下,MyTest1方法表示要做的工作
    	//放在其下面的方法代表调用这个。上面写的是路径名字
    	private static void MyTest1()          //只有静态方法可以使用MenuItem属性
    	{         
    		Debug.Log("扩展1");
    	}
    }
    

    [MenuItem("MyTools/Test1",false,1)]
    第一个参数:显示在菜单栏的位置
    第二个参数:是否为验证函数,默认为false
    第三个参数:优先级,默认为1000。优先级越大越靠下面,优先级相差>10时,会出现分隔符

    2.2、为扩展事件添加快捷键

    [MenuItem("MyTools/Test1 %t",false,11)]
    在第一个参数后面加空格然后写要加的快捷键。
    此例就代表快捷键为 Ctrl+t

    % == Ctrl
    # == Shift
    & == alt

    2.3、在Hierarchy,Project视图中右键添加扩展

    Hierarchy视图右键下的基本都是GameObject菜单第一层分割线之上的扩展。
    那么只要把扩展放在第一层的分割线之上不就行了。
    而优先级为11则刚好在第一层分割线的最后一个。
    [MenuItem("GameObject/Test1",false,11)]

    Project右键下的选项基本都在Assets目录下,添加方法同上。

    2.4、使用Selection类选择游戏物体

    Selection属于UnityEditor命名空间。

    //返回选择场景中的一个游戏物体或者预制体。未选择会报错返回none,选择多个会返回第一个。
    GameObject go1 = Selection.activeGameObject;
    
    //返回选择场景中的一个游戏物体或预制体、脚本等任意物体。未选择会报错返回none,选择多个会返回第一个。
    Object object1 = Selection.activeObject;
    
    //返回选择场景中的一个游戏物体。未选择会报错返回none,选择多个会返回第一个。
    Transform transform = Selection.activeTransform;
    
    
    //返回GameObject类型数组,为选择场景中的多个游戏物体或者预制体。只会选择符合条件的,未选择则数组长度为0。
    GameObject[] gameObjects = Selection.gameObjects;
    
    //返回Object类型数组,为选择场景中的多个游戏物体或者任意资源。只会选择符合条件的,未选择则数组长度为0。
    Object[] objects = Selection.objects;
    
    //返回transform类型数组,为选择场景中的多个游戏物体。只会选择符合条件的,未选择则数组长度为0。
    Transform[] transforms = Selection.transforms;
    
    

    2.5、Menuitem第二个参数

    使用第二个参数时一般配合两个方法来使用。

        [MenuItem("SelectionTest/Test1 _t", true, 1)]
        static bool Test()
        {
            if (Selection.activeTransform == null)
                return false;
            return true;
        }
    
        [MenuItem("SelectionTest/Test1 _t",false,1)]
        static void Test1()
        {
            Debug.Log(Selection.activeTransform.name);
        }
    

    第二个方法在未选择物体时,本来会报错none。
    当使用第二个参数设为true时,只有当此函数返回为true,才会继续执行下面的函数。
    那么当未选择物体时,第一个函数返回false,就不会再进行第二个函数。就避免了报错的情况。

    注意:MenuItem里的游戏路径和名称必须都相同。

    2.6、ContextMenu和ContextMenuItem

    第一个类用于在组件的右键中添加扩展。
    别的脚本中写其他脚本的扩展需要使用静态方法
    本脚本中添加扩展,不需要使用静态方法

    1. 对系统组件添加扩展
    	[MenuItem("CONTEXT/Rigidbody/Clear")]
    		//CONTEXT(默认写法) , 组件名 , 扩展名
    	static void ClearMassGravity(MenuCommand cmd)
    		//MenuCommand是当前正在操作的组件对象。只要定义就行,系统会自动赋值
    	{
    	    Rigidbody rgd = cmd.context as Rigidbody;
    		//MenuCommand.context为正在操作的组件对象
    	    rgd.mass = 0;
    	}
    
    1. 对自定义脚本添加扩展
    	//自定义脚本的话可以在别的脚本里面写,也可以在本脚本写。
    	//一般都在本脚本写,因为可以更方便的访问脚本中已经存在的游戏物体
    	[ContextMenu("SetColor")]
        void SetColor()
        {
            flashColour = Color.green;
        }
    
    1. 对脚本的属性添加扩展
    	//属于MonoBehaviour,不需要引用Editor。
    	//第一个参数为扩展名,第二个为方法名
        [ContextMenuItem("Add", "AddHp")]
        public int startingHealth = 100;   
    	void AddHp()
        {
            startingHealth += 20;
        }  
    

    2.7、ScriptableWizard---对话框

    当参与的项目非常大时,假如LOL。如果想把所有英雄的HP都一起修改时,使用之前的方法就要一个一个的修改,工作量巨大。
    那么有没有更加简单的方法呢?

    1. 静态方法---对话框的创建
      DisplayWizard<类名>(对话框名,Create按钮名,OtherButton按钮名);

    2. 事件---对话框按钮事件
      OnWizardCreate:Create按钮事件名
      OnWizardOtherButton:OtherButton按钮事件名
      OnWizardUpdate:打开对话框或改变对话框内容时调用此方法

    3. OnEnable:当对话框被创建时调用一次

    using UnityEngine;
    using UnityEditor;
    
    public class EnemyChange : ScriptableWizard {
    
        public int changeStartHpValue = 150;
        public int ChangeSinkSpeed = 11;
        public const string changeStartHpValueKey = "changeStartHpValue";
        public const string ChangeSinkSpeedKey = "ChangeSinkSpeed";
    
        //创建对话框扩展
        [MenuItem("Tools/CreateWizard")]
        static void CreateWizard()
        {
            DisplayWizard<EnemyChange>("统一修改敌人","Change And Close","Change");
            //EnemyChange为类名,对话框名字,Create按钮的名字,OtherButton按钮名字
            //第2、3参数都可以省略
            //Create点击后会关闭对话框,OtherButton按钮点击后不会关闭对话框
        }
    
        //检测Create按钮点击的自带方法
        private void OnWizardCreate()
        {
            GameObject[] enemyPrefabs =  Selection.gameObjects;
    
            int count = 0;
            EditorUtility.DisplayProgressBar("进度", count + "/" + enemyPrefabs.Length, 0);
    
            foreach (GameObject go in enemyPrefabs)
            {
                //获取物体的EnemyHealth脚本
                CompleteProject.EnemyHealth hp = go.GetComponent<CompleteProject.EnemyHealth>();
                Undo.RecordObject(hp, "Change Health And Speed");   //开始记录对hp的更改,之后对其的更改都可以撤销
    
                //改变物体的属性
                hp.startingHealth = changeStartHpValue;
                hp.sinkSpeed = ChangeSinkSpeed;
    
                count++;
                EditorUtility.DisplayProgressBar("进度", count + "/" + enemyPrefabs.Length, (float)count/enemyPrefabs.Length);
            }
            EditorUtility.ClearProgressBar();
        }
    
        //检测Other Button按钮方法
        private void OnWizardOtherButton()
        {
            OnWizardCreate();
            ShowNotification(new GUIContent(Selection.gameObjects.Length + "值被修改了"));
        }
    
    	//打开对话框或改变对话框内容时调用此方法
        private void OnWizardUpdate()
        {
            helpString = "";
            errorString = "";
            if(Selection.gameObjects.Length > 0)
            {
                helpString = "您当前选择了" + Selection.gameObjects.Length + "个敌人";
            }
            else
            {
                errorString = "请选择至少一个敌人";
            }
            EditorPrefs.SetInt("changeStartHpValue", changeStartHpValue);
            EditorPrefs.SetInt("ChangeSinkSpeed", ChangeSinkSpeed);
        }
    
    	//当窗口被创建时调用
        private void OnEnable()
        {
            changeStartHpValue = EditorPrefs.GetInt(changeStartHpValueKey, changeStartHpValue);
            ChangeSinkSpeed = EditorPrefs.GetInt(ChangeSinkSpeedKey, ChangeSinkSpeed);
            
        }
    
        //打开修改选中的物体时调用此方法
        private void OnSelectionChange()
        {
            OnWizardUpdate();
        }
    }
    
  • 相关阅读:
    [LeetCode] Min Stack
    [LeetCode] Find Minimum in Rotated Sorted Array
    [LeetCode] Maximum Product Subarray
    [Jobdu] 题目1504:把数组排成最小的数
    [Jobdu] 题目1544:数字序列区间最小值
    Python2.3-原理之语句和语法
    Python2.5-原理之模块
    Vim2.1-Vim简明教程【CoolShell】【非原创】
    Python2.6-原理之类和oop(下)
    QT1.1-与Opencv的hello world
  • 原文地址:https://www.cnblogs.com/Fflyqaq/p/10620087.html
Copyright © 2011-2022 走看看