-
[Unity Tip] State Machine Behaviour로 애니메이션 컨트롤하기2023년 11월 10일
- 유니얼
-
작성자
-
2023.11.10.오후09:32
728x90Unity 프로젝트에서 애니메이션은 단순한 움직임 이상의 역할을 수행할 수 있습니다. 애니메이션 이벤트는 특정 애니메이션 프레임에서 함수를 호출하는 데 사용될 수 있지만, 보다 일반적인 작업을 하려면 Unity의 상태 머신 동작(StateMachineBehaviour)을 고려하는 것이 좋습니다.
유니티 도큐먼트 링크 :
https://docs.unity3d.com/kr/560/Manual/StateMachineBehaviours.html
상태 머신 동작 - Unity 매뉴얼
상태 머신 동작(State Machine Behaviour)은 특별 스크립트 클래스입니다. 일반 Unity 스크립트(MonoBehaviours)를 개별 게임 오브젝트에 연결하는 것과 유사한 방법으로 StateMachineBehaviour 스크립트를 상태 머
docs.unity3d.com
State Machine Behaviour란?
상태 머신 동작(StateMachineBehaviour)은 Unity의 Animator 시스템과 함께 사용되며, 특정 애니메이션 상태에 진입, 이탈 또는 업데이트할 때 원하는 작업을 정의할 수 있습니다. 이것은 다양한 애니메이션 상태에서 작동해야 하는 작업을 관리하고, 상태 전환 시 추가 코드를 실행하는 데 유용합니다. 또한 상태 머신 동작은 코드를 깔끔하게 유지하고 재사용 가능하게 만들어주며, 여러 상태에서 동일한 로직을 공유할 수 있습니다.
상태 머신 동작을 사용하면 특정 상태에서 특별한 작업을 수행할 수 있는 뿐만 아니라 코드를 더 효율적으로 관리하고 모듈화 할 수 있습니다. 또한 이러한 스크립트를 여러 상태 머신에서 재사용할 수 있어 프로젝트의 코드를 구조적으로 만들어줍니다. Unity의 애니메이션 및 게임 로직을 더욱 유연하게 제어하고 관리할 수 있게 도와줍니다.상태 머신 동작을 사용하는 몇 가지 예는 다음과 같습니다.
- 상태를 시작 또는 종료할 때 사운드 재생
- 적절한 상태에 있을 때만 특정 테스트(예: 지면 탐지) 수행
- 특정 상태와 연관된 특수 효과 활성화 및 제어
이번 글에서는 프로젝트에서 State Machine Behaviour와 그 사용법 예시를 알아보겠습니다.
1, State Machine Behaviour 코드
StateMachineBehaviour는 Unity에서 사용되는 스크립트 클래스로, Animator 컨트롤러의 상태 머신(State Machine)에서 발생하는 다양한 이벤트에 대응하여 동작을 정의할 수 있습니다. 이 클래스는 다양한 이벤트에 대한 메서드를 가지며, 이를 상속하여 원하는 동작을 정의할 수 있습니다.
public abstract class StateMachineBehaviour : ScriptableObject { public virtual void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) { // 상태에 진입할 때 호출됩니다. } public virtual void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) { // 상태가 업데이트될 때 호출됩니다. } public virtual void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) { // 상태를 빠져나갈 때 호출됩니다. } public virtual void OnStateMove(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) { // 상태가 이동할 때 호출됩니다. } public virtual void OnStateIK(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) { // 역방향 키네마틱(Inverse Kinematics) 작업을 수행할 때 호출됩니다. } public virtual void OnStateMachineEnter(Animator animator, int stateMachinePathHash) { // 상태 머신에 진입할 때 호출됩니다. } public virtual void OnStateMachineExit(Animator animator, int stateMachinePathHash) { // 상태 머신을 빠져나갈 때 호출됩니다. } }
OnStateEnter 이 메서드는 StateMachineBehaviour와 연결된 상태가 진입될 때 호출됩니다. 상태에 진입할 때 초기 조건을 설정하거나 진입 시 특정 동작을 트리거하는 데 사용됩니다. OnStateExit 이 메서드는 StateMachineBehaviour와 연결된 상태가 빠져나갈 때 호출됩니다. 상태를 빠져나갈 때 정리 작업을 수행하거나 나가는 동안 특정 작업을 수행하는 데 자주 사용됩니다. OnStateUpdate 이 메서드는 상태가 활성화된 상태에서 매 프레임마다 호출됩니다. 상태가 활성 상태인 동안 지속적으로 업데이트해야 하는 동작을 구현하는 데 사용됩니다. OnStateIK 이 메서드는 상태 동안 역방향 키네마틱(Inverse Kinematics, IK)을 처리하는 데 사용됩니다. 주로 캐릭터의 팔다리 위치를 실제 객체나 표면과 현실적으로 상호 작용하도록 조정하는 데 사용됩니다. OnStateMachineEnter 이 메서드는 상태를 포함하는 상태 머신(Animator 컨트롤러)이 상태를 진입할 때 호출됩니다. 상태 머신 전체의 초기 조건을 설정하는 데 유용합니다. OnStateMachineExit 이 메서드는 상태를 포함하는 상태 머신(Animator 컨트롤러)이 상태를 빠져나갈 때 호출됩니다. 상태 머신의 상태를 정리하거나 재설정하는 데 자주 사용됩니다. 2, State Machine Behaviour 생성 및 사용
Step 1 : Animator Editor 창 열기
Unity 에디터에서 Animator 컨트롤러를 열어서 애니메이션 상태 머신(State Machine)을 선택합니다. 상태 머신은 Animator 컨트롤러에서 특정 상태(또는 레이어)를 나타냅니다. 선택한 상태를 Inspector 창에서 확인하세요.
Animator Editor 창 Step 2 : State Machine Behaviour 생성하기
"Add Behaviour" 버튼을 사용하여 StateMachineBehaviour를 선택하거나 생성하는 단계는 다음과 같습니다. 상태를 선택한 후, 인스펙터 창에서 해당 상태를 확인합니다. 그런 다음 인스펙터 창에서 "동작 추가" 또는 "Add Behavior" 버튼을 찾습니다. 이 버튼을 클릭하면 해당 상태에 대한 동작(behavior)을 추가할 수 있는 옵션 목록이 표시됩니다.
기존에 작성한 StateMachineBehaviour 스크립트를 선택하려면 해당 스크립트 이름이 나타날 것입니다. 이 스크립트를 선택하고 추가 버튼을 클릭하면 해당 스크립트가 해당 상태에 연결됩니다.
새로운 StateMachineBehaviour 스크립트를 생성하려면 "New Script" 또는 "새 스크립트" 옵션을 선택하고 원하는 스크립트 이름을 입력한 다음 "Create and Add" 버튼을 클릭하여 새 스크립트를 생성하고 해당 상태에 연결합니다.
State Machine Behaviour 코드 생성하기 Step 3 : Animator/ Animation Sub_State Machine/ Animation State에 코드 추가하기
이제 선택한 상태에 대한 StateMachineBehaviour 스크립트을 추가 혹은 연결을 하여 해당 상태에서 실행할 동작을 정의하고 애니메이션 논리를 확장할 수 있습니다.
Animator/ Animation Sub_State Machine/ Animation State에 코드 연결 3, State Machine Behaviour 사용 예시
저는 피격 상태일시 캐릭터의 움직임을 막기위해서 Aniamtor Parameters에서 LockVelocity 변수를 추가하였고 이를 State Machine Behaviour를 통해서 Hit애니메이션이 재생할 동안 LockVelocity를 제어하여 캐릭터의 상태를 제어하도록 하였습니다.
SetBoolBehaviour.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; public class SetBoolBehaviour : StateMachineBehaviour { public string boolName; // Animator의 bool 변수의 이름을 저장할 변수 public bool updateOnState; // 상태 진입 및 종료 시 Animator의 bool 변수를 업데이트할지 여부를 결정하는 플래그 public bool updateOnStateMachine; // 상태 머신 진입 및 종료 시 Animator의 bool 변수를 업데이트할지 여부를 결정하는 플래그 public bool valueOnEnter; // 상태 진입 시 설정할 Animator의 bool 변수 값 public bool valueOnExit; // 상태 종료 시 설정할 Animator의 bool 변수 값 // OnStateEnter는 해당 상태에 진입할 때 호출됩니다. override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) { if (updateOnState) { // updateOnState 플래그가 true이면 boolName으로 지정된 Animator의 bool 변수를 valueOnEnter 값으로 설정합니다. animator.SetBool(boolName, valueOnEnter); } } // OnStateExit는 해당 상태에서 빠져나갈 때 호출됩니다. override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) { if (updateOnState) { // updateOnState 플래그가 true이면 boolName으로 지정된 Animator의 bool 변수를 valueOnExit 값으로 설정합니다. animator.SetBool(boolName, valueOnExit); } } // OnStateMachineEnter는 해당 상태 머신(Animator 내에서 상태들의 집합)에 진입할 때 호출됩니다. override public void OnStateMachineEnter(Animator animator, int stateMachinePathHash) { if(updateOnStateMachine) { // updateOnStateMachine 플래그가 true이면 boolName으로 지정된 Animator의 bool 변수를 valueOnEnter 값으로 설정합니다. animator.SetBool(boolName, valueOnEnter); } } // OnStateMachineExit는 해당 상태 머신에서 빠져나갈 때 호출됩니다. override public void OnStateMachineExit(Animator animator, int stateMachinePathHash) { if (updateOnStateMachine) { // updateOnStateMachine 플래그가 true이면 boolName으로 지정된 Animator의 bool 변수를 valueOnExit 값으로 설정합니다. animator.SetBool(boolName, valueOnExit); } } }
PlayerController.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.InputSystem; public class PlayerController : MonoBehaviour { public bool LockVelocity { get { // Animator에서 "LockVelocity"라는 bool 변수의 현재 상태를 가져옵니다. return animator.GetBool(AnimationStrings.LockVelocity); } set { // Animator의 "LockVelocity"라는 bool 변수 값을 주어진 값(value)으로 설정합니다. animator.SetBool(AnimationStrings.LockVelocity, value); } } private void FixedUpdate() { // damageable.LockVelocity가 false이고 IsWallJump가 false일 때 아래 코드를 실행합니다. if (!damageable.LockVelocity && !IsWallJump) { // Move 메서드를 호출하여 캐릭터 이동을 처리합니다. Move(); // Rigidbody2D의 속도를 설정하여 캐릭터를 움직입니다. rb.velocity = new Vector2(moveInput.x * CurrentMoveSpeed, rb.velocity.y); } // 애니메이터에 캐릭터의 y 방향 속도 정보를 전달하여 점프 애니메이션 등을 제어합니다. animator.SetFloat(AnimationStrings.yVelocity, rb.velocity.y); } public void Move() { // 수평 입력 값을 받아옵니다. float x_value = Input.GetAxis("Horizontal"); // 입력된 x_value 값을 기반으로 캐릭터의 수평 이동 방향을 설정합니다. moveInput = new Vector2(x_value, 0);/*context.ReadValue<Vector2>();*/ // 캐릭터가 살아있는 경우에만 아래 코드를 실행합니다. if (IsAlive) { // 캐릭터가 움직이는지 여부를 확인하고 상태를 설정합니다. IsMoving = moveInput != Vector2.zero; // 캐릭터의 이동 방향을 설정하는 메서드를 호출하여 캐릭터가 어느 방향을 향하는지 결정합니다. SetFacingDirection(moveInput); } else { // 캐릭터가 죽은 경우에는 IsMoving을 false로 설정합니다. IsMoving = false; } } }
KnockbackAnimation 이제 캐릭터가 Hit 상태의 애니메이션을 실행중이면 움직일 수 없도록 코드를 제어할 수 있습니다. 이를 통해서 다양한 애니메이션 상태에서 작동해야 하는 작업을 관리하고, 상태 전환 시 추가적인 코드를 실행하는 데 용이합니다. 또한 상태 머신 동작은 코드를 깔끔하게 유지하고 재사용 가능하게 만들어주고, 여러 상태에서 동일한 로직을 공유할 수 있습니다.
반응형다음글이전글이전 글이 없습니다.댓글