编辑器拓展(入门与实践)

学习目标:入门编辑器并实现几个简单的工具

菜单编辑器

cs 复制代码
[MenuItem("编辑器拓展/MenuItem")]
    static void MenuItem()
    {
        Debug.Log("这是编辑器拓展");
    }
}

案例 1:在场景中的 GameObject 设置

    1. @设置面板
    1. @直接创建 GameObject 结构
    1. @生成的 GameObject 结构进行赋值
    1. @制作成 Prefab

当场景中没有UIRoot物体时方法可用,有了之后方法不启用

当第二个参数 是true时表示是一个验证函数,用来验证这个功能是否启用

cs 复制代码
   [MenuItem("编辑器拓展/SetupUIRoot", true)]
    static bool ValidateUIRoot()
    {
        var gameObject = GameObject.Find("UIRoot");
        return !gameObject;
    }

    [MenuItem("编辑器拓展/SetupUIRoot", false)]
    static void SetupUIRoot()
    {
        Debug.Log("这是编辑器拓展");
        var uiRootObj = new GameObject("UIRoot");
        var canvas = new GameObject("Canvas");
        canvas.transform.SetParent(uiRootObj.transform);
        canvas.AddComponent<Canvas>().renderMode = RenderMode.ScreenSpaceOverlay;
        canvas.AddComponent<CanvasScaler>();
        canvas.AddComponent<GraphicRaycaster>();

        var eventSystem = new GameObject("EventSystem");
        eventSystem.transform.SetParent(uiRootObj.transform);
        eventSystem.AddComponent<EventSystem>();
        eventSystem.AddComponent<StandaloneInputModule>();
    }

第3个参数优先级,主要影响菜单出现的先后顺序,不填默认是1000. 值越小,出现在越上层的位置。当一个菜单的优先级 - 它上一个菜单的优先级 >= 11,菜单之间还能看到分界线

快捷键:可以为MenuItem可以添加快捷键。ctrl,shift,alt 都有对应的字符,比如表示shift键的字符是#。那么快捷键shift + q,可以写成 #q。

cs 复制代码
        //注意:路径和快捷键之间有个空格
        [MenuItem("Learn/Log #q",false)]
        public static void Log()
        {
            Debug.Log(1);
        }

如果你想直接按一个键就触发,不想多按ctrl/shift/alt,那么可以用 '_'来表示。比如你想按F1就触发,那么可以写成 _F1

在Hierarchy层级窗口增加右键菜单

MenuItem还可以增加到右键菜单里面。其实用法和上面差不多,但有两个要求。

  • MenuItem("GameObject/xxxx",false,0)命名时,名字必须以GameObject/开头

在Assets资源窗口增加右键菜单

  • MenuItem("Assets/自定义菜单_Assets")\] 命名时,以Assets/开头 优先级可以不填

    [MenuItem("Assets/自定义菜单_Assets")]
    public static void CustomMenu_Assets(){}
复制代码
### 创建一个窗口

