Version: 6000.3
语言: 中文
相机叠加
场景视图网格捕捉

创建您自己的叠加层

您可以创建自定义面板叠加层和工具栏Unity 编辑器顶部的一排按钮和基本控件,允许您以各种方式(例如缩放、翻译)与编辑器交互。更多信息
请参阅术语表
覆盖层场景场景包含游戏的环境和菜单。将每个唯一的场景文件视为一个独特的关卡。在每个场景中,你放置你的环境、障碍物和装饰品,基本上是将你的游戏设计和构建成碎片。更多信息
请参阅术语表
视图
窗。

提示:有关创建 UIElement 的信息,请参阅 UI 元素开发人员指南

了解 EditorToolbarElement

工具栏元素可以包含文本、图标或两者的组合。

EditorToolbarElement(Identifier, EditorWindowType)注册要在ToolbarOverlay实现。

您可以从任何VisualElement自己键入并创建样式,但工具栏元素需要特定的样式。最好从这些预定义的其中一个继承EditorToolbar类型:

  • EditorToolbarButton:基于UnityEditor.UIElements.ToolbarButton
  • EditorToolbarToggle:基于UnityEditor.UIElements.ToolbarToggle
  • EditorToolbarDropdown:基于EditorToolbarButton
  • EditorToolbarDropdownToggle:基于UnityEngine.UIElements.BaseField

提示:如果工具栏水平或垂直停靠,则其文本可能不可见或裁剪。您可以为每个工具栏指定一个图标,以避免文本剪切。

创建面板叠加

所有覆盖都必须继承自 Overlay 基类并实现 CreatePanelContent 方法。这将创建一个可以使用的基本面板,并可以向其添加工具栏元素。

要创建面板叠加:

  1. Editor 文件夹中创建一个新的 C# 脚本并将其命名。

  2. 打开您创建的脚本。

  3. 从脚本中删除默认内容。

  4. 实现Overlay类从UnityEditor.OverlaysNamespace。

  5. 覆盖 CreatePanelContent 函数并将您的内容添加到视觉元素实例化或派生自 C# 的可视化树的节点VisualElement类。您可以设置外观样式、定义行为并将其作为 UI 的一部分显示在屏幕上。更多信息
    请参阅术语表
    .

  6. OverlayAttribute 属性添加到类中。

  7. OverlayAttribute中,指定您希望此叠加层位于哪种类型的窗口中:

    • 如果希望叠加在所有编辑器窗口中可用,请指定EditorWindow作为类型。仅继承自ISupportOverlays可以使用叠加层。
    • 使叠加层在继承自ISupportOverlays,将窗口指定为类型。例如,要使叠加层仅在场景视图:您正在创建的世界的交互式视图。您可以使用场景视图来选择和定位场景、角色、摄像机、灯光和所有其他类型的游戏对象。更多信息
      请参阅术语表
      指定SceneView作为类型。
  8. OverlayAttribute,添加显示名称。请参阅 OverlayAttribute 有关可以在OverlayAttribute.

  9. 要添加叠加层折叠时显示的图标,请将Icon属性添加到Overlayclass 并指定一个图标。如果叠加没有图标,则默认情况下,系统使用叠加名称的前两个字母或前两个单词的前两个首字母。

using UnityEditor;
using UnityEditor.Overlays;
using UnityEngine.UIElements;
[Overlay(typeof(SceneView), "Panel Overlay Example", true)]
public class MyToolButtonOverlay : Overlay
{
    public override VisualElement CreatePanelContent()
    {
        var root = new VisualElement() { name = "My Toolbar Root" };
        root.Add(new Label() { text = "Hello" });
        return root;

    }
}

创建工具栏叠加

工具栏叠加层是保存工具栏项的容器,由EditorToolbarElement.

工具栏叠加具有内置的水平、垂直和面板布局。ToolbarOverlay实现一个无参数构造函数,该构造函数将EditorToolbarElementAttribute同上。与面板叠加层不同,内容被定义为独立的部分,这些部分被收集起来形成元素条带。

