top of page

Design Pattern] Strategy Pattern을 사용한 Player 이동 구현

  • 작성자 사진: 김영호
    김영호
  • 2022년 11월 14일
  • 2분 분량

최종 수정일: 2023년 4월 25일

Strategy Pattern(전략 패턴)은 한 행동에 대해 여러가지 전략을 필요에 따라 사용 할 수 있도록 구현하는 디자인 패턴이다.

이를 사용해 Player 이동방법을 Translate와 AddForce 두가지 방법으로 따로 구현한 뒤, Player1에는 Translate를, Player2에는 AddForce를 넣고 동작 시켰다.

각 전략은 ScriptableObject를 상속받아 구현했다.



  • Player

public class Player : MonoBehaviour
{
    //속도
    public float speed_Mov;
    
    //Action : 전략
    public Action move;
    
    void Start()
    {
        //Move 전략에 사용할 캐릭터 지정
        if(move != null)
            move.SetCha(this);
    }
    
    void Update()
    {
        //전략 동작
        move._Action();
    }
}


  • Interface IMove : Move 전략을 포함할때 사용할 인터페이스

public Interface IMove
{
    public void Move();
}

  • Action : 행동 전반의 부모 클래스

// Prefab화 시켜서 Player의 script에 드래그 앤 드롭을 통해 간편한 전략 선택을 하기 위해 ScriptableObject 상속
public class Action : ScriptableObject
{
    //해당 전략을 보유한 캐릭터
    protected Character cha;
    public void SetCha(Character cha)
    {
        this.cha = cha;
    }
    
    //하위 클래스에서 기능을 구현할 동작 함수
    virtual public void _Action() {}
}

  • Action_Move : Action을 상속받은 이동 전반의 클래스들의 부모

//움직임 전략
public class Action_Move : Action, IMove
{
    public override void _Action()
    {
        //Action_Move._Action()을 하면 Move(하위 클래스에서 기능 구현) 동작
        Move();
    }
    
    //하위 클래스에서 기능 구현
    virtual public void Move() {}
}

  • Action_Move_Translate : Action_Move를 상속받고 Translate를 사용해 구현

//Translate를 이용한 이동 구현
[CreateAssetMenu(fileName = "Action_Move_Translate", menuName = "Scriptable Object/Action/Move/Translate", order = 0]
public class Action_Move_Translate : Action_Move
{
    //실제 기능(Move) 구현
    override public void Move()
    {
        //Exception Handling (
        if(cha == null) return;

        //Input
        float v = Input.GetAxis("Vertical");    //forward, back
        float h = Input.GetAxis("horizontal");  //right, left
        
        //Move Direction
        Vector3 mov = new Vector3(h, 0, v) * cha.stat.GetSpeedMov() * Time.deltaTime;
        
        //Translate
        cha.transform.Translate(mov);
        
        Debug.Log(cha.name + "] Translate is better!!");
    }
}

  • Action_Move_AddForce : Action_Move를 상속받고 AddForce를 사용해 구현

//AddForce를 이용한 이동 구현
[CreateAssetMenu(fileName = "Action_Move_AddForce", menuName = "Scriptable Object/Action/Move/AddForce", order = 0]
public class Action_Move_AddForce : Action_Move
{
    //실제 기능(Move) 구현
    override public void Move()
    {
        //Exception Handling
        if(cha == null) return;
        
        //Input
        float v = Input.GetAxis("Vertical");    //forward, back
        float h = Input.GetAxis("horizontal");  //right, left
        
        //Move Direction
        Vector3 mov = new Vector3(h, 0, v) * cha.stat.GetSpeedMov();
        
        //AddForce
        cha.GetComponent<Rigidbody>().AddForce(mov);
        
        Debug.Log(cha.name + "] AddForce is better!!");
    }
}


  • 장점

새로운 이동방법으로 변경할 때 새로운 Action을 만들어 설정 해주는 것만으로 교체가가능하며, Character, Player의 코드를 고칠 필요가 없어진다.

이동을 하는데에 문제가 발생하면 해당 이동 클래스만 수정하면 되기 때문에 유지관리에 용의하다.

  • Facebook
  • Twitter
  • LinkedIn

©2021 by 김영호_포트폴리오. Proudly created with Wix.com

bottom of page