135 lines
4.7 KiB
C#
135 lines
4.7 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using Unity.VisualScripting;
|
|
using UnityEngine;
|
|
|
|
namespace Animation
|
|
{
|
|
// 제네릭인 P 는 값 형식이면서 Enum을 상속한 타입이어야 한다.
|
|
public class AnimatorManager<P> where P : struct, Enum
|
|
{
|
|
private readonly Animator animator;
|
|
|
|
// 마지막 세팅 값을 저장해 불필요한 동작 방지용
|
|
private readonly Dictionary<P, object> cache = new();
|
|
|
|
// 키별 실제 타입을 매핑해두는 용도
|
|
private readonly Dictionary<P, AnimatorControllerParameterType> types = new();
|
|
|
|
// 없는 키를 경고하기 위한 용도 (Enum에는 있는데 Animator에는 없는 경우)
|
|
private readonly HashSet<P> missing = new();
|
|
|
|
// 없는 키를 경고하기 위한 용도 (Animator에는 있는데 Enum에는 없는 경우)
|
|
private readonly HashSet<string> 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<P>(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");
|
|
}
|
|
}
|
|
}
|
|
|
|
} |