For the complete documentation index, see llms.txt. This page is also available as Markdown.

@ao_serialize

Select fields for scene, Inspector, and JSON serialization.

@ao_serialize is the annotation you place on struct/class fields to opt them into the engine's serialization system. Adding this allows you to edit script fields in the editor for easy customization and is also required if you intend to use JSON serializations/save data for structs.

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. Include it in JSON serialization (Save.set_json / Save.try_get_json).

Fields without @ao_serialize exist only in memory at runtime. They start from their normal initializer each time the component is created, but are not included in scene or JSON serialization.

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)

Engine references

Entities, components, and assets where supported

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 schema changes

Class fields can have constant inline defaults. Put @ao_serialize after the initializer:

When a serialized field is missing, class deserialization keeps that field's default. Unknown fields are ignored. Struct fields cannot have inline defaults, so initialize a struct before deserializing when it needs non-zero values.

Fixed-array deserialization is bounded by the destination size. Extra JSON items are ignored. If the input is shorter, untouched elements keep their initialized values.

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.

Marking a component field does not by itself persist runtime changes across sessions. Use Save, Economy, or Inventory when that persistence is required.

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