[Design Pattern] State Pattern, 유니티 애니매이션에 자주 쓰이는 state 디자인 패턴에 대해서 알아보자!

2024. 11. 12. 20:48·DesignPattern

유니티에서 뛰기 점프하기 장전하기 쏘기 등등 상황에 걸맞는 멋있는 애니매이션을 쓰고자 노력을 하다보면 상황을 제한해야하기도, 추가해야하기도 한다. 그럴땐 보통 드는 생각은 bool값을 설정하여 if else문에 && || 로 조건을 걸어 해당 애니매이션을 재생하곤 한다.

bool isFalling;
bool isJumping;
bool isSkillCasting;
bool isSkillChanneling;

if(isJumping)
{

}
else
{
    if(isSkillChanneling && isFalling)
    {

    }
    else
    {
        if(isSkillCasting)
        {

        }
    }
}

 

위와 같이 상황이 적으면 괜찮겠지만 와우 캐릭터 하나만 해도 여러가지 감정표현에 엄청 많은 bool변수들이 필요한다고 한다. flag 변수들을 많이 두고 if else문으로 조건을 걸면 너무 복잡하다.

 

그래서 State(상태)에 따라 재생하는 애니매이션을 다르게 하고자 한다!!

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerController : MonoBehaviour
{
    float wait_run_ratio = 0;

    [SerializeField]
    float _speed = 10.0f;

    Vector3 _destPos;  // 목적지

    void Start()
    {
        Managers.Input.MouseAction -= OnMouseClicked;
        Managers.Input.MouseAction += OnMouseClicked;
    }

    public enum PlayerState
    {
        Die,
        Moving,
        Idle,
    }

    PlayerState _state = PlayerState.Idle;

    void Update()
    {
        switch (_state)
        {
            case PlayerState.Die:
                UpdateDie();
                break;
            case PlayerState.Moving:
                UpdateMoving();
                break;
            case PlayerState.Idle:
                UpdateIdle();
                break;
        }
    }

    void UpdateDie()
    {
        // 아무것도 못함
    }

    void UpdateMoving()
    {
        Vector3 dir = _destPos - transform.position;
        if (dir.magnitude < 0.0001f)  // 도착함
        {
            _state = PlayerState.Idle;
        }
        else   // 도착 X 
        {
            float moveDist = Mathf.Clamp(_speed * Time.deltaTime, 0, dir.magnitude);
            transform.position = transform.position + dir.normalized * moveDist;

            transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(dir), 10 * Time.deltaTime);
            transform.LookAt(_destPos);
        }

        // 애니메이션
        wait_run_ratio = Mathf.Lerp(wait_run_ratio, 1, 10.0f * Time.deltaTime);
        Animator anim = GetComponent<Animator>();
        anim.SetFloat("wait_run_ratio", wait_run_ratio);
        anim.Play("WAIT_RUN");
    }

    void UpdateIdle()
    {
        // 애니메이션
        wait_run_ratio = Mathf.Lerp(wait_run_ratio, 0, 10.0f * Time.deltaTime);
        Animator anim = GetComponent<Animator>();
        anim.SetFloat("wait_run_ratio", wait_run_ratio);
        anim.Play("WAIT_RUN");
    }

    void OnMouseClicked(Define.MouseEvent evt)
    {
        if (_state == PlayerState.Die)
            return;

        if (evt != Define.MouseEvent.Click)
            return;

        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); 
        Debug.DrawRay(Camera.main.transform.position, ray.direction * 100.0f, Color.red, 1.0f);

        RaycastHit hit;
        if (Physics.Raycast(ray, out hit, 100.0f, LayerMask.GetMask("Wall")))
        {
            _destPos = hit.point;
            _state = PlayerState.Moving;
        }
    }
}
if (_state == PlayerState.Die)

//...

        switch (_state)
        {
            case PlayerState.Die:
                UpdateDie();
                break;
            case PlayerState.Moving:
                UpdateMoving();
                break;
            case PlayerState.Idle:
                UpdateIdle();
                break;
        }

 

여기선 Point는!! enum으로 보기좋게 State(상태)를 설정하고 switch 문으로 해당 애니매이션을 실행시키는 것이다!! 이것이 바로 State 디자인 패턴이다!! 보기 좋고 유지보수에 용이하다! 다만 주의해야할 점은 다른 상태로 자연스럽게 넘어가기 위해서 hp가 0이 된다던지 도착지에 도달했다던지 하는 flag 상황에 State를 변경하는 로직이 꼭 있어야 한다!

_state == PlayerState.Jump && _state == PlayerState.Attack 

이런 코드는 불가능하기 때문에! 여러 동작이 꼬일일이 없다! 

 

애니매이션이 너무 많아 어떤 애니매이션을 써야할지 고민하는 행복한 개발자라면 이 디자인 패턴을 잘 사용해보자!

'DesignPattern' 카테고리의 다른 글

[C#] 리스너 패턴을 알아보자 근데 유니티를 곁들인.(이벤트 함수를 사용하는 대표적인 패턴! )  (0) 2024.11.14
[C#] 유니티에서 보는 싱글톤(SingleTone) 디자인 패턴 완벽 가이드  (0) 2024.11.10
'DesignPattern' 카테고리의 다른 글
  • [C#] 리스너 패턴을 알아보자 근데 유니티를 곁들인.(이벤트 함수를 사용하는 대표적인 패턴! )
  • [C#] 유니티에서 보는 싱글톤(SingleTone) 디자인 패턴 완벽 가이드
개발준입니다
개발준입니다
백문이 불여일타
  • 개발준입니다
    Re:제로부터 시작하는 개발이야기
    개발준입니다
  • 전체
    오늘
    어제
    • All (32)
      • Java & Kotlin (3)
      • Spring (0)
      • DataBase (0)
      • Git & Github (1)
      • Baekjoon (8)
      • C & C++ & C# (5)
      • Unity (12)
      • DesignPattern (3)
      • SmallTalk (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    매서드
    유니티
    오블완
    github
    c#
    백준
    코딩
    티스토리챌린지
    알고리즘 #코테
    개발자
    디자인패턴
    알고리즘
    코테
    개발
    게임개발
    가중치 비교
    리스너 패턴
    자바
    레벨 디자인
    state pattern
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.2
개발준입니다
[Design Pattern] State Pattern, 유니티 애니매이션에 자주 쓰이는 state 디자인 패턴에 대해서 알아보자!
상단으로

티스토리툴바