![](https://i-blog.csdnimg.cn/direct/a5faf787a6104fc2aa28d824df97c59a.png)

```cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System.IO;

public class CreateUIRootWindow : EditorWindow
{
    [MenuItem("编辑器拓展/SetupUIRoot", true)]
    static bool ValidateUIRoot()
    {
        var gameObject = GameObject.Find("UIRoot");
        return !gameObject;
    }

    private string mWidth = "720";
    private string mHeight = "1280";

    private void OnGUI()
    {
        GUILayout.BeginHorizontal();
        GUILayout.Label("width:", GUILayout.Width(45));
        mWidth = GUILayout.TextField(mWidth);
        GUILayout.Label("x", GUILayout.Width(10));
        GUILayout.Label("height", GUILayout.Width(50));
        mHeight = GUILayout.TextField(mHeight);
        GUILayout.EndHorizontal();

        if(GUILayout.Button("Setup"))
        {
            var width = float.Parse(mWidth);
            var height = float.Parse(mHeight);

            Setup(width, height);
            Close();
        }
    }

    [MenuItem("编辑器拓展/SetupUIRoot", false)]
    static void SetupUIRoot()
    {
        var window = GetWindow<CreateUIRootWindow>();
        window.Show();
    }

    static void Setup(float width,float height)
    {
        //UIRoot
        var uiRootObj = new GameObject("UIRoot");
        var uirootScript = uiRootObj.AddComponent<UIRoot>();
        uiRootObj.layer = LayerMask.NameToLayer("UI");

        //Canvas
        var canvas = new GameObject("Canvas");

        canvas.transform.SetParent(uiRootObj.transform);

        canvas.AddComponent<Canvas>().renderMode = RenderMode.ScreenSpaceOverlay;

        // CanvasScaler
        var canvasScaler = canvas.AddComponent<CanvasScaler>();
        canvasScaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
        canvasScaler.referenceResolution = new Vector2(width, height);

        canvas.AddComponent<GraphicRaycaster>();

        canvas.layer = LayerMask.NameToLayer("UI");

        // EventSystem
        var eventSystem = new GameObject("EventSystem");

        eventSystem.transform.SetParent(uiRootObj.transform);

        eventSystem.AddComponent<EventSystem>();
        eventSystem.AddComponent<StandaloneInputModule>();
        eventSystem.layer = LayerMask.NameToLayer("UI");

        // Bg
        var bgObj = new GameObject("Bg");
        bgObj.AddComponent<RectTransform>();
        bgObj.transform.SetParent(canvas.transform);
        bgObj.transform.localPosition = Vector3.zero;

        uirootScript.Bg = bgObj.transform;
        // Common

        var commonObj = new GameObject("Common");
        commonObj.AddComponent<RectTransform>();
        commonObj.transform.SetParent(canvas.transform);
        commonObj.transform.localPosition = Vector3.zero;

        uirootScript.Common = commonObj.transform;
        // PopUI
        var popUp = new GameObject("PopUp");
        popUp.AddComponent<RectTransform>();
        popUp.transform.SetParent(canvas.transform);
        popUp.transform.localPosition = Vector3.zero;

        uirootScript.PopUp = popUp.transform;

        // Forward
        var forwardObj = new GameObject("Forward");
        forwardObj.AddComponent<RectTransform>();
        forwardObj.transform.SetParent(canvas.transform);
        forwardObj.transform.localPosition = Vector3.zero;

        uirootScript.Forward = forwardObj.transform;


        var uirootScriptSerializedObj = new SerializedObject(uirootScript);

        uirootScriptSerializedObj.FindProperty("mRootCanvas").objectReferenceValue = canvas.GetComponent<Canvas>();
        uirootScriptSerializedObj.ApplyModifiedPropertiesWithoutUndo();

        // 制作 prefab
        var savedFolder = Application.dataPath + "/Resources";

        if (!Directory.Exists(savedFolder))
        {
            Directory.CreateDirectory(savedFolder);
        }

        var savedFilePath = savedFolder + "/UIRoot.prefab";

        PrefabUtility.SaveAsPrefabAssetAndConnect(uiRootObj, savedFilePath, InteractionMode.AutomatedAction);
    }
}

效果:

自动生成代码

案例2 : 根据GameObject结构生成代码工具

  • 在 Hierarchy上生成菜单
  • 生成脚本
  • 添加标记
  • 搜索并生成脚本

学习课程链接:siki学院课程,直接贴链接会被识别成广告

Unity编辑器拓展(一)-MenuItem的使用_unity menuitem-CSDN博客

相关推荐
敲代码的 蜡笔小新2 小时前
【行为型之中介者模式】游戏开发实战——Unity复杂系统协调与通信架构的核心秘诀
unity·设计模式·c#·中介者模式
敲代码的 蜡笔小新4 小时前
【行为型之解释器模式】游戏开发实战——Unity动态公式解析与脚本系统的架构奥秘
unity·设计模式·游戏引擎·解释器模式
敲代码的 蜡笔小新9 小时前
【行为型之观察者模式】游戏开发实战——Unity事件驱动架构的核心实现策略
观察者模式·unity·设计模式·c#
向宇it9 小时前
【unity游戏开发——编辑器扩展】使用EditorGUI的EditorGUILayout绘制工具类在自定义编辑器窗口绘制各种UI控件
开发语言·ui·unity·c#·编辑器·游戏引擎
qq_2052790512 小时前
unity 鼠标更换指定图标
unity·游戏引擎
FAREWELL0007515 小时前
Unity基础学习(九)输入系统全解析:鼠标、键盘与轴控制
学习·unity·c#·游戏引擎
敲代码的 蜡笔小新19 小时前
【行为型之策略模式】游戏开发实战——Unity灵活算法架构的核心实现策略
unity·设计模式·c#·策略模式
Flamesky2 天前
Unity编辑器重新编译代码
unity·重新编译
qq_5982117572 天前
Unity.UGUI DrawCall合批笔记
笔记·unity·游戏引擎
Tech Synapse3 天前
Unity ML-Agents实战指南:构建多技能游戏AI训练系统
人工智能·游戏·unity