using System; using System.Collections.Generic; using Unity.VisualScripting; using UnityEngine; namespace Animation { // 제네릭인 P 는 값 형식이면서 Enum을 상속한 타입이어야 한다. public class AnimatorManager

where P : struct, Enum { private readonly Animator animator; // 마지막 세팅 값을 저장해 불필요한 동작 방지용 private readonly Dictionary cache = new(); // 키별 실제 타입을 매핑해두는 용도 private readonly Dictionary types = new(); // 없는 키를 경고하기 위한 용도 (Enum에는 있는데 Animator에는 없는 경우) private readonly HashSet

missing = new(); // 없는 키를 경고하기 위한 용도 (Animator에는 있는데 Enum에는 없는 경우) private readonly HashSet extras = new(); public AnimatorManager(Animator animator) { this.animator = animator; if (this.animator == null) return; cache.Clear(); types.Clear(); missing.Clear(); extras.Clear(); var parameters = animator.parameters; foreach (var param in parameters) { if (Enum.TryParse

(param.name, out var key)) { types[key] = param.type; switch (param.type) { case AnimatorControllerParameterType.Bool: cache[key] = animator.GetBool(param.name); break; case AnimatorControllerParameterType.Float: cache[key] = animator.GetFloat(param.name); break; case AnimatorControllerParameterType.Int: cache[key] = animator.GetInteger(param.name); break; } } else { extras.Add(param.name); } } foreach (P enumKey in (P[])Enum.GetValues(typeof(P))) { if (!types.ContainsKey(enumKey)) missing.Add(enumKey); } } public void SetValue(P key, object value) { if (animator == null) throw new InvalidOperationException("Animator is null"); // missing은 가능하나 extras는 불가능(변수가 P 로 들어오기에 Animator에는 있는데 Enum에 없는 경우는 불가능) if (missing.Contains(key)) throw new KeyNotFoundException("key is missing in animator: " + key); string name = key.ToString(); switch (types[key]) { case AnimatorControllerParameterType.Bool: { var newVal = Convert.ToBoolean(value); if (!cache.TryGetValue(key, out var oldVal) || !Equals(newVal, (bool)oldVal)) { animator.SetBool(name, newVal); cache[key] = newVal; } break; } case AnimatorControllerParameterType.Float: { var newVal = Convert.ToSingle(value); if (!cache.TryGetValue(key, out var oldVal) || !Mathf.Approximately(newVal, (float)oldVal)) { animator.SetFloat(name, newVal); cache[key] = newVal; } break; } case AnimatorControllerParameterType.Int: { var newVal = Convert.ToInt32(value); if (!cache.TryGetValue(key, out var oldVal) || !Equals(newVal, (int)oldVal)) { animator.SetInteger(name, newVal); cache[key] = newVal; } break; } case AnimatorControllerParameterType.Trigger: { var newVal = Convert.ToBoolean(value); if (newVal) animator.SetTrigger(name); else animator.ResetTrigger(name); break; } } } public object GetValue(P key) { if (types[key] != AnimatorControllerParameterType.Trigger) { return cache[key]; } else { throw new InvalidOperationException("Trigger type cannot be get"); } } } }