using UnityEngine; // Подгоняет RectTransform под безопасную зону экрана (Screen.safeArea): вырез камеры, скруглённые углы, // полоска "домой" на iPhone. Следит за поворотом и сменой разрешения (и в Device Simulator). // Вешать на растянутый объект; всё, что внутри, не залезет под вырез. // - fitInsideParent = false: объект растянут на весь Canvas (HUD); // - fitInsideParent = true: родитель не на весь экран (окно между верхней и нижней панелью) -- // зона пересчитывается в координаты родителя, отступ появляется только там, где родитель заходит под вырез. [RequireComponent(typeof(RectTransform))] public class SafeArea : MonoBehaviour { public bool fitInsideParent; private RectTransform rect; private Rect appliedArea; private Vector2Int appliedScreen; private Rect appliedParent; void Awake() { rect = GetComponent(); Apply(); } void Update() { if (Screen.safeArea != appliedArea || Screen.width != appliedScreen.x || Screen.height != appliedScreen.y || (fitInsideParent && ParentScreenRect() != appliedParent)) Apply(); } void Apply() { Rect area = Screen.safeArea; appliedArea = area; appliedScreen = new Vector2Int(Screen.width, Screen.height); if (Screen.width <= 0 || Screen.height <= 0) return; if (!fitInsideParent) { // Якоря в долях экрана: Canvas в режиме Screen Space Overlay покрывает экран целиком rect.anchorMin = new Vector2(area.xMin / Screen.width, area.yMin / Screen.height); rect.anchorMax = new Vector2(area.xMax / Screen.width, area.yMax / Screen.height); } else { Rect parent = ParentScreenRect(); appliedParent = parent; if (parent.width <= 0 || parent.height <= 0) return; // Пересечение родителя с безопасной зоной -- в долях родителя float xMin = Mathf.Max(parent.xMin, area.xMin), xMax = Mathf.Min(parent.xMax, area.xMax); float yMin = Mathf.Max(parent.yMin, area.yMin), yMax = Mathf.Min(parent.yMax, area.yMax); if (xMax <= xMin || yMax <= yMin) return; rect.anchorMin = new Vector2((xMin - parent.xMin) / parent.width, (yMin - parent.yMin) / parent.height); rect.anchorMax = new Vector2((xMax - parent.xMin) / parent.width, (yMax - parent.yMin) / parent.height); } rect.offsetMin = Vector2.zero; rect.offsetMax = Vector2.zero; } // Прямоугольник родителя в пикселях экрана Rect ParentScreenRect() { var parent = transform.parent as RectTransform; if (parent == null) return new Rect(0, 0, Screen.width, Screen.height); var corners = new Vector3[4]; parent.GetWorldCorners(corners); Canvas canvas = parent.GetComponentInParent(); Camera cam = canvas != null && canvas.renderMode != RenderMode.ScreenSpaceOverlay ? canvas.worldCamera : null; Vector2 min = RectTransformUtility.WorldToScreenPoint(cam, corners[0]); Vector2 max = RectTransformUtility.WorldToScreenPoint(cam, corners[2]); return Rect.MinMaxRect(min.x, min.y, max.x, max.y); } }