版本:Unity 6 (6000.0)
语言:English
在窗口之间创建拖放列表和树形视图
设置 UI 样式

创建纵横比自定义控件

纵横比图像比例尺寸的关系,例如宽度和高度。
参见 术语表
是显示器宽度和高度之间的比率。纵横比用于保持显示器的比例。例如,如果您的纵横比为 4:3,则显示器每 3 个像素的高度对应 4像素计算机图像中的最小单位。像素大小取决于屏幕分辨率。每个屏幕像素都会计算像素光照。 更多信息
参见 术语表
的宽度。如果您的纵横比为 16:9,则显示器每 9 个像素的高度对应 16 个像素的宽度。

示例概述

此示例创建一个自定义控件,该控件维护其子元素的指定纵横比。为了演示目的,如果显示器比例更宽,则自定义控件会在左侧和右侧添加填充,或者如果显示器比例更高,则在顶部和底部添加填充,从而将“中心”项目推入以适应纵横比。

Aspect ratio example
纵横比示例

您可以在此 GitHub 存储库 中找到此示例创建的完整文件。

先决条件

本指南适用于熟悉 Unity 编辑器、UI(用户界面) 允许用户与您的应用程序交互。Unity 目前支持三种 UI 系统。 更多信息
参见 术语表
工具包和 C# 脚本的开发人员。在开始之前,请熟悉以下内容

创建自定义控件类

创建一个从 VisualElement 继承的 C# 类,并包含两个属性:widthheightwidthheight 属性用于计算纵横比。

  1. 使用任何模板创建一个 Unity 项目。

  2. 创建一个名为 AspectRatio.cs 的 C# 脚本,内容如下

    using UnityEngine;
    using UnityEngine.UIElements;
        
    // Custom element that lays out its contents following a specific aspect ratio.
    [UxmlElement]
    public partial class AspectRatioElement : VisualElement
    {
        // The ratio of width.
        [UxmlAttribute("width")]
        public int RatioWidth
        {
            get => _ratioWidth;
            set
            {
                _ratioWidth = value;
                UpdateAspect();
            }
        }
        
        // The ratio of height.
        [UxmlAttribute("height")]
        public int RatioHeight
        {
            get => _ratioHeight;
            set
            {
                _ratioHeight = value;
                UpdateAspect();
            }
        }
        
        // Padding elements to keep the aspect ratio.
        private int _ratioWidth = 16;
        private int _ratioHeight = 9;
        
        public AspectRatioElement()
        {
            // Update the padding elements when the geometry changes.
            RegisterCallback<GeometryChangedEvent>(UpdateAspectAfterEvent);
            // Update the padding elements when the element is attached to a panel.
            RegisterCallback<AttachToPanelEvent>(UpdateAspectAfterEvent);
        }
        
        static void UpdateAspectAfterEvent(EventBase evt)
        {
            var element = evt.target as AspectRatioElement;
            element?.UpdateAspect();
        }
        
        private void ClearPadding()
        {
            style.paddingLeft = 0;
            style.paddingRight = 0;
            style.paddingBottom = 0;
            style.paddingTop = 0;
        }
            
        // Update the padding.
        private void UpdateAspect()
        {
            var designRatio = (float)RatioWidth / RatioHeight;
            var currRatio = resolvedStyle.width / resolvedStyle.height;
            var diff = currRatio - designRatio;
                
            if (RatioWidth <= 0.0f || RatioHeight <= 0.0f)
            {
                ClearPadding();
                Debug.LogError($"[AspectRatio] Invalid width:{RatioWidth} or height:{RatioHeight}");
                return;
            }
        
            if (float.IsNaN(resolvedStyle.width) || float.IsNaN(resolvedStyle.height))
            {
                return;
            }
                
            if (diff > 0.01f)
            {
                var w = (resolvedStyle.width - (resolvedStyle.height * designRatio)) * 0.5f;
                style.paddingLeft = w;
                style.paddingRight = w;
                style.paddingTop = 0;
                style.paddingBottom = 0;
            }
            else if (diff < -0.01f)
            {
                var h = (resolvedStyle.height - (resolvedStyle.width * (1/designRatio))) * 0.5f;
                style.paddingLeft= 0;
                style.paddingRight = 0;
                style.paddingTop = h;
                style.paddingBottom = h;
            }
            else
            {
                ClearPadding();
            }
        }
    }
    

使用自定义控件

创建一个使用自定义控件的自定义编辑器窗口。测试自定义控件以查看更改纵横比时的行为。

  1. 创建一个名为 AspectRatioDemo.cs 的 C# 脚本,内容如下

    using UnityEditor;
    using UnityEngine;
    using UnityEngine.UIElements;
        
    public class AspectRatioDemo : EditorWindow
    {
        [SerializeField]
        private VisualTreeAsset m_VisualTreeAsset = default;
        
        [MenuItem("Test/AspectRatioDemo")]
        public static void ShowExample()
        {
            AspectRatioDemo wnd = GetWindow<AspectRatioDemo>();
            wnd.titleContent = new GUIContent("AspectRatioDemo");
        }
        
        public void CreateGUI()
        {
            // Each editor window contains a root VisualElement object.
            VisualElement root = rootVisualElement;
        
            var aspectRatio = new AspectRatioElement();
            aspectRatio.style.flexGrow = 1;
        
            var widthField = new IntegerField() { value = aspectRatio.RatioWidth, label = "W"};
            var heightField = new IntegerField() { value = aspectRatio.RatioHeight, label = "H" };
        
            root.Add(widthField);
            root.Add(heightField);
            root.Add(aspectRatio);
        
            var contents = new VisualElement();
            aspectRatio.Add(contents);
        
            aspectRatio.style.backgroundColor = Color.black;
        
            contents.style.backgroundColor = Color.green;
        
            widthField.RegisterValueChangedCallback((evt) =>aspectRatio.RatioWidth = evt.newValue);
            heightField.RegisterValueChangedCallback((evt) => aspectRatio.RatioHeight = evt.newValue);
                
            contents.style.width = new Length(100, LengthUnit.Percent);
            contents.style.height = new Length(100, LengthUnit.Percent);
                
            contents.RegisterCallback<GeometryChangedEvent>((evt) =>
            {
                Debug.Log($"Content ratio: {evt.newRect.width} x {evt.newRect.height} : {evt.newRect.width/evt.newRect.height}");
            });
        
        }
    }
    
  2. 从菜单中选择测试 > 纵横比演示

  3. 将纵横比更改为不同的值。自定义控件会根据编辑器窗口的大小在左侧和右侧或顶部和底部添加填充。

其他资源

在窗口之间创建拖放列表和树形视图
设置 UI 样式