Projext/Assets/Scripts/Systems/Optimization/Player Render Manager.cs
2026-02-02 17:30:23 +09:00

77 lines
2.6 KiB
C#

using UnityEngine;
using System.Collections.Generic;
public class PlayerRangeManager : MonoBehaviour
{
[Header("--- 대상 설정 ---")]
[SerializeField] private Transform environmentParent; // 맵 오브젝트 부모 폴더
[Header("--- 최적화 설정 ---")]
[SerializeField] private float renderRange = 40f; // ⭐ 반드시 30~50 사이로 키워주세요!
[SerializeField] private float checkInterval = 0.2f;
private struct RenderGroup
{
public Vector3 actualCenter; // ⭐ 피벗이 아닌 실제 메쉬의 중심점
public Renderer[] renderers;
}
private List<RenderGroup> _childGroups = new List<RenderGroup>();
private Transform _player;
private void Start()
{
// 태그로 플레이어를 정확히 찾습니다.
GameObject playerObj = GameObject.FindGameObjectWithTag("Player");
if (playerObj != null) _player = playerObj.transform;
else _player = transform;
if (environmentParent != null) RefreshChildList();
InvokeRepeating(nameof(UpdateCulling), 0f, checkInterval);
}
public void RefreshChildList()
{
if (environmentParent == null) return;
_childGroups.Clear();
foreach (Transform child in environmentParent)
{
Renderer[] rs = child.GetComponentsInChildren<Renderer>(true);
if (rs.Length > 0)
{
// ⭐ [수정] 피벗(position)이 아니라, 실제 모델링의 중심(bounds.center)을 가져옵니다.
// 이래야 "가까이 갔는데 꺼지는" 현상이 완벽히 해결됩니다!
Vector3 center = rs[0].bounds.center;
_childGroups.Add(new RenderGroup { actualCenter = center, renderers = rs });
}
}
}
private void UpdateCulling()
{
if (_player == null) return;
Vector3 playerPos = _player.position;
foreach (var group in _childGroups)
{
// ⭐ [핵심] 실제 몸통 중심점과의 거리를 계산합니다.
float dist = Vector3.Distance(playerPos, group.actualCenter);
bool shouldShow = dist <= renderRange;
foreach (Renderer r in group.renderers)
{
if (r != null && r.enabled != shouldShow) r.enabled = shouldShow;
}
}
}
private void OnDrawGizmos()
{
if (_player != null)
{
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(_player.position, renderRange); // 플레이어를 따라다니는 빨간 원
}
}
}