Course contentsShow
← Unity Game Development
Lesson 760 of 82811. Performance and Data PersistenceFree lesson

Designing Decoupled Data Transfer Objects

Create serializable container classes that decouple your game state from Unity's internal engine objects to ensure clean, flexible data persistence.

In this lesson, you will learn how to design decoupled Data Transfer Objects (DTOs) to separate your raw game state from your complex Unity-specific engine objects.

Why Decouple Your Data?

In Unity, your game logic often relies on MonoBehaviour scripts or Transform components. If you try to save these directly to a file, you run into two major issues: circular references and engine-dependent bloat. For example, a Transform object contains thousands of lines of engine-level data—most of which you don’t need to persist.

A Data Transfer Object (DTO) is a simple, serializable C# class (often a struct or a [Serializable] class) that contains only the raw primitive values needed to recreate a state. By decoupling your state into DTOs, you ensure your save system remains lightweight and immune to changes in your scene hierarchy.

Designing the DTO

Instead of saving a GameObject or a PlayerController component, create a clean "Data" class that acts as a blueprint for your state:

[System.Serializable]
public class PlayerData
{
    public float[] position; // Use primitive arrays instead of Vector3
    public int health;
    public string playerName;
}

In your controller, you map your active state to the DTO before saving:

public PlayerData ToDTO()
{
    return new PlayerData {
        position = new float[] { transform.position.x, transform.position.y, transform.position.z },
        health = this.currentHealth,
        playerName = this.name
    };
}

The Benefits

  1. Flexibility: If you rename a component or move it in the scene hierarchy, your saved JSON files remain valid because they don't contain hardcoded references to the object's original path.
  2. Performance: You reduce the disk I/O load by only writing necessary primitives rather than serializing the overhead of an entire Component or GameObject.
  3. Safety: DTOs act as a buffer. You can validate the data within the DTO class before applying it to your active game systems, preventing corrupted values from crashing your game logic during loading.

Key Takeaway: By isolating your game state into lightweight, serializable DTOs, you decouple your data persistence from the volatile structure of your Unity scene, ensuring long-term compatibility and improved performance.