BEHAVIORAL

Memento

What is it?

Memento is a behavioral design pattern that allows an object's current state to be saved without exposing its internal structure, and restored later when needed. In simple terms, it works with the idea of “save the current state, then return to it later if necessary.”

There are three main roles in this pattern. Originator is the actual object whose state will be saved. It creates its own snapshot and restores itself from that snapshot when needed. Memento is the container that holds this saved state. Its contents are not modified or directly accessed from the outside. Caretaker is the structure that stores these Mementos. It does not need to know what is inside them; it only keeps them and gives them back when necessary.

Thanks to this structure, the object's internal data is not directly exposed. This keeps the system clean and makes operations like undo, checkpoints, or save/load possible without breaking encapsulation.

When is it used?

Memento is generally used when a system needs to return to a previous state. The most common example is an undo / redo system. Before the user makes a change, the current state is saved. When undo is triggered, the system returns to the last saved state.

In games, it is often used for save / load, checkpoint, and sometimes replay systems. For example, a player's position, health, inventory, or current level can be saved. If the player makes a mistake or hits a dangerous obstacle, the system can restore them to the last saved point.

Level editors, character customization screens, form-filling pages, playtesting tools, and experimental game mechanics are also suitable use cases for Memento. It is especially useful in situations where the user should be able to try something and return to the previous state if needed.

Animation

MEMENTOmoves: 0Move forward, then Save your position!Save Slots (Stack)empty stack

Code

Assets / Scripts / Behavioral / MementoPlayerMemento.cs
READ ONLY
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
using UnityEngine;

namespace Patterns.Behavioral.Memento
{
    public class PlayerMemento
    {
        public Vector3 Position { get; }

        public PlayerMemento(Vector3 position)
        {
            Position = position;
        }
    }
}

Advantages and Disadvantages

• Advantages:

  • It saves an object's state safely without exposing its internal structure.
  • It makes managing previous states easier in undo / redo systems.
  • Outside systems do not need to know the object's internal details.

• Disadvantages:

  • Saving too many snapshots can increase memory usage.
  • Reference types can break snapshots if real copies are not made.
  • Keeping an unlimited undo stack can cause memory problems over time.

Tips

In Unity, the Memento object usually does not need to be a MonoBehaviour. A simple [Serializable] class or struct is usually enough. The purpose of Memento is not to exist as an object in the scene, but to carry the data of a specific moment.

For undo / redo, using Stack<T> makes sense because the last saved state is the first one to be restored. However, this stack should not be unlimited. Limiting it to something like the last 50 or 100 records is usually healthier. For checkpoint systems, where the order of saved states matters more, using a List<T> with an active index can be more practical.

Reference types should be handled carefully. If structures like List<Item>, List<string>, or similar collections are assigned directly, a real snapshot may not be created. Instead, a new list should be created:

savedInventory = new List<string>(currentInventory);

For a save / load system, marking the Memento class as [Serializable] and converting it to JSON with JsonUtility is a practical solution. Files are usually saved under Application.persistentDataPath. For systems like replay or ghost mechanics, where data is recorded very frequently, it is better to avoid saving the entire state every frame.

In short, when using Memento in Unity, three things matter most: the snapshot must be a real copy, the number of saved states should be controlled, and unnecessary saving should be avoided every frame.