Создание настраиваемого элемента управления соотношением сторон
Соотношение сторон — это соотношение между шириной и высотой дисплея. Соотношение сторон используется для поддержания пропорций дисплея. Например, если у вас соотношение сторон 4:3, то дисплей имеет ширину 4 пикселей на каждый 3 пиксель высоты. Если у вас соотношение сторон 16:9, то дисплей имеет ширину 16 пикселей на каждый 9 пиксель высоты.
Вы можете установить соотношение сторон визуального элемента непосредственно с помощью свойства aspect-ratio USS. В этом примере показано, как использовать события изменения геометрии для поддержания соотношения сторон пользовательского контроля.
Примерный обзор
Этот пример создает пользовательский контроллер, который поддерживает заданное соотношение сторон его дочерних элементов. Для демонстрационных целей пользовательский контроллер добавляет заполнение слева и справа, если соотношение сторон более широкое. Он добавляет заполнение сверху и снизу, если соотношение сторон большее. Это подталкивает центральные элементы, чтобы вписаться в соотношение сторон.
Вы можете найти завершенные файлы, созданные этим примером, в хранилище GitHub.
Предварительные условия
Это руководство предназначено для разработчиков, знакомых со скриптами Unity Editor, UI Toolkit и C#. Перед началом работы ознакомьтесь со следующим:
Создание класса пользовательского элемента управления
Создайте класс C#, наследующий VisualElement с двумя атрибутами: width и height. width и height атрибуты используются для расчета соотношения сторон.
Создайте проект Unity с любым шаблоном.
-
Создайте скрипт C# с именем
AspectRatio.csсо следующим содержанием: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(); } } }
Использование настраиваемого контроля
Создайте настраиваемое окно редактора, которое использует настраиваемый элемент управления. Проверьте настраиваемый элемент управления, чтобы увидеть, как он ведет себя при изменении соотношения сторон.
-
Создайте скрипт C# с именем
AspectRatioDemo.csсо следующим содержанием:using UnityEditor; using UnityEngine; using UnityEngine.UIElements; public class AspectRatioDemo : EditorWindow { [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}"); }); } } В меню выберите Тест > Aspect Ratio Demo.
Измените соотношение сторон на различные значения. Настраиваемый контроллер добавляет заполнение слева и справа, или сверху и снизу в зависимости от размера окна редактора.