SummerGame/Assets/Scripts/RoomVisibilityController.cs

115 lines
3.9 KiB
C#

using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class PillarData
{
public GameObject pillarObject;
public GameObject connectedWall1;
public GameObject connectedWall2;
}
public class RoomVisibilityController : MonoBehaviour
{
[Header("Центр комнаты")]
public Transform roomCenter;
[Header("Стены (Просто перетащите 4 стены)")]
public GameObject[] walls;
[Header("Столбики")]
public PillarData[] pillars;
[Header("Настройки видимости")]
[Range(-0.5f, 0.5f)]
public float hideThreshold = 0.1f;
private Camera _mainCamera;
private Dictionary<GameObject, bool> _wallHiddenStates = new Dictionary<GameObject, bool>();
// Кэшируем Renderer'ы для оптимизации (чтобы не делать GetComponent каждый кадр)
private Dictionary<GameObject, Renderer[]> _objectRenderers = new Dictionary<GameObject, Renderer[]>();
void Start()
{
_mainCamera = Camera.main;
// При старте игры находим и запоминаем все Renderer'ы
foreach (var wall in walls) { CacheRenderers(wall); }
foreach (var pillar in pillars) { CacheRenderers(pillar.pillarObject); }
}
private void CacheRenderers(GameObject obj)
{
if (obj != null && !_objectRenderers.ContainsKey(obj))
{
_objectRenderers[obj] = obj.GetComponentsInChildren<Renderer>();
}
}
void LateUpdate()
{
if (_mainCamera == null || roomCenter == null) return;
Vector3 dirToCamera = _mainCamera.transform.position - roomCenter.position;
dirToCamera.y = 0; // Игнорируем высоту
// 1. СТЕНЫ
foreach (var wall in walls)
{
if (wall == null) continue;
Vector3 targetPos = GetRealCenter(wall);
Vector3 dirToWall = targetPos - roomCenter.position;
dirToWall.y = 0;
bool isHidden = Vector3.Dot(dirToCamera.normalized, dirToWall.normalized) > hideThreshold;
// Включаем или выключаем графику стены моментально
SetVisibility(wall, !isHidden);
_wallHiddenStates[wall] = isHidden;
Debug.DrawLine(roomCenter.position, targetPos, isHidden ? Color.red : Color.green);
}
// 2. СТОЛБИКИ
foreach (var pillar in pillars)
{
if (pillar.pillarObject == null || pillar.connectedWall1 == null || pillar.connectedWall2 == null)
continue;
bool isWall1Hidden = _wallHiddenStates.ContainsKey(pillar.connectedWall1) && _wallHiddenStates[pillar.connectedWall1];
bool isWall2Hidden = _wallHiddenStates.ContainsKey(pillar.connectedWall2) && _wallHiddenStates[pillar.connectedWall2];
// Прячем столбик только если ОБЕ подключенные стены спрятаны
bool shouldHidePillar = isWall1Hidden && isWall2Hidden;
SetVisibility(pillar.pillarObject, !shouldHidePillar);
}
}
// Метод для быстрого включения/выключения отрисовки объекта
private void SetVisibility(GameObject obj, bool isVisible)
{
if (obj == null || !_objectRenderers.ContainsKey(obj)) return;
Renderer[] renderers = _objectRenderers[obj];
foreach (Renderer r in renderers)
{
if (r.enabled != isVisible)
{
r.enabled = isVisible;
}
}
}
private Vector3 GetRealCenter(GameObject obj)
{
Renderer r = obj.GetComponentInChildren<Renderer>();
if (r != null)
{
return r.bounds.center;
}
return obj.transform.position;
}
}