创建工具栏叠加层时:

  • EditorToolbarElement(Identifier, EditorWindowType)注册要在ToolbarOverlay实现。
  • 使用 OverlayAttribute 标记所有叠加层。
  • 确保工具栏叠加继承ToolbarOverlay并实现一个无参数构造函数。
  • 确保工具栏的内容填充了字符串 ID,这些 ID 将传递给基构造函数。
  • 确保 ID 由EditorToolbarElementAttribute.
  • 使用Icon属性以将图标图标添加到叠加层。当叠加层折叠时,该图标可见。如果叠加层没有图标,则在叠加层折叠时会显示叠加层名称的前两个字母(或前两个单词的前两个首字母)。

当您实现特定于ToolbarOverlay在叠加层中:

  • 使用IAccessContainerWindow仅用于工具栏的界面。元素不知道其上下文。在DropdownToggleExample,如果您切换元素,它将不会执行任何作。
  • UIElement视觉效果的样式。工具栏元素不会在叠加层中设置样式。

要创建工具栏叠加层:

  1. Editor 文件夹中创建一个新的 C# 脚本并将其命名。
  2. 打开您创建的脚本。
  3. 从脚本中删除默认内容。
  4. 将工具栏元素添加到脚本中。
  5. 将工具栏元素添加到覆盖构造函数。
  6. 添加面板叠加层并实现工具栏元素。

此示例是名为 元素工具栏示例(Element Toolbars Example) 的叠加层,演示了以下工具栏元素:

  • EditorToolbarButton
  • EditorToolbarToggle
  • EditorToolbarDropdown
  • EditorToolbarDropdownToggle

每个工具栏元素都创建为独立类,然后添加到叠加面板。

