131 lines
7.2 KiB
C#
131 lines
7.2 KiB
C#
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
|
|
// Отвязывает HUD от камеры и ставит одну нормальную камеру.
|
|
//
|
|
// Было: HUD_Canvas в режиме World Space был дочерним объектом камеры, а CameraZoom масштабировал
|
|
// саму камеру, чтобы HUD не уменьшался при зуме. Поэтому HUD ехал, дрожал и масштабировался криво.
|
|
// Стало: HUD_Canvas -- Screen Space Overlay (всегда приклеен к экрану, камера на него не влияет),
|
|
// на камере -- только CityCamera (перетаскивание, щипок, колёсико, границы карты).
|
|
//
|
|
// Работает в двух местах:
|
|
// - при запуске игры (автоматически), если сцену ещё не исправили в редакторе;
|
|
// - Tools -> Fix Camera & HUD (или Build HUD Panels) -- исправляет и сохраняет сцену навсегда.
|
|
public static class HUDCameraSetup
|
|
{
|
|
// ОТКЛЮЧЕНО по просьбе команды: камера и HUD вернулись к прежней схеме (Tools -> Restore Old Camera & HUD).
|
|
// Автоисправление при запуске больше не выполняется.
|
|
static void AutoFix()
|
|
{
|
|
// и при каждой следующей загрузке города (возврат с карты мира)
|
|
UnityEngine.SceneManagement.SceneManager.sceneLoaded += (s, m) => Apply(false);
|
|
|
|
int changes = Apply(false);
|
|
if (changes > 0)
|
|
Debug.Log("[КАМЕРА/HUD] Исправлено при запуске: " + changes +
|
|
". Чтобы сохранить в сцене навсегда -- Tools -> Fix Camera & HUD");
|
|
}
|
|
|
|
// editMode = true -- вызывается из редактора: лишние компоненты удаляются, а не выключаются
|
|
public static int Apply(bool editMode)
|
|
{
|
|
int changes = 0;
|
|
|
|
// ---------- HUD ----------
|
|
var hudGO = GameObject.Find("HUD_Canvas");
|
|
if (hudGO != null)
|
|
{
|
|
var canvas = hudGO.GetComponent<Canvas>();
|
|
var rt = (RectTransform)hudGO.transform;
|
|
if (canvas != null && canvas.renderMode != RenderMode.ScreenSpaceOverlay)
|
|
{
|
|
Vector2 designSize = rt.sizeDelta; // размер, под который дизайнер расставил HUD
|
|
if (designSize.x < 100 || designSize.y < 100) designSize = new Vector2(1080, 1920);
|
|
|
|
if (hudGO.transform.parent != null) hudGO.transform.SetParent(null, false);
|
|
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
|
canvas.sortingOrder = 100;
|
|
rt.localScale = Vector3.one;
|
|
rt.localRotation = Quaternion.identity;
|
|
|
|
var scaler = hudGO.GetComponent<CanvasScaler>();
|
|
if (scaler == null) scaler = hudGO.AddComponent<CanvasScaler>();
|
|
scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
|
|
scaler.referenceResolution = designSize; // HUD выглядит так же, как его собрал дизайнер
|
|
scaler.screenMatchMode = CanvasScaler.ScreenMatchMode.MatchWidthOrHeight;
|
|
scaler.matchWidthOrHeight = 1f; // как было в мире: высота HUD = высота экрана
|
|
changes++;
|
|
}
|
|
// высота HUD = высота экрана (так HUD выглядел, пока был привязан к камере)
|
|
var sc = hudGO.GetComponent<CanvasScaler>();
|
|
if (sc != null && canvas != null && canvas.renderMode == RenderMode.ScreenSpaceOverlay && sc.matchWidthOrHeight != 1f)
|
|
{ sc.matchWidthOrHeight = 1f; changes++; }
|
|
changes += ConvertSpritesToImages(hudGO, editMode);
|
|
changes += RemoveOrDisable(hudGO, "HUDWorldSpaceSync", editMode);
|
|
}
|
|
|
|
// ---------- КАМЕРА ----------
|
|
var cam = Camera.main;
|
|
if (cam != null)
|
|
{
|
|
changes += RemoveOrDisable(cam.gameObject, "CameraZoom", editMode);
|
|
changes += RemoveOrDisable(cam.gameObject, "CameraController", editMode);
|
|
changes += RemoveOrDisable(cam.gameObject, "FlyCamera", editMode);
|
|
if (cam.transform.localScale != Vector3.one) { cam.transform.localScale = Vector3.one; changes++; }
|
|
if (cam.transform.rotation != Quaternion.identity) { cam.transform.rotation = Quaternion.identity; changes++; }
|
|
if (cam.GetComponent<CityCamera>() == null) { cam.gameObject.AddComponent<CityCamera>(); changes++; }
|
|
}
|
|
return changes;
|
|
}
|
|
|
|
// В экранном Canvas обычные SpriteRenderer не рисуются как часть интерфейса -- они улетают в мир
|
|
// огромными картинками (отсюда белая "клетка" на весь экран). Переделываем их в UI Image того же размера.
|
|
static int ConvertSpritesToImages(GameObject hud, bool editMode)
|
|
{
|
|
int n = 0;
|
|
foreach (var sr in hud.GetComponentsInChildren<SpriteRenderer>(true))
|
|
{
|
|
if (sr.sprite == null) { sr.enabled = false; continue; }
|
|
var t = sr.transform;
|
|
var parent = t.parent as RectTransform;
|
|
if (parent == null) { sr.enabled = false; continue; }
|
|
|
|
var go = new GameObject(t.name + "_UI", typeof(RectTransform), typeof(Image));
|
|
var rt = (RectTransform)go.transform;
|
|
rt.SetParent(parent, false);
|
|
rt.SetSiblingIndex(t.GetSiblingIndex());
|
|
rt.anchorMin = rt.anchorMax = parent.pivot; // localPosition считается от pivot родителя
|
|
rt.pivot = new Vector2(0.5f, 0.5f);
|
|
Vector2 size = Vector2.Scale(sr.sprite.bounds.size, new Vector2(Mathf.Abs(t.localScale.x), Mathf.Abs(t.localScale.y)));
|
|
rt.sizeDelta = size;
|
|
rt.localPosition = t.localPosition + (Vector3)Vector2.Scale(sr.sprite.bounds.center, t.localScale);
|
|
rt.localRotation = t.localRotation;
|
|
var img = go.GetComponent<Image>();
|
|
img.sprite = sr.sprite;
|
|
img.color = sr.color;
|
|
img.raycastTarget = false;
|
|
img.preserveAspect = false;
|
|
|
|
if (editMode) Object.DestroyImmediate(t.gameObject);
|
|
else t.gameObject.SetActive(false);
|
|
n++;
|
|
}
|
|
return n;
|
|
}
|
|
|
|
// Компоненты ищем по имени класса: часть из них (FlyCamera, HUDWorldSpaceSync) в проекте уже нет
|
|
static int RemoveOrDisable(GameObject go, string typeName, bool editMode)
|
|
{
|
|
int n = 0;
|
|
foreach (var mb in go.GetComponents<MonoBehaviour>())
|
|
{
|
|
if (mb == null || mb.GetType().Name != typeName) continue;
|
|
if (editMode) Object.DestroyImmediate(mb);
|
|
else if (mb.enabled) mb.enabled = false;
|
|
else continue;
|
|
n++;
|
|
}
|
|
return n;
|
|
}
|
|
}
|