using UnityEngine; using Unheimlich.Gameplay.Portals; namespace Unheimlich.Managers { /// /// Dynamically adjusts Unity's shadow rendering distance based on proximity to active portals. /// When the player is near a portal with a loaded room, shadow distance is extended to ensure /// shadows from the remote room are visible through the portal. This improves visual quality /// while maintaining performance when far from portals. /// public class DynamicShadowDistance : MonoBehaviour { private const float PORTAL_CHECK_DISTANCE = 100f; [Header("Shadow Distance Settings")] [SerializeField] private float _baseShadowDistance = 50f; [SerializeField] private float _extendedShadowDistance = 250f; [SerializeField] private float _transitionSpeed = 2f; [Header("Detection")] [SerializeField] private float _checkInterval = 0.5f; private float _targetShadowDistance; private float _currentShadowDistance; private float _nextCheckTime; private Transform _playerTransform; private void Start() { _playerTransform = Camera.main.transform; _currentShadowDistance = _baseShadowDistance; _targetShadowDistance = _baseShadowDistance; QualitySettings.shadowDistance = _baseShadowDistance; } private void Update() { if (Time.time >= _nextCheckTime) { _nextCheckTime = Time.time + _checkInterval; UpdateTargetShadowDistance(); } if (!Mathf.Approximately(_currentShadowDistance, _targetShadowDistance)) { _currentShadowDistance = Mathf.Lerp(_currentShadowDistance, _targetShadowDistance, Time.deltaTime * _transitionSpeed); QualitySettings.shadowDistance = _currentShadowDistance; } } /// /// Checks if any active portal with a loaded room is within range. /// If found, extends shadow distance to cover the remote room. /// private void UpdateTargetShadowDistance() { bool needsExtendedDistance = false; foreach (var portal in Portal.AllPortals) { if (portal == null || !portal.isActiveAndEnabled) continue; if (portal.LoadedRoomInstance != null) { float distanceToPortal = Vector3.Distance(_playerTransform.position, portal.transform.position); if (distanceToPortal < PORTAL_CHECK_DISTANCE) { needsExtendedDistance = true; break; } } } _targetShadowDistance = needsExtendedDistance ? _extendedShadowDistance : _baseShadowDistance; } private void OnValidate() { if (_baseShadowDistance < 0) _baseShadowDistance = 0; if (_extendedShadowDistance < _baseShadowDistance) _extendedShadowDistance = _baseShadowDistance; } #if UNITY_EDITOR private void OnDrawGizmosSelected() { if (_playerTransform == null) return; Gizmos.color = new Color(1f, 1f, 0f, 0.2f); Gizmos.DrawWireSphere(_playerTransform.position, QualitySettings.shadowDistance); UnityEditor.Handles.Label(_playerTransform.position + Vector3.up * 2, $"Shadow Distance: {QualitySettings.shadowDistance:F0}"); } #endif } }