107 lines
3.7 KiB
C#
107 lines
3.7 KiB
C#
using UnityEngine;
|
|
using Unheimlich.Features.Portals;
|
|
|
|
namespace Unheimlich.World.CameraSystem
|
|
{
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
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 Awake()
|
|
{
|
|
_playerTransform = Camera.main != null ? Camera.main.transform : null;
|
|
}
|
|
|
|
private void Start()
|
|
{
|
|
_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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks if any active portal with a loaded room is within range.
|
|
/// If found, extends shadow distance to cover the remote room.
|
|
/// </summary>
|
|
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
|
|
}
|
|
}
|