此叠加层:

  • 可以水平和垂直排列为面板。
  • 具有包含文本和工具提示的按钮。
  • 具有由Icon属性。当叠加层折叠时,会显示此图标。
    using System.Collections;
    using System.Collections.Generic;
    using System.Text;
    using UnityEngine;
    using UnityEditor.EditorTools;
    using UnityEditor.Toolbars;
    using UnityEditor.Overlays;
    using UnityEngine.UIElements;
    using UnityEditor;

    // Use [EditorToolbarElement(Identifier, EditorWindowType)] to register toolbar elements for use in ToolbarOverlay implementation.

    [EditorToolbarElement(id, typeof(SceneView))]
    class DropdownExample : EditorToolbarDropdown
    {
        public const string id = "ExampleToolbar/Dropdown";

        static string dropChoice = null;

        public DropdownExample()
        {
            text = "Axis";
            clicked += ShowDropdown;
        }

        void ShowDropdown()
        {
            var menu = new GenericMenu();
            menu.AddItem(new GUIContent("X"), dropChoice == "X", () => { text = "X"; dropChoice = "X"; });
            menu.AddItem(new GUIContent("Y"), dropChoice == "Y", () => { text = "Y"; dropChoice = "Y"; });
            menu.AddItem(new GUIContent("Z"), dropChoice == "Z", () => { text = "Z"; dropChoice = "Z"; });
            menu.ShowAsContext();
        }
    }
    [EditorToolbarElement(id, typeof(SceneView))]
    class ToggleExample : EditorToolbarToggle
    {
        public const string id = "ExampleToolbar/Toggle";
        public ToggleExample()
        {
            text = "Toggle OFF";
            this.RegisterValueChangedCallback(Test);
        }

        void Test(ChangeEvent<bool> evt)
        {
            if (evt.newValue)
            {
                Debug.Log("ON");
                text = "Toggle ON";
            }
            else
            {
                Debug.Log("OFF");
                text = "Toggle OFF";
            }
        }
    }

    [EditorToolbarElement(id, typeof(SceneView))]
    class DropdownToggleExample : EditorToolbarDropdownToggle, IAccessContainerWindow
    {
        public const string id = "ExampleToolbar/DropdownToggle";

        // This property is specified by IAccessContainerWindow and is used to access the Overlay's EditorWindow.

        public EditorWindow containerWindow { get; set; }
        static int colorIndex = 0;
        static readonly Color[] colors = new Color[] { Color.red, Color.green, Color.cyan };
        public DropdownToggleExample()
        {
            text = "Color Bar";
            tooltip = "Display a color rectangle in the top left of the Scene view. Toggle on or off, and open the dropdown" +
                      "to change the color.";

        // When the dropdown is opened, ShowColorMenu is invoked and we can create a popup menu.

            dropdownClicked += ShowColorMenu;

        // Subscribe to the Scene view OnGUI callback so that we can draw our color swatch.

            SceneView.duringSceneGui += DrawColorSwatch;
        }

        void DrawColorSwatch(SceneView view)
        {

         // Test that this callback is for the Scene View that we're interested in, and also check if the toggle is on
        // or off (value).

            if (view != containerWindow || !value)
            {
                return;
            }

            Handles.BeginGUI();
            GUI.color = colors[colorIndex];
            GUI.DrawTexture(new Rect(8, 8, 120, 24), Texture2D.whiteTexture);
            GUI.color = Color.white;
            Handles.EndGUI();
        }

        // When the dropdown button is clicked, this method will create a popup menu at the mouse cursor position.

        void ShowColorMenu()
        {
            var menu = new GenericMenu();
            menu.AddItem(new GUIContent("Red"), colorIndex == 0, () => colorIndex = 0);
            menu.AddItem(new GUIContent("Green"), colorIndex == 1, () => colorIndex = 1);
            menu.AddItem(new GUIContent("Blue"), colorIndex == 2, () => colorIndex = 2);
            menu.ShowAsContext();
        }
    }

    [EditorToolbarElement(id, typeof(SceneView))]
    class CreateCube : EditorToolbarButton//, IAccessContainerWindow
    {
        // This ID is used to populate toolbar elements.

        public const string id = "ExampleToolbar/Button";

        // IAccessContainerWindow provides a way for toolbar elements to access the `EditorWindow` in which they exist.
        // Here we use `containerWindow` to focus the camera on our newly instantiated objects after creation.
        //public EditorWindow containerWindow { get; set; }

        // Because this is a VisualElement, it is appropriate to place initialization logic in the constructor.
        // In this method you can also register to any additional events as required. In this example there is a tooltip, an icon, and an action.

        public CreateCube()
        {

    // A toolbar element can be either text, icon, or a combination of the two. Keep in mind that if a toolbar is
        // docked horizontally the text will be clipped, so usually it's a good idea to specify an icon.

            text = "Create Cube";
            icon = AssetDatabase.LoadAssetAtPath<Texture2D>("Assets/CreateCubeIcon.png");
            tooltip = "Instantiate a cube in the scene.";
            clicked += OnClick;
        }

        // This method will be invoked when the `Create Cube` button is clicked.

        void OnClick()
        {
            var newObj = GameObject.CreatePrimitive(PrimitiveType.Cube).transform;

        // When writing editor tools don't forget to be a good citizen and implement Undo!

            Undo.RegisterCreatedObjectUndo(newObj.gameObject, "Create Cube");

        //if (containerWindow is SceneView view)
        //    view.FrameSelected();

        }

    }

    // All Overlays must be tagged with the OverlayAttribute

    [Overlay(typeof(SceneView), "ElementToolbars Example")]

        // IconAttribute provides a way to define an icon for when an Overlay is in collapsed form. If not provided, the name initials are used.

    [Icon("Assets/unity.png")]

    // Toolbar Overlays must inherit `ToolbarOverlay` and implement a parameter-less constructor. The contents of a toolbar are populated with string IDs, which are passed to the base constructor. IDs are defined by EditorToolbarElementAttribute.

    public class EditorToolbarExample : ToolbarOverlay
    {

     // ToolbarOverlay implements a parameterless constructor, passing the EditorToolbarElementAttribute ID.
    // This is the only code required to implement a toolbar Overlay. Unlike panel Overlays, the contents are defined
    // as standalone pieces that will be collected to form a strip of elements.

        EditorToolbarExample() : base(
            CreateCube.id,
            ToggleExample.id,
            DropdownExample.id,
            DropdownToggleExample.id
            )
        { }
    }


