반응형
상태 패턴이란?
상태 패턴은 객체의 상태에 따라 그에 따른 행동을 달리하는 상황에서, 상태를 객체화하여 상태가 행동을 할 수 있도록 위임하는 패턴이다.
이 디자인 패턴을 활용하면 캐릭터의 상태에 따른 행동을 SOLID원칙을 고수하며 작성할 수 있다.
왜 사용하는 것일까?
아래는 상태 패턴의 장단점을 정리한 것이다.
장점
- 상태의 개수를 변경하더라도 기존의 코드 수정 없이 확장하거나 줄일 수 있다.
- 상태 전이에 따른 로직 변경이 쉽다.
- 캡슐화 하여 동적으로 할당이 가능하다.
단점
- 애니메이션 블렌딩이 어렵다. 따라서 CrossFade를 사용하거나 Behavior Tree를 사용해야 한다.
- 상태 간의 전환에 관한 로직은 별도로 구현해야 한다. FSM(유한 상태 머신)을 사용해도 된다.
정리하자면 어떠한 객체(특히 캐릭터)의 상태를 나타낼 때 유지보수를 고려하여 작성하기 좋은 방법 중 하나이다.
어떻게 사용할 수 있을까?
상태 패턴은 다음 세 가지의 요소를 중점으로 작성해야 한다.
- Context : 객체의 상태를 저장하고 행동을 정의한다.
- IState : 구체 상태 클래스로 연결할 수 있는 인터페이스이다.
- ConcreteState : 클래스에 의해 인스턴스화되는 상태를 구현한 클래스이다.
아래는 캐릭터의 상태(이동, 공격, 피격, 죽음)를 상태 패턴으로 구현한 예시이다.
먼저 인터페이스를 구현한다.
public interface ICharacterState
{
void Convert(CharacterController controller);
}
그리고 상태를 담을 수 있는 Context를 구현한다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class StateController : MonoBehaviour
{
public ICharacterState Current
{
get; private set;
}
private readonly CharacterController characterController;
public StateController(CharacterController characterController)
{
this.characterController = characterController;
}
public void ChangeState(ICharacterState state)
{
if (state == Current)
return;
Current = state;
Current.Convert(characterController);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CharacterController : MonoBehaviour
{
public int id;
public string characterName;
public int moveSpeed;
public int hp;
public int damage;
public int cost;
public float spawnTime;
public Animator animator { get; private set; }
private StateController controller;
private ICharacterState move, attack, hit, dead;
void Awake()
{
move = new MoveState();
attack = new AttackState();
hit = new HitState();
dead = new DeadState();
}
public void Attak()
{
controller.ChangeState(attack);
}
public void Move()
{
controller.ChangeState(move);
}
public void Hit()
{
controller.ChangeState(hit);
}
public void Dead()
{
controller.ChangeState(dead);
}
void Update()
{
}
}
마지막으로 각 상태를 클래스로 정의한다.
Move 클래스
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MoveState : ICharacterState
{
public void Convert(CharacterController controller)
{
throw new System.NotImplementedException();
}
}
Attack 클래스
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AttackState : ICharacterState
{
public void Convert(CharacterController controller)
{
controller.animator.SetTrigger("Attack");
}
}
Hit 클래스
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HitState : ICharacterState
{
public void Convert(CharacterController controller)
{
throw new System.NotImplementedException();
}
}
Dead 클래스
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DeadState : ICharacterState
{
public void Convert(CharacterController controller)
{
throw new System.NotImplementedException();
}
}
정리
상태 패턴은 캐릭터의 상태 변경을 유지보수와 확장을 편리한 방식으로 사용할 수 있도록 설계된 디자인 패턴이다.
단독으로 사용할 경우 상태 전환에 대한 문제점이 있으므로 FSM등과 함께 사용하여 이용한다.
반응형
'유니티 > 디자인 패턴' 카테고리의 다른 글
[Unity] 서비스 로케이터 패턴 (Service Locator Pattern) (0) | 2024.04.09 |
---|---|
[Unity] 널 객체 패턴 (Null Object Pattern) (1) | 2023.10.25 |
[Unity] 커맨드 패턴 (Command Pattern) (1) | 2023.10.22 |
[Unity] 빌더 패턴 (Builder Pattern) (0) | 2023.10.05 |
[Unity] 옵저버 패턴 (Observer Pattern) (0) | 2022.05.03 |