Skip to main content
AssetManager is Prisma Engine’s central subsystem for loading, caching, and releasing game assets at runtime. It integrates with the engine’s JobSystem for non-blocking async loads, maintains an internal hash-keyed cache to avoid duplicate disk reads, and searches across configurable root paths to resolve relative asset references. All asset types — TextureAsset, MeshAsset, TilemapAsset, and CubemapTextureAsset — are loaded through this single interface.
AssetManager must be explicitly initialized with a project root before any load calls. Calling Load() on an uninitialized manager crashes intentionally — there is no silent auto-initialization. Call Initialize(projectRoot) during engine startup.

Class declaration

Initialization

Initialize(projectRoot)

Initializes the manager and sets the primary asset search root. Returns true on success. You must call this before any Load() or FindResource() calls.
std::filesystem::path
required
Absolute path to the project’s root directory. Assets are resolved relative to this path.

AddSearchPath(path)

Registers an additional directory to search when resolving relative asset paths. Paths are searched in the order they were added, after the project root.
std::filesystem::path
required
Absolute or project-relative path to add to the search list.

Loading assets

Load<T>(relativePath, args...)

Synchronously loads an asset of type T from disk and stores it in the cache. If the asset is already cached (matched by hashed path), the cached handle is returned immediately without re-reading from disk. Returns an empty (invalid) AssetHandle<T> if the resource cannot be found or fails to load.
std::string
required
Path relative to the project root (or any registered search path). Used as the cache key.
Args&&...
Optional constructor arguments forwarded to T’s constructor before Load() is called.
Load() runs on the calling thread. Avoid calling it on the render thread for large assets. Use LoadAsync() instead.

LoadAsync<T>(relativePath, callback, args...)

Submits an asset load job to the engine’s JobSystem. The callback is invoked with the resulting AssetHandle<T> when loading completes (or with an invalid handle on failure). If the asset is already cached, the callback fires immediately on the calling thread without dispatching a job.
std::string
required
Relative path used to locate and cache the asset.
std::function<void(AssetHandle<T>)>
required
Invoked with the loaded handle. Check IsValid() before use — the handle may be empty if loading failed.
Args...
Constructor arguments captured by value and forwarded to T on the job thread.
The callback is called from a worker thread. Synchronize access to shared state accordingly.

GetCachedAsset<T>(hash)

Retrieves an already-loaded asset from the cache by its string hash without triggering a disk read. Returns an invalid handle if the hash is not in the cache.

Unloading assets

Unload(name)

Removes the named asset from the cache. The underlying asset data is released when no more AssetHandle instances hold a reference to it (reference-counted via std::shared_ptr).
std::string
required
The relative path string used when the asset was originally loaded.

UnloadAll()

Removes every cached entry. Assets currently held by live AssetHandle instances remain valid until those handles go out of scope.

Path resolution

FindResource(relativePath)

Searches all registered paths (project root + any added via AddSearchPath) for a file matching relativePath. Returns the first absolute path found, or std::nullopt if no match exists.

AssetHandle

AssetHandle<T> is a strongly-typed, reference-counted wrapper over std::shared_ptr<T>. It is the return type of all load calls.
Always check IsValid() before dereferencing a handle returned by Load() or LoadAsync().

Thread safety

Safe across threads

Load() and LoadAsync() are safe to call from multiple threads. The internal cache uses hash-keyed lookup and assets are registered atomically via RegisterAsset().

Callback threading

LoadAsync() callbacks run on a JobSystem worker thread. Use locks or engine-provided synchronization primitives when writing to shared state inside a callback.

Serialization formats

AssetManager works with two on-disk formats, both handled transparently by each asset type’s Load() implementation:

Integration with HotReloadManager

During editor builds (PRISMA_BUILD_EDITOR=ON), the engine’s HotReloadManager monitors asset directories for file changes. When a source file is modified, it calls Unload() on the affected asset and triggers a fresh Load() on the next frame, ensuring the editor viewport reflects the current state of assets on disk without a full engine restart.
In game builds, hot-reload is disabled. Assets are loaded once and remain cached for the lifetime of the session unless explicitly unloaded.

Lifecycle summary