工具栏元素实现

工具栏元素的控件与 UIToolkit 中的等效控件相同,但它们继承了一些工具栏功能和特定样式。

本节包含以下工具栏元素的示例:

编辑器工具栏按钮

EditorToolbarButton是一个包含元素逻辑的独立类。此示例创建一个按钮,当您单击该按钮时,该按钮会生成一个多维数据集:

[EditorToolbarElement(id, typeof(SceneView))]
class CreateCube : EditorToolbarButton
{
// This ID is used to populate toolbar elements.

public const string id = "ExampleToolbar/Button";

// Because this is a VisualElement, it is appropriate to place initialization logic in the constructor.

// In this method you can also register to any additional events as required. In this example there is a tooltip, an icon, and an action.

    public CreateCube()
       {

// A toolbar element can be either text, icon, or a combination of the two. Keep in mind that if a toolbar is docked horizontally the text will be clipped, so it's a good idea to specify an icon.

            text = "Create Cube";
            icon = AssetDatabase.LoadAssetAtPath<Texture2D>("Assets/CreateCubeIcon.png");
            tooltip = "Instantiate a cube in the scene.";
            clicked += OnClick;
}

void OnClick()
{
    var newObj = GameObject.CreatePrimitive(PrimitiveType.Cube).transform;

    // When writing editor tools, don't forget to be a good citizen and implement Undo.

    Undo.RegisterCreatedObjectUndo(newObj.gameObject, "Create Cube");

// Note: Using ObjectFactory class instead of GameObject(like in this example) will register the undo entry automatically removing the need to register manually.

}
}

将元素的 ID 添加到 Overlay 构造函数:

[Overlay(typeof(SceneView), "ElementToolbar Example")]
[Icon("Assets/unity.png")]
public class EditorToolbarExample : ToolbarOverlay
{
    EditorToolbarExample() : base(CreateCube.id) { }

}

编辑器工具栏切换

创建一个包含元素所有逻辑的独立类。此示例创建一个切换开关,用于在控制台中打印其状态并在元素中更新其文本:

[EditorToolbarElement(id, typeof(SceneView))]
class ToggleExample : EditorToolbarToggle
{
    public const string id = "ExampleToolbar/Toggle";
    public ToggleExample()
    {
        text = "Toggle OFF";

    // Register the class to a callback for when the toggle’s state changes

        this.RegisterValueChangedCallback(OnStateChange);
    }

    void OnStateChange(ChangeEvent<bool> evt)
    {
        if (evt.newValue)
        {

    // Put logic for when the state is ON here

                Debug.Log("Toggle State -> ON");
        text = "Toggle ON";
        }
        else
        {

    // Put logic for when the state is OFF here

                Debug.Log("Toggle State -> OFF");
        text = "Toggle OFF";
        }
    }
}

将元素的 ID 添加到 Overlay 构造函数:

[Overlay(typeof(SceneView), "ElementToolbar Example")]
[Icon("Assets/unity.png")]
public class EditorToolbarExample : ToolbarOverlay
{
    EditorToolbarExample() : base(
ToggleExample.id
) { }

}

编辑器工具栏下拉菜单

创建一个包含元素所有逻辑的独立类。这是一个简单的下拉列表示例,它使用下拉选项调整其文本。

[EditorToolbarElement(id, typeof(SceneView))]
class DropdownExample : EditorToolbarDropdown
{
    public const string id = "ExampleToolbar/Dropdown";

