Quick Reference
Unity 6.5 기준입니다. Animator 파라미터는 Controller의 전이 조건을 코드와 연결하는 상태 값입니다. 이름과 타입은 Controller와 코드에서 정확히 같아야 하며, 전이가 파라미터를 어떻게 읽는지가 실제 결과를 결정합니다.
| 파라미터 | 기본값과 쓰임 | 코드에서 바꾸는 때 | 전이에서 읽는 방식 |
|---|---|---|---|
Bool | 기본 false. 이동 가능, 접지, 장비 장착처럼 유지되는 참/거짓 상태 | 상태가 바뀐 순간 또는 매 프레임 최신 상태가 필요할 때 | true 또는 false 조건 |
Float | 기본 0. 속도, 조준량, Blend Tree 축처럼 연속 값 | 입력과 속도 계산이 끝난 Update, 물리 속도는 FixedUpdate 뒤의 반영 지점 | 비교 조건 또는 Blend Tree 임계값 |
Int | 기본 0. 무기 종류, 행동 단계, 방향처럼 이산 값 | 값이 변경될 때 | 일치·대소 비교 조건 |
Trigger | 기본 미설정. 공격, 피격, 점프 시작처럼 한 번 요청하는 신호 | 입력 edge, 전투 이벤트처럼 한 번 발생할 때 | 조건을 만족하는 전이가 소비하면 해제됨 |
Trigger는 전이가 소비해야 사라집니다. 조건을 만족하는 전이가 없거나 전이 우선순위에 밀리면 다음 상태 변화까지 남을 수 있으므로, 취소·재입력 경로에서는 ResetTrigger를 명시적으로 고려합니다.
private static readonly int SpeedId = Animator.StringToHash("Speed");
private static readonly int GroundedId = Animator.StringToHash("Grounded");
private static readonly int AttackId = Animator.StringToHash("Attack");
[SerializeField] private Animator animator;
public void ApplyState(float inputMagnitude, bool isGrounded, bool attackPressed)
{
animator.SetFloat(SpeedId, inputMagnitude);
animator.SetBool(GroundedId, isGrounded);
if (attackPressed)
{
animator.ResetTrigger(AttackId); // 이전에 남은 요청을 취소해야 할 때만 사용
animator.SetTrigger(AttackId);
}
}Controller 설정
Parameters 목록
Animator Controller > Parameters에서 이름, 타입, 기본값을 만듭니다. 기본값은 Controller가 시작되거나 Animator.Rebind()로 상태를 다시 묶을 때의 출발값으로 보아야 합니다. 런타임 코드가 첫 프레임에 값을 덮어쓴다면 기본값이 화면에 드러나는 시간은 짧지만, 전이 진입 조건과 프리뷰에는 그대로 영향을 줍니다.
이름을 바꾸면 기존 코드의 문자열과 hash ID는 자동으로 바뀌지 않습니다. 파라미터를 제거하거나 타입을 바꾼 경우에는 모든 Transition 조건과 Set... 호출을 함께 점검합니다. 없는 이름을 넘긴 호출은 원하는 전이를 만들지 못하므로, 팀에서는 파라미터 이름을 hash ID로 한곳에 모아 관리하는 편이 안전합니다.
Transition Conditions
Transition의 Conditions는 현재 상태에서 다음 상태로 갈 수 있는 조건입니다. 여러 조건을 넣으면 모두 만족해야 합니다. 같은 상태에서 나가는 Transition이 여러 개라면 목록 순서와 Has Exit Time, 현재 파라미터 조합이 함께 결과를 좌우합니다.
Has Exit Time은 현재 애니메이션의 정규화 시간(normalized time)이 Exit Time에 도달한 뒤 전이를 허용합니다. 공격처럼 즉시 반응해야 하는 상태에 무심코 켜 두면 Trigger를 눌렀어도 이전 클립 끝까지 기다립니다. 반대로 이동 상태처럼 동작의 끝을 유지해야 하는 전이에서 끄면 중간에 끊기는 모습이 날 수 있습니다.
Animator 컴포넌트
| Inspector 항목 | 기본 동작 | 언제 바꾸는가 | 잘못 맞추면 보이는 증상 |
|---|---|---|---|
Controller | 상태·파라미터·전이를 담은 Runtime Animator Controller | 이 오브젝트가 다른 상태 그래프를 써야 할 때 | API 호출은 해도 대상 파라미터나 상태가 없음 |
Avatar | Humanoid 리타게팅에 쓰는 Avatar | Humanoid 모델과 Avatar가 분리된 경우 | 뼈 매핑 오류, 기대와 다른 포즈 |
Apply Root Motion | 애니메이션의 루트 이동·회전을 Transform에 적용 | 클립이 이동 거리를 소유해야 할 때만 켬 | 코드 이동과 합쳐져 두 번 움직이거나 제자리 재생 |
Update Mode | Normal은 scaled frame time, Animate Physics는 물리 타이밍, Unscaled Time은 pause에도 진행 | 물리 몸체와 맞추거나 pause UI 연출을 분리할 때 | 물리와 애니메이션 타이밍이 어긋나거나 pause 중에도 원치 않게 재생 |
Culling Mode | 화면 밖 Animator의 업데이트 범위를 정함 | 화면 밖에도 root motion·상태가 계속 필요할 때 | 다시 보일 때 상태가 튀거나 root motion이 누적과 다르게 보임 |
Animate Physics로 바꿨다고 Rigidbody 이동 책임이 Animator로 넘어가지는 않습니다. Root motion을 쓸지, FixedUpdate에서 Rigidbody를 움직일지를 먼저 하나의 소유자로 정합니다.
스크립트 연결
SetBool, SetInteger, SetFloat, SetTrigger는 값을 쓰고, GetBool, GetInteger, GetFloat는 현재 Animator가 가진 값을 읽습니다. 매 프레임 반복 호출하는 파라미터는 문자열 대신 Animator.StringToHash 결과를 사용합니다. hash 값은 실행 중 동일한 이름을 빠르게 찾기 위한 ID이므로, 이름 자체를 바꾸면 hash 상수도 다시 맞춰야 합니다.
private static readonly int MoveSpeedId = Animator.StringToHash("MoveSpeed");
[SerializeField] private Rigidbody body;
private void FixedUpdate()
{
// Rigidbody.velocity처럼 물리 결과를 읽는 경우에는 물리 루프에서 갱신합니다.
float planarSpeed = new Vector3(body.linearVelocity.x, 0f, body.linearVelocity.z).magnitude;
animator.SetFloat(MoveSpeedId, planarSpeed, 0.12f, Time.fixedDeltaTime);
}SetFloat(id, value, dampTime, deltaTime)의 네 인수 형태는 Animator가 목표 값으로 부드럽게 접근하게 합니다. 이미 입력값에 smoothing을 적용했다면 다시 큰 damping을 주어 이중 지연을 만들지 않습니다. GetCurrentAnimatorStateInfo(layer)는 현재 레이어가 어느 상태를 재생하는지 확인할 때 쓰되, 전이 중인지 확인하려면 IsInTransition(layer)도 함께 봅니다.
Trigger가 들어간 전이를 막거나 다른 공격으로 바꿔야 할 때는 순서를 의식합니다.
public void CancelAttack()
{
animator.ResetTrigger(AttackId);
animator.Play("Locomotion", 0, 0f);
}ResetTrigger는 이미 소비된 Trigger를 되돌리는 기능이 아닙니다. 아직 소비되지 않은 요청을 제거하는 수단입니다. Trigger 하나로 콤보 단계, 접지 여부, 장착 상태까지 표현하면 언제 남고 사라지는지 추적하기 어려워지므로 유지 상태는 Bool·Int·Float으로 분리합니다.
자주 틀리는 부분
| 증상 | 흔한 원인 | 확인과 수정 |
|---|---|---|
| Trigger를 눌렀는데 나중에 갑자기 전이 | 해당 Trigger를 소비할 전이가 당시에는 없었음 | Transition 조건·Exit Time·우선순위를 확인하고 취소 경로에서 ResetTrigger |
| 공격 Trigger가 이동 전이와 충돌 | 여러 전이가 같은 조건 조합에서 가능 | 상태별 전이 우선순위와 상호 배타 조건을 정리 |
SetFloat을 했는데 Blend Tree가 움직이지 않음 | 다른 Controller, 잘못된 이름·타입, layer weight 0 | 실제 Animator의 Controller·Parameter·레이어 가중치 확인 |
| 애니메이션 이동이 너무 멀거나 물리 충돌이 이상함 | root motion과 Transform/Rigidbody 이동을 함께 적용 | 이동 소유자를 하나로 정하고 Apply Root Motion과 코드 경로를 맞춤 |
| pause 중에도 캐릭터 모션이 진행 | Unscaled Time 또는 외부 재생 코드 사용 | 연출 의도에 맞는 Update Mode와 Time.timeScale 영향 재확인 |
참고 링크
3 sources