Files
MVP1/Assets/Scripts/UI/SafeAreaInstaller.cs
AlexanderandClaude Opus 5.5 57fc7e0006 HUD учитывает Safe Area (вырез, скругления, полоска «домой»)
- UI/SafeArea: подгоняет контейнер под Screen.safeArea, следит за поворотом
- UI/SafeAreaInstaller: при загрузке сцены переносит элементы HUD_Canvas и
  WorldMap_Canvas в контейнер SafeArea; окна на весь экран остаются на весь экран

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 18:41:43 +02:00

65 lines
3.0 KiB
C#

using UnityEngine;
using UnityEngine.SceneManagement;
// Сам ставит Safe Area на экранные Canvas при загрузке каждой сцены (город, карта мира).
// Руками в сцене ничего делать не нужно, и пересборка HUD через Tools не сломает настройку.
//
// Правило: всё, что растянуто на весь экран (фоны и окна поверх игры: BuildMenuPanel, Panels),
// остаётся на весь экран. Остальные элементы (верхняя и нижняя панели, кнопки по краям, чат, окна
// по центру) переезжают в контейнер "SafeArea" и не залезают под вырез и скругления экрана.
public static class SafeAreaInstaller
{
const string ContainerName = "SafeArea";
// Canvas, которые подгоняются под безопасную зону
static readonly string[] CanvasNames = { "HUD_Canvas", "WorldMap_Canvas" };
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)]
static void Init()
{
InstallAll();
SceneManager.sceneLoaded += (scene, mode) => InstallAll();
}
static void InstallAll()
{
foreach (var name in CanvasNames)
{
var go = GameObject.Find(name);
if (go != null) Install(go.GetComponent<RectTransform>());
}
}
public static void Install(RectTransform canvasRect)
{
if (canvasRect == null || canvasRect.Find(ContainerName) != null) return;
var container = new GameObject(ContainerName, typeof(RectTransform)).GetComponent<RectTransform>();
container.SetParent(canvasRect, false);
container.anchorMin = Vector2.zero;
container.anchorMax = Vector2.one;
container.offsetMin = Vector2.zero;
container.offsetMax = Vector2.zero;
// Контейнер -- первым: окна на весь экран остаются поверх HUD
container.SetSiblingIndex(0);
// Пока контейнер совпадает с Canvas, перенос сохраняет раскладку один в один
for (int i = canvasRect.childCount - 1; i >= 0; i--)
{
var child = canvasRect.GetChild(i) as RectTransform;
if (child == null || child == container || IsFullScreen(child)) continue;
child.SetParent(container, false);
child.SetSiblingIndex(0); // обход с конца -- порядок отрисовки сохраняется
}
container.gameObject.AddComponent<SafeArea>(); // а теперь сжимаем под безопасную зону
}
// Растянут на весь экран без отступов -- это фон или окно поверх игры
static bool IsFullScreen(RectTransform rt)
{
return rt.anchorMin == Vector2.zero && rt.anchorMax == Vector2.one;
}
}