using UnityEngine; using UnityEngine.UI; [RequireComponent(typeof(RectTransform), typeof(LayoutElement))] [ExecuteInEditMode] public class LayoutElementFitParent : MonoBehaviour { [SerializeField] private float aspectRatio = 1; [SerializeField] private bool updateMin = false; [SerializeField] private bool updatePreferred = false; private bool isDirty = false; private Vector2 lastParentSize; private new RectTransform transform; private LayoutElement layoutElement; public float AspectRatio { get { return aspectRatio; } set { aspectRatio = value; isDirty = true; } } public bool UpdateMin { get { return updateMin; } set { updateMin = value; isDirty = true; } } public bool UpdatePreferred { get { return updatePreferred; } set { updatePreferred = value; isDirty = true; } } private void OnEnable() { transform = GetComponent(); layoutElement = GetComponent(); isDirty = true; } private void Update() { Vector2 parentSize = GetParentSize(); // Mark as dirty if parent's size changes if (lastParentSize != parentSize) { lastParentSize = parentSize; isDirty = true; } // Only recalculate layout size if something has changed if (!isDirty) return; isDirty = false; float neededWidth = parentSize.y * aspectRatio; float neededHeight = parentSize.x / aspectRatio; // Is height the limiting factor? if (neededWidth <= parentSize.x) { // Scale to match parent's height SetSizes(neededWidth, parentSize.y); } else { // Scale to match parent's width SetSizes(parentSize.x, neededHeight); } } #if UNITY_EDITOR private void OnValidate() { // Inspector fields have changed, mark as dirty isDirty = true; } #endif private void SetSizes(float x, float y) { if (updateMin) { layoutElement.minWidth = x; layoutElement.minHeight = y; } if (updatePreferred) { layoutElement.preferredWidth = x; layoutElement.preferredHeight = y; } } private Vector2 GetParentSize() { var parent = transform.parent as RectTransform; return parent == null ? Vector2.zero : parent.rect.size; } }