Assets, scenes, and packaging
A resource reference identifies a project file. Loading that reference produces caller-owned CPU data; rendering a Mesh uses renderer-owned GPU caches. Those objects have different lifetimes even when they refer to the same model or image. The loading guide shows the calls for each task.
The asset catalog connects source files to packaged data
The editor keeps one hidden catalog, .eggy/assets.zon, giving every file and folder in
resources/ an ID, a kind, and (for models) an import scale. Editor file operations keep
IDs through moves, renames, and trash and restore; copies receive new IDs. Keep the catalog
in version control with the assets. Projects from older versions have <file>.eggy
descriptors beside their resources: the editor moves them into the catalog when it opens the
project, then deletes them.
A model file opens in the Assets panel into its geometry (Skeletal when the model has
animation clips, else Static), one entry for each of its clips, and one image for each
texture its materials use (Material 1 and on). Those entries have IDs of their own, so a
reference field can name a single clip or texture, but they are not files: they can't be
renamed, moved, or deleted. Drag a material onto a folder (or right-click it and choose
Extract as PNG) to save its texture there as a PNG you can edit in any image editor.
The editor refreshes model and image imports after changes. Packaging converts models
to .eggmodel and decoded images to .eggtexture, copies other resources unchanged,
and names the packaged files after their IDs in data/. Game code refers to assets by
reference, which the build resolves to IDs; it must not reconstruct packaged filenames.
Scene instances belong to the world
A SceneInstance root refers to a source scene. Saving the containing scene stores
that instance, not its generated descendants. Refreshing the source scene updates
each instance. The editor selects the instance root and hides generated descendants
in the Hierarchy; edit them by opening the source scene.
Instantiated entities keep the source scene's parent tree, with entity references remapped to the new entities. Recursive scene instances are prevented. Components or fields no longer known by the project are logged and skipped, as when the editor opens an older scene.
The world owns the returned root and generated entities. Immediate scene entities
exist before app.scenes().instantiate returns; nested instances synchronize at the
normal scene-sync point. A failed read, parse, or allocation removes entities created
by that call. Borrowed service views and component pointers do not survive a world
reset or reload. See ownership and reload.
Startup scene choices
The runtime starts in the scene named by -Dscene, otherwise the project's default
scene. A local runtime build may fall back to the scene last open in the editor, then
the first scene. Export requires an explicit or default startup scene. The
project configuration reference covers these
settings, and build and export covers choosing them
for a build.
Low-level scene access
Tools that need diagnostics and entity lists can use Scene.capture, parse,
write, and instantiate directly.
scene.Access.readFieldAlloc(gpa, world, entity, component, field) returns complete
field ZON. nameAlloc(gpa, world, entity) returns an entity name, or null when it has
none. Free each returned string with gpa.free. Field reads report missing components
or fields as errors. The buffer-based readField and name are available when the
caller manages storage.
Engine-free format tools
Build tools can import eggy_assets without linking App, SDL, GPU, or editor code:
const engine = b.dependency("eggy", .{ .target = target, .optimize = optimize });
tool.root_module.addImport("eggy_assets", engine.module("eggy_assets"));
Its catalog, model, imported-clip, and texture formats use explicit readers, writers,
allocators, and std.Io where needed. Games can also access it as eggy.assets.
Browser builds read their preloaded packaged resources synchronously. Async reads and
streaming still return NotImplemented.
Switch levels
Call try app.scenes().replace(.init("resources/levels/next.scene.zon")) from game code.
Eggy reads and parses the target immediately, then commits it after the current gameplay
hooks and systems finish. Only one replacement can be pending.
The old entities remain until the new scene instantiates successfully. A missing file or invalid scene reports an error rather than clearing the current level. Unknown or invalid components reject the replacement rather than loading a partially defaulted level.
Replacement removes all old entities, including entities created by game code. Plugin instances, world resources, schedules, preferences and game UI survive; store cross-level progress there, not in an entity you expect to survive. Resolve entity references again after switching. Nested scene instances populate at the usual scene-sync point.