그냥 조건문으로 관리하면 안되나?
처음 유니티를 배운 후, 캐릭터의 애니메이션 및 행동을 관리해주기 위한 스크립트를 짜보라 하면 보통 아래같은 방식으로 작성합니다
if(뛰는 중)
{
뛰는 애니메이션 실행.
움직일 목적지로 이동시킴.
if(죽음)
{
죽는 애니메이션 실행.
각종 필요한 처리..
...
}
else
{
if(속도를 줄여서 걷게됨)
{
...
}
}
}
else if(먹는 중)
{
if(죽음)
{
...
}
else if()...
}
이런식으로 조건문속에 조건문을 넣고 넣고...
간단한 애니메이션과 상태를 지닌 게임이라면 이렇게 해도 무방합니다.
하지만 이 방식은 결국 코드가 복잡해지는 한계에 봉착합니다.
이를 해결할 수 있는 방식중에 하나가 스테이트 패턴을 사용하기 입니다.
스테이트 패턴
일단 가정을 플레이어컨트롤러에 대한 스크립트라고 하겠습니다.
저 같은 경우는 가독성을 위해서 enum으로 플레이어의 상태를 지정해보겠습니다.
public enum PlayerState
{
Die,
Moving,
Idle,
}
위와 같이 Die, Moving, Idle 기본적인 3가지로 가정합니다.
그리고 핵심은, Update문에서 볼 수 있습니다.
void Update()
{
switch (_state)
{
case PlayerState.Die:
UpdateDie();
break;
case PlayerState.Moving:
UpdateMoving();
break;
case PlayerState.Idle:
UpdateIdle();
break;
}
}
state에 따라서 해당하는 상태에서 일어나야 할 일을 처리해주는 함수를 호출해줍니다.
이런 식으로 하면, if문이 얼기설기 중첩되는 방식을 쉽게 막아주며 가독성도 높일 수 있습니다.
그리고 아래와 같이 각 상태에 해당하는 함수를 구성해 봤습니다.
void UpdateDie()
{
// 아무것도 못함
}
void UpdateMoving()
{
Vector3 dir = _destPos - transform.position;
if (dir.magnitude < 0.0001f)
{
_state = PlayerState.Idle;
}
else
{
float moveDist = Mathf.Clamp(_speed * Time.deltaTime, 0, dir.magnitude);
transform.position += dir.normalized * moveDist;
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(dir), 20 * Time.deltaTime);
}
// 애니메이션
Animator anim = GetComponent<Animator>();
// 현재 게임 상태에 대한 정보를 넘겨준다
//애니메이터에서 speed변수값이 변경되면 뛰기 애니메이션을 변경되게 설정해놨음
anim.SetFloat("speed", _speed);
}
void UpdateIdle()
{
// 애니메이션
Animator anim = GetComponent<Animator>();
anim.SetFloat("speed", 0);
}
활용법은 무궁무진할 것입니다.
단점은 상태가 움직이면서 스킬을 쓰는 등, 상태가 복잡해지면 약간 복잡해 질 수 있습니다.
그래도 기존 방식보다는 확실히 코드를 읽는데 수월한 건 변함없습니다.
'유니티' 카테고리의 다른 글
[Unity] Json을 이용한 데이터 관리 (0) | 2023.02.03 |
---|---|
[Unity] 코루틴(Coroutine) (0) | 2023.02.02 |
[Unity] 애니메이션 기초(스테이트 머신) 및 파라미터 설정 (0) | 2023.01.28 |
[Unity] Input System을 스크립트에서 사용하는법 (0) | 2023.01.25 |
[Unity] Input받는 방법 (Input System 이용) (0) | 2023.01.25 |