    static string dropChoice = null;

    public DropdownExample()
    {
        text = "Axis";
        clicked += ShowDropdown;
    }

    void ShowDropdown()
    {

// A simple GenericMenu to populate the dropdown content

        var menu = new GenericMenu();
        menu.AddItem(new GUIContent("X"), dropChoice == "X", () => { text = "X"; dropChoice = "X"; });
        menu.AddItem(new GUIContent("Y"), dropChoice == "Y", () => { text = "Y"; dropChoice = "Y"; });
        menu.AddItem(new GUIContent("Z"), dropChoice == "Z", () => { text = "Z"; dropChoice = "Z"; });
        menu.ShowAsContext();
    }
}

将元素的 ID 添加到 Overlay 构造函数:

[Overlay(typeof(SceneView), "ElementToolbar Example")]
[Icon("Assets/unity.png")]
public class EditorToolbarExample : ToolbarOverlay
{
    EditorToolbarExample() : base(
DropdownExample.id
) { }

}

EditorToolbar下拉切换

创建一个包含元素所有逻辑的独立类。下拉菜单切换是一个可以像Gizmo与场景中的游戏对象关联的图形叠加层,并显示在场景视图中。移动工具等内置场景工具是 Gizmo,您可以使用纹理或脚本创建自定义 Gizmo。某些 Gizmo 仅在选择游戏对象时绘制,而其他 Gizmo 则由编辑器绘制,而不管选择了哪个游戏对象。更多信息
请参阅术语表
菜单。此示例在场景视图的角落创建一个矩形,您可以从叠加的下拉列表中选择其颜色。

[EditorToolbarElement(id, typeof(SceneView))]
class DropdownToggleExample : EditorToolbarDropdownToggle, IAccessContainerWindow
{
    public const string id = "ExampleToolbar/DropdownToggle";


    // This property is specified by IAccessContainerWindow and is used to access the Overlay's EditorWindow.

    public EditorWindow containerWindow { get; set; }
    static int colorIndex = 0;
    static readonly Color[] colors = new Color[] { Color.red, Color.green, Color.cyan };
    public DropdownToggleExample()
    {
        text = "Color Bar";
        tooltip = "Display a color rectangle in the top left of the Scene view. Toggle on or off, and open the dropdown" +
                "to change the color.";


   // When the dropdown is opened, ShowColorMenu is invoked and you can create a pop-up menu.

        dropdownClicked += ShowColorMenu;


    // Subscribe to the Scene view OnGUI callback to draw a color swatch.

        SceneView.duringSceneGui += DrawColorSwatch;
    }


    void DrawColorSwatch(SceneView view)
    {

        // Test that this callback is for the correct Scene view, and check if the toggle is on
     // or off (value).

        if (view != containerWindow || !value)
        {
            return;
        }


        Handles.BeginGUI();
            GUI.color = colors[colorIndex];
        GUI.DrawTexture(new Rect(8, 8, 120, 24), Texture2D.whiteTexture);
        GUI.color = Color.white;
        Handles.EndGUI();
    }


    // When the drop-down button is clicked, this method creates a pop-up menu at the mouse cursor position.

    void ShowColorMenu()
    {
        var menu = new GenericMenu();
        menu.AddItem(new GUIContent("Red"), colorIndex == 0, () => colorIndex = 0);
        menu.AddItem(new GUIContent("Green"), colorIndex == 1, () => colorIndex = 1);
        menu.AddItem(new GUIContent("Blue"), colorIndex == 2, () => colorIndex = 2);
        menu.ShowAsContext();
    }
}

将元素的 ID 添加到 Overlay 构造函数:

[Overlay(typeof(SceneView), "ElementToolbar Example")]
[Icon("Assets/unity.png")]
public class EditorToolbarExample : ToolbarOverlay
{
    EditorToolbarExample() : base(
DropdownToggleExample.id
) { }


}
相机叠加
场景视图网格捕捉