-
Notifications
You must be signed in to change notification settings - Fork 0
Asset Management
Void's asset system handles loading, caching, and managing all your game assets: textures, sounds, fonts, levels, and shaders. It's designed to be simple to use while handling complexity behind the scenes.
Loading an asset is straightforward. You call the asset manager and tell it what type you want and the path to the file.
var texture = AssetManager.Instance.Load<Texture>("player.png");
var sound = AssetManager.Instance.Load<Sound>("explosion.wav");
var font = AssetManager.Instance.Load<SpriteFont>("Fonts/arial.png");
var level = AssetManager.Instance.Load<LDtkMap>("Maps/level1.ldtk");
The asset manager finds files through the mount system. By default, it looks in the Content folder of your project. The path is relative to the content root.
When you load an asset, the asset manager keeps it in memory. If you request the same asset again, you get the cached version. Loading from cache is instant. No disk I/O, no parsing, no decompression. Just a dictionary lookup.
Assets are automatically unloaded after a configurable idle time. If you haven't used an asset for 30 minutes (configurable), the asset manager evicts it from memory. It reloads automatically when requested again. This keeps memory usage under control without manual management.
You can adjust the eviction timeout with GameSettings:
GameSettings.Instance.SetAssetEviction(15); // Evict after 15 minutes
You can also adjust how often the asset manager checks for expired assets:
GameSettings.Instance.SetAssetCheckIntervalMinutes(5); // Check every 5 minutes
- Texture: .png, .jpg, .bmp, .tga, .gif — Load with Load()
- Sound: .wav, .ogg, .mp3, .flac — Load with Load()
- Shader: .shader — Load with Load()
- LDtkMap: .ldtk, .json — Load with Load()
- SpriteFont: .png — Load with LoadSpriteFont() or Load()
- Spritesheet: .sheet, .json — Load with Load()
SpriteFonts support custom settings like character sets, spacing, and line spacing. The recommended approach is to load the font once with your custom settings, then use Load or TryLoad everywhere else in your code.
Load the font with settings on startup:
var font = AssetManager.Instance.LoadSpriteFont(
"Fonts/arial.png",
spacing: 0f,
lineSpacing: 1.2f,
charset: SpriteFont.CharsetFull
);
The LoadSpriteFont method accepts three optional parameters:
- spacing: Additional space between characters (default: 0)
- lineSpacing: Space between lines of text (default: 0)
- charset: Which characters to include in the font (default: CharsetFull)
After the font is loaded with your settings, any subsequent call to Load<SpriteFont>("Fonts/arial.png") or TryLoad<SpriteFont>("Fonts/arial.png") will return the cached font with the same settings. You don't need to pass settings again.
This keeps your code clean and ensures consistent appearance throughout your game. This also applies to all asset types that have custom load functions.
You can register your own asset types. Create a class that implements IAsset, then register it with the asset manager.
public class MyAsset : IAsset
{
public uint Id { get; }
public string Tag { get; }
public byte[] Data { get; }
public bool IsValid { get; }
public AssetType Type => AssetType.Normal;
public DateTime LastAccessTime { get; }
public void Load() { /* Load from Data */ }
public void Unload() { /* Unload resources */ }
public void Dispose() { /* Clean up */ }
}
Once your class is defined, register it with the asset manager:
AssetManager.Instance.RegisterAssetType<MyAsset>(
new[] { ".myasset", ".mya" },
(id, data, tag) => new MyAsset(id, data, tag)
);
After registration, you load your custom assets the same way as built-in types.
var myAsset = AssetManager.Instance.Load<MyAsset>("data.myasset");
The asset manager uses a mount system to find files. Mounts are searched in priority order. The default mount is the Content folder in your project root.
You can add additional mounts:
var pack = AssetManager.Instance.LoadPack("GameAssets.pack", "GameAssets.key");
AssetManager.Instance.AddMountToStart(pack);
This loads an encrypted pack as a mount. The asset manager will search the pack before the Content folder. Once a pack is loaded, your existing asset paths don't change. Whether assets are loose files in Content or packed into an encrypted archive, Load<Texture>("player.png") works the same way. Converting to a pack requires no code changes or restructuring.
You can load multiple packs if you split your assets by type. For example, you might have one pack for graphics, another for sounds, and a third for levels. This keeps your project organized and allows for selective updates.
The mount system also supports indexed packs. If your project is large or you have multiple teams working on different parts, you can split a pack into multiple files:
GameAssets-0.pack
GameAssets-1.pack
GameAssets-2.pack
The LoadAllPacks method automatically discovers and mounts all indexed packs in a directory. Each pack is mounted in order, and the asset manager searches them sequentially. This allows you to distribute updates or DLC as additional indexed packs without rebuilding the entire archive.
You can also add custom mounts for other sources:
AssetManager.Instance.AddMountToEnd(new NetworkMount("//server/assets/"));
Mounts can be added to the start or end of the search order. Mounts added to the start are searched first. Mounts added to the end are searched last.
Void assets can be packed into encrypted archives. See the Asset Packer page for details.