tag@ao_serialize

The @ao_serialize annotation controls which fields are persisted and editable in the inspector.

@ao_serialize is the annotation you place on struct/class fields to opt them into the engine's serialization system. Without it, a field is runtime-only — it won't be saved, won't appear in the inspector, and won't be included when the scene is written to disk.

Enemy :: class : Component {
    // Saved, shown in inspector, included in scene data
    max_health: int @ao_serialize;
    patrol_radius: float @ao_serialize;

    // Runtime-only — not saved, not in inspector
    current_target: v2;
    aggro_timer: float;
}

What it does

When you mark a field with @ao_serialize, the engine will:

  1. Show it in the inspector so you can edit it on entities in the editor.

  2. Save it with the scene so the value is restored when the scene loads.

  3. Include it in JSON serialization (Save.set_json / Save.try_get_json).

Fields without @ao_serialize exist only in memory at runtime. They start at their default (zero) value each time the component is created or the scene is loaded.

Supported types

@ao_serialize works with all common CSL types:

Type
Example

Integers

s8, s16, s32, s64 / int

Unsigned

u8, u16, u32, u64 / uint

Floats

f32 / float, f64

Booleans

bool

Strings

string

Vectors

v2, v3, v4

Enums

Any user-defined enum

Fixed arrays

[N]T

Dynamic arrays

[..]T

Structs / classes

Nested types (their @ao_serialize fields are included recursively)

circle-info

For nested structs/classes, only the fields marked @ao_serialize inside the nested type are serialized. The annotation doesn't cascade — you must mark each field individually.

Using with components

The most common use is on component fields. These become editable in the editor's inspector and are saved as part of the scene.

You can set capacity, loot_table, and is_locked per-entity in the editor. When the scene loads, those values are restored automatically.

Using with the Save system

@ao_serialize also controls which fields are included when you use the JSON save APIs. Only marked fields are written to JSON.

For full details on the Save system, see Save System and JSON Serialization.

Using with standalone JSON

You can serialize any annotated type to/from a JSON string, independent of the Save system:

Default values and zero-filling

When deserializing, fields that are missing from the data (e.g. you added a new field after players already have saves) are zero-filled:

  • Numbers → 0

  • Booleans → false

  • Strings → ""

  • Arrays → empty

If zero isn't a sensible default, check and fill in your own defaults after loading:

What NOT to serialize

Not every field should be serialized. Leave @ao_serialize off fields that are:

  • Derived at runtime (positions computed each frame, cached lookups)

  • Temporary state (timers, cooldown counters, frame-local flags)

  • Large data that changes every frame (unnecessary save overhead)

A good rule of thumb: if the value is set once (in the editor or on load) and rarely changes, serialize it. If it's recomputed every frame, don't.

Common patterns

Enums for mode selection

Nested structs

Asset references

Some fields reference engine assets (textures, prefabs, sounds). These are serialized as asset identifiers and resolved automatically on load. See the built-in components (like Sprite_Renderer) for examples.

Last updated