using System; using System.Collections; using System.Collections.Generic; using Pathfinding; using UnityEngine; using UnityEngine.Localization.Settings; using UnityEngine.Localization.Tables; using UnityEngine.ResourceManagement.AsyncOperations; using Random = UnityEngine.Random; namespace BlueWater.Utility { public static class Utils { public static IEnumerator CoolDownCoroutine(float waitTime, Action onCooldownComplete = null) { yield return new WaitForSeconds(waitTime); onCooldownComplete?.Invoke(); } public static void StartUniqueCoroutine(MonoBehaviour owner, ref Coroutine coroutineField, IEnumerator coroutineMethod) { if (coroutineField != null) { owner.StopCoroutine(coroutineField); coroutineField = null; } coroutineField = owner.StartCoroutine(coroutineMethod); } public static void EndUniqueCoroutine(MonoBehaviour owner, ref Coroutine coroutineField) { if (coroutineField != null) { owner.StopCoroutine(coroutineField); coroutineField = null; } } public static void RegisterList(List list, T item) { if (list.Contains(item)) { Debug.Log($"{item}은 이미 {list}안에 등록되어 있습니다."); return; } list.Add(item); } public static void UnregisterList(List list, T item) { if (!list.Contains(item)) { Debug.Log($"{item}은 {list}안에 없습니다."); return; } list.Remove(item); } public static Vector3 RandomPositionOnGraph(int graphIndex = 0, float radius = 0.5f) { // 그래프 인덱스가 유효한지 검사 if (graphIndex < 0 || graphIndex >= AstarPath.active.data.graphs.Length) { throw new Exception("유효하지 않은 그래프 인덱스입니다."); } // 특정 그래프를 가져와 모든 walkable 노드를 수집 List walkableNodes = new List(); NavGraph graph = AstarPath.active.data.graphs[graphIndex]; graph.GetNodes(node => { if (node.Walkable) { walkableNodes.Add(node); } return true; // 모든 노드를 반복하도록 true 반환 }); // walkable한 노드가 없을 경우 Vector3.zero 반환 if (walkableNodes.Count == 0) { throw new Exception("이동 가능한 노드가 없습니다."); } LayerMask propsLayerMask = LayerMask.GetMask("Props"); // 반복적으로 랜덤 위치를 가져와 조건을 만족하는지 확인 for (int attempt = 0; attempt < 100000; attempt++) { // walkable한 노드 중 하나를 무작위로 선택 GraphNode randomNode = walkableNodes[Random.Range(0, walkableNodes.Count)]; // 선택한 노드의 위치를 Vector3로 변환 Vector3 randomPosition = (Vector3)randomNode.position; // 반경과 Props 레이어가 설정되어 있다면 검사 if (radius > 0) { // 반경 내 Props 레이어 오브젝트가 있는지 검사 Collider[] results = new Collider[1]; var size = Physics.OverlapSphereNonAlloc(randomPosition, radius, results, propsLayerMask, QueryTriggerInteraction.Collide); // Props가 발견되면 다시 시도 if (size > 0) { continue; } } // 조건을 만족하면 위치 반환 return randomPosition; } // 반복 시도 후에도 유효한 위치를 찾지 못한 경우 예외 처리 throw new Exception("조건을 만족하는 유효한 위치를 찾지 못했습니다."); } public static string GetLocalizedString(string key) { return LocalizationSettings.StringDatabase.GetLocalizedString("StringDataTable", key, LocalizationSettings.SelectedLocale); } public static AsyncOperationHandle GetTableAsync() { return LocalizationSettings.StringDatabase.GetTableAsync("StringDataTable"); } } }