개인 공부/디자인패턴

유니티 메멘토

smallship 2024. 7. 19. 14:33

메멘토 패턴은 객체의 상태를 저장하고 이를 나중에 복원할 수 있는 기능을 제공한다.

 

메멘토는 원조자, 메멘토, 관리자로 구성되어 있다.

 

  • Originator (원조자): 현재 상태를 저장하고 복구할 수 있는 객체. 상태를 저장하고 복원하는 메서드를 가지고 있다.
  • Memento (메멘토): 원조자 객체의 내부 상태를 저장하는 객체. 원조자의 내부 상태를 외부에 공개하지 않고, 원조자만이 접근할 수 있다.
  • Caretaker (관리자): 메멘토 객체를 보관하고 관리하는 객체. 원조자의 상태를 저장하고 복원할 때 메멘토 객체를 사용한다.

유니티에서 플레이어의 상태를 저장하고 복원하는 스크립트를 작성해보자.

using UnityEngine;
using System.Collections.Generic;

// Memento 클래스: 플레이어의 상태를 저장
public class Player_1Memento
{
    public Vector3 Position { get; private set; }
    public int Health { get; private set; }
    public int Score { get; private set; }

    public Player_1Memento(Vector3 position, int health, int score)
    {
        Position = position;
        Health = health;
        Score = score;
    }
}

// Originator 클래스: 플레이어
public class Player_1 : MonoBehaviour
{
    public Vector3 Position { get; set; }
    public int Health { get; set; }
    public int Score { get; set; }

    // 현재 상태를 Memento에 저장
    public Player_1Memento SaveState()
    {
        return new Player_1Memento(Position, Health, Score);
    }

    // Memento로부터 상태를 복원
    public void RestoreState(Player_1Memento memento)
    {
        Position = memento.Position;
        Health = memento.Health;
        Score = memento.Score;

        // Unity Transform 업데이트
        transform.position = Position;

        Debug.Log($"State restored - Position: {Position}, Health: {Health}, Score: {Score}");
    }

    // 플레이어 상태 변경 (예시용)
    public void ChangeState(Vector3 newPosition, int healthChange, int scoreChange)
    {
        Position = newPosition;
        Health += healthChange;
        Score += scoreChange;

        // Unity Transform 업데이트
        transform.position = Position;

        Debug.Log($"State changed - Position: {Position}, Health: {Health}, Score: {Score}");
    }
}

// Caretaker 클래스: 메멘토 관리
public class MementoExample : MonoBehaviour
{
    public Player_1 Player_1;
    private Stack<Player_1Memento> mementos = new Stack<Player_1Memento>();

    void Start()
    {
        Player_1 = GetComponent<Player_1>();
        SavePlayer_1State(); // 초기 상태 저장
    }

    public void SavePlayer_1State()
    {
        mementos.Push(Player_1.SaveState());
        Debug.Log("Player_1 state saved.");
    }

    public void UndoPlayer_1State()
    {
        if (mementos.Count > 1) // 항상 하나의 상태는 남겨둠
        {
            mementos.Pop(); // 현재 상태 제거
            Player_1.RestoreState(mementos.Peek());
        }
        else
        {
            Debug.Log("Can't undo: No more saved states.");
        }
    }

    // 테스트용 메서드들
    public void MovePlayer_1Randomly()
    {
        Vector3 randomPosition = Random.insideUnitSphere * 5f;
        randomPosition.y = 0; // y축은 0으로 유지

        int healthChange = Random.Range(-10, 11);
        int scoreChange = Random.Range(0, 101);

        Player_1.ChangeState(randomPosition, healthChange, scoreChange);
        SavePlayer_1State();
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.S))
        {
            MovePlayer_1Randomly();
        }
        if (Input.GetKeyDown(KeyCode.U))
        {
            UndoPlayer_1State();
        }
    }
}

 

Player_1Memento는 구성요소 중 Memento에 해당되며 플레이어의 상태를 저장하는 역할을 한다. 생성자를 통해 초기화를 해주고 외부에서 변경할 수 없도록 했다.

 

Player_1은 구성요소중 Originater에 해당되며 현재 상태를 관리하며 SaveState를 통해 현재 상태를 메멘토 객체에 저장한다. RestoreState는 저장된 메멘토를 사용하여 플레이어의 상태를 복원한다. ChangeState는 플레이어 상태를 변경한는 메서드로 새로운 상태를 업데이트한다.

 

MementoExample는 Caretaker에 해당되며 관리자 역할을 한다.

Player_1객체를 관리하며 상태를 저장하고 복원한다. 스택이 비어있지 않다면 현재 플레이어 상태를 스택에 저장하고 저장된 상태 중 가장 위에 있는 상태를 가져와 복원한다. 


메멘토 패턴은 플레이어가 죽었을때 체크포인트 지점을 활용하여 재시작 하는 기능, 스킬 사용 이력을 저장하여 되돌리는 기능 등을 구현하는데 자주 사용되며 플레이어 상태와 게임 흐름을 제어가 간편해진다는 장점이 있다.

'개인 공부 > 디자인패턴' 카테고리의 다른 글

유니티 전략 패턴 (Strategy)  (0) 2024.07.19
유니티 중재자 (Mediator)  (0) 2024.07.19
유니티 옵저버  (1) 2024.07.19
유니티 FSM  (0) 2024.07.17
디자인패턴 커맨드 & 유니티 커스텀 에디터  (1) 2024.07.16