using System.Collections.Generic;
using UnityEngine;
namespace Colosseum.Player
{
///
/// 카메라와 타겟 사이의 장애물을 숨기는 컨트롤러
///
public class ObstacleTransparencyController : MonoBehaviour
{
[Header("Occlusion Settings")]
[Min(0.01f)] [SerializeField] private float checkRadius = 0.3f;
private Transform cameraTransform;
private Transform targetTransform;
private LayerMask occlusionMask;
private readonly HashSet hiddenRenderers = new();
public void Initialize(Transform target, LayerMask mask)
{
cameraTransform = GetComponent().transform;
targetTransform = target;
occlusionMask = mask;
}
private void LateUpdate()
{
if (cameraTransform == null || targetTransform == null) return;
Vector3 origin = cameraTransform.position;
Vector3 direction = targetTransform.position - origin;
float maxDistance = direction.magnitude;
if (maxDistance < 0.01f) return;
direction.Normalize();
HashSet currentHits = CollectHits(origin, direction, maxDistance);
foreach (Renderer renderer in currentHits)
{
if (!hiddenRenderers.Contains(renderer))
{
renderer.enabled = false;
hiddenRenderers.Add(renderer);
}
}
List toShow = null;
foreach (Renderer renderer in hiddenRenderers)
{
if (renderer == null || !currentHits.Contains(renderer))
{
if (renderer != null)
renderer.enabled = true;
(toShow ??= new List()).Add(renderer);
}
}
if (toShow != null)
{
foreach (Renderer renderer in toShow)
hiddenRenderers.Remove(renderer);
}
}
private HashSet CollectHits(Vector3 origin, Vector3 direction, float maxDistance)
{
var hits = new HashSet();
RaycastHit[] rayHits = Physics.SphereCastAll(origin, checkRadius, direction, maxDistance, occlusionMask, QueryTriggerInteraction.Ignore);
float targetY = targetTransform.position.y;
foreach (RaycastHit hit in rayHits)
{
if (hit.point.y <= targetY) continue;
Renderer renderer = hit.collider.GetComponent();
if (renderer == null) continue;
if (renderer is ParticleSystemRenderer || renderer is TrailRenderer) continue;
hits.Add(renderer);
}
return hits;
}
public void ClearHidden()
{
foreach (Renderer renderer in hiddenRenderers)
{
if (renderer != null)
renderer.enabled = true;
}
hiddenRenderers.Clear();
}
private void OnDestroy()
{
ClearHidden();
}
}
}