feat: 카메라-플레이어 사이 장애물 숨김 처리
- SphereCast 충돌 당기기 로직 제거로 카메라가 항상 원래 거리 유지 - ObstacleTransparencyController 신규: 카메라-타겟 사이 장애물을 renderer.enabled로 숨김 - 플레이어 발 위치 이하의 바닥/지형은 숨김 대상에서 제외 - 파티클/트레일 렌더러는 숨김 스킵 Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
105
Assets/_Game/Scripts/Player/ObstacleTransparencyController.cs
Normal file
105
Assets/_Game/Scripts/Player/ObstacleTransparencyController.cs
Normal file
@@ -0,0 +1,105 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace Colosseum.Player
|
||||
{
|
||||
/// <summary>
|
||||
/// 카메라와 타겟 사이의 장애물을 숨기는 컨트롤러
|
||||
/// </summary>
|
||||
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<Renderer> hiddenRenderers = new();
|
||||
|
||||
public void Initialize(Transform target, LayerMask mask)
|
||||
{
|
||||
cameraTransform = GetComponent<Camera>().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<Renderer> currentHits = CollectHits(origin, direction, maxDistance);
|
||||
|
||||
foreach (Renderer renderer in currentHits)
|
||||
{
|
||||
if (!hiddenRenderers.Contains(renderer))
|
||||
{
|
||||
renderer.enabled = false;
|
||||
hiddenRenderers.Add(renderer);
|
||||
}
|
||||
}
|
||||
|
||||
List<Renderer> toShow = null;
|
||||
foreach (Renderer renderer in hiddenRenderers)
|
||||
{
|
||||
if (renderer == null || !currentHits.Contains(renderer))
|
||||
{
|
||||
if (renderer != null)
|
||||
renderer.enabled = true;
|
||||
(toShow ??= new List<Renderer>()).Add(renderer);
|
||||
}
|
||||
}
|
||||
|
||||
if (toShow != null)
|
||||
{
|
||||
foreach (Renderer renderer in toShow)
|
||||
hiddenRenderers.Remove(renderer);
|
||||
}
|
||||
}
|
||||
|
||||
private HashSet<Renderer> CollectHits(Vector3 origin, Vector3 direction, float maxDistance)
|
||||
{
|
||||
var hits = new HashSet<Renderer>();
|
||||
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<Renderer>();
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user