using System; using System.Collections; using System.Diagnostics; using BehaviorDesigner.Runtime; using UnityEditor; using UnityEngine; using UnityEngine.AI; using UnityEngine.Assertions; using Debug = UnityEngine.Debug; using Object = UnityEngine.Object; using Random = UnityEngine.Random; // ReSharper disable once CheckNamespace namespace BlueWaterProject { public class Utils { public enum DebugType { NONE, LOG, WARNING, ERROR, DEBUG_ASSERT, ASSERT // } /// /// 각도를 통해 방향값을 반환하는 함수 /// public static Vector3 AngleToDir(float angle) { var radian = angle * Mathf.Deg2Rad; return new Vector3(Mathf.Sin(radian), 0f, Mathf.Cos(radian)).normalized; } // public static T FindTaskAndAssert(BehaviorTree behaviorTree) where T : Task // { // var newBehaviorTask = behaviorTree.FindTask(); // Assert.IsNotNull(newBehaviorTask, typeof(T) + "타입의 Task가 존재하지 않습니다."); // // return newBehaviorTask; // } public static T GetComponentAndAssert(Transform componentLocation, DebugType debugType = DebugType.DEBUG_ASSERT) where T : class { var newComponent = componentLocation.GetComponent(); switch (debugType) { case DebugType.NONE: Debug.Log("DebugType is None."); break; case DebugType.LOG: Debug.Log(typeof(T) + "타입의 Component가 존재하지 않습니다."); break; case DebugType.WARNING: Debug.LogWarning(typeof(T) + "타입의 Component가 존재하지 않습니다."); break; case DebugType.ERROR: Debug.LogError(typeof(T) + "타입의 Component가 존재하지 않습니다."); break; case DebugType.DEBUG_ASSERT: Debug.Assert(newComponent != null, typeof(T) + "타입의 Component가 존재하지 않습니다."); break; case DebugType.ASSERT: Assert.IsNotNull(newComponent, typeof(T) + "타입의 Component가 존재하지 않습니다."); break; default: throw new ArgumentOutOfRangeException(nameof(debugType), debugType, null); } return newComponent; } public static bool ArrivedAgentDestination(NavMeshAgent agent) => !agent.pathPending && agent.remainingDistance <= agent.stoppingDistance; /// /// 메서드를 누가 호출하는지 알려주는 메서드입니다 /// 메서드 마지막에 이 함수를 호출하면 됩니다 /// public static void WhereCallThisFunction() { var stackTrace = new StackTrace(); var stackFrame = stackTrace.GetFrame(1); var method = stackFrame.GetMethod(); var className = method.DeclaringType?.Name; var methodName = method.Name; UnityEngine.Debug.Log($"Call {className}.{methodName}"); } /// /// waitTime만큼 기다렸다가 완료되었을 때, onCooldownComplete 행동을 하는 코루틴 함수 /// /// 기다리는 시간 /// 완료되었을 때, 실행할 행동 /// public static IEnumerator CoolDown(float waitTime, Action onCooldownComplete = null) { var time = 0f; while (time <= waitTime) { time += Time.deltaTime; yield return null; } onCooldownComplete?.Invoke(); } /// /// eulerAngles값은 음수가아닌 0 ~ 360값으로 나오기 때문에 -180 ~ 180값으로 정규화 해주는 함수 /// public static float NormalizeEulerAngle(float eulerAngle) { while (eulerAngle > 180) eulerAngle -= 360; while (eulerAngle < -180) eulerAngle += 360; return eulerAngle; } public static bool SetCloseDestination(NavMeshAgent agent, Vector3 destination, float stopDistance, float maxDistance) { var walkableMask = 1 << NavMesh.GetAreaFromName("Walkable"); if (NavMesh.SamplePosition(destination, out var hit, maxDistance, walkableMask)) { agent.stoppingDistance = stopDistance; agent.SetDestination(hit.position); return true; // var path = new NavMeshPath(); // if (agent.CalculatePath(hit.position, path) && path.status == NavMeshPathStatus.PathComplete) // { // agent.stoppingDistance = stopDistance; // agent.SetDestination(hit.position); // return true; // } // // Debug.Log("길이 연결되어 있지 않습니다."); // return false; } Debug.Log("근처에 갈 수 있는 위치가 없습니다."); return false; } public static void SetBehaviorVariable(Behavior behaviorTreeComponent, string behaviorVariableName, T value) { var sharedVariable = behaviorTreeComponent.GetVariable(behaviorVariableName); sharedVariable?.SetValue(value); } #if UNITY_EDITOR public static T LoadFromFolder(string folderPath, string name, string extension) where T : Object { var fullPath = System.IO.Path.Combine(folderPath, name + extension); var t = AssetDatabase.LoadAssetAtPath(fullPath); return t; } #endif } }