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 _wallHiddenStates = new Dictionary(); // Кэшируем Renderer'ы для оптимизации (чтобы не делать GetComponent каждый кадр) private Dictionary _objectRenderers = new Dictionary(); 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(); } } 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(); if (r != null) { return r.bounds.center; } return obj.transform.position; } }