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 _childGroups = new List(); 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(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); // 플레이어를 따라다니는 빨간 원 } } }