Stack/DesignPattern
명령패턴 실행취소 기능
Seo_re:
2024. 2. 27. 16:47
반응형
※ 명령패턴 설명
1. 실행 취소 기능
명령 패턴으로 실행 단위를 객체로 만들어두면 손쉽게 실행취소 기능을 구현할 수 있다.
위와 같이 Command 객체에 대한 List를 만들고 추가 명령이 생성되면 List의 맨 끝에 추가한 뒤, 현재 명령으로 기억하면 된다. Undo의 기능만 넣게되면 현재명령은 지워주고 현재 명령을 이전 명령으로 위치를 잡아주면 되고, Redo 기능을 같이 추가하게되면 실행 취소 전의 명령은 그대로 살려주면 될것이다.
2. 예시 코드
2-1) Command(추상 클래스)
public abstract class Command
{
protected int direction;
protected Actor actor;
public abstract void Execute(Actor actor);
public abstract void ExecuteAxis(Actor actor);
public abstract void Undo();
}
2-2) VerticalCommand(Command 상속)
using UnityEngine;
public class VerticalCommand : Command
{
public VerticalCommand(Actor actor, int direction)
{
this.actor = actor;
this.direction = direction;
}
public override void Execute(Actor actor)
{
}
public override void ExecuteAxis(Actor actor)
{
actor.MoveTo(new Vector2(0, direction));
}
public override void Undo()
{
actor.MoveTo(new Vector2(0, -direction));
}
}
2-3) HorizontalCommand(Command 상속)
using UnityEngine;
public class HorizontalCommand : Command
{
public HorizontalCommand(Actor actor, int direction)
{
this.actor = actor;
this.direction = direction;
}
public override void Execute(Actor actor)
{
}
public override void ExecuteAxis(Actor actor)
{
actor.MoveTo(new Vector2(direction, 0));
}
public override void Undo()
{
actor.MoveTo(new Vector2(-direction, 0));
}
}
2-4) Actor
using UnityEngine;
public class Actor : MonoBehaviour
{
private Rigidbody2D rb;
private void Start()
{
rb = GetComponent<Rigidbody2D>();
}
public void MoveTo(Vector2 pos)
{
rb.MovePosition(rb.position + pos);
}
}
2-5) InputHandler
using System.Collections.Generic;
using UnityEngine;
public class InputHandler : MonoBehaviour
{
[SerializeField]
private Actor targetActor;
private List<Command> commands = new List<Command>();
private int executionIndex = -1;
private void Update()
{
Command targetCommand = HandleInput();
if(targetCommand != null && targetActor != null)
{
commands.Add(targetCommand);
executionIndex++;
targetCommand.ExecuteAxis(targetActor);
}
}
private Command HandleInput()
{
if (Input.GetKeyDown(KeyCode.W))
{
return new VerticalCommand(targetActor, 1);
}
else if (Input.GetKeyDown(KeyCode.S))
{
return new VerticalCommand(targetActor, - 1);
}
else if (Input.GetKeyDown(KeyCode.A))
{
return new HorizontalCommand(targetActor, - 1);
}
else if (Input.GetKeyDown(KeyCode.D))
{
return new HorizontalCommand(targetActor,1);
}
else if(executionIndex >= 0 && Input.GetKey(KeyCode.LeftControl) && Input.GetKeyDown(KeyCode.X))
{
commands[executionIndex].Undo();
commands.RemoveAt(executionIndex);
executionIndex--;
}
return null;
}
}
※ 위 코드는 Undo의 기능만 구현해서 짠 코드이다.
※ 생성자에 Actor를 인자로 받는 이유는 플레이어만이 아닌 다른 캐릭터에 대한 실행취소도 포함하기 위함이다.
※ 앞선 커맨트 패턴의 게시글의 코드를 재활용해서 짠 코드이므로 Actor에 붙어있는 Rigidbody의 GravityScale의 값을 0으로 설정해야 정상적으로 작동 된다.
3. 실행 확인
반응형