4.1 KiB
Asset Database Documentation
The Asset Database is a core component of the Ghost Editor responsible for managing the lifecycle, storage, import, and retrieval of project assets. It provides a unified API for interacting with assets, ensuring that metadata (GUIDs, tags, settings) stays synchronized with files on disk.
Key Features
- GUID-based Asset Identification: Every asset is uniquely identified by a stable GUID, stored in a sidecar
.gmetafile. - Automatic Importing: Monitors the file system for changes and automatically imports assets using registered importers.
- Dependency Tracking: Tracks dependencies between assets to ensure validity and trigger re-imports when dependencies change.
- Caching: Implements an LRU (Least Recently Used) cache for loaded assets to optimize performance.
- SQLite Backed: Uses a local SQLite database for fast lookups (Path <-> GUID) and metadata queries.
- Metadata Management: Handles
.gmetafiles automatically, including generation, validation, and cleanup.
usage
Initialization
The Asset Database must be initialized after the project is loaded.
await AssetDatabase.Initialize(cancellationToken);
Loading Assets
Assets can be loaded by GUID or by Path.
// Load by Path
var result = AssetDatabase.LoadAssetAtPath<TextureAsset>("Assets/Textures/my_texture.png");
if (result.IsSuccess)
{
var texture = result.Value;
}
// Load by GUID
var guid = ...;
var result = AssetDatabase.LoadAsset<TextureAsset>(guid);
File Operations
Always use the AssetDatabase API for file operations to ensure metadata is preserved.
// Create
await AssetDatabase.CreateAssetAsync("Assets/Data/config.json", dataBytes);
// Move
await AssetDatabase.MoveAssetAsync("Assets/Old/file.txt", "Assets/New/file.txt");
// Copy
await AssetDatabase.CopyAssetAsync("Assets/template.txt", "Assets/instance.txt");
// Delete
await AssetDatabase.DeleteAssetAsync("Assets/garbage.tmp");
Searching
Find assets using wildcards or tags.
// Find all PNGs
var guids = await AssetDatabase.FindAssetsByNameAsync("*.png");
// Find assets with a specific tag
var enemyAssets = await AssetDatabase.FindAssetsByTagAsync("Enemy");
Tags
Manage asset tags for organization.
// Get tags
var tagsResult = await AssetDatabase.GetAssetTagsAsync(guid);
// Set tags
await AssetDatabase.SetAssetTagsAsync(guid, new List<string> { "Level1", "Prop" });
Opening Assets
Open an asset using its registered handler or the system default.
AssetDatabase.OpenAsset("Assets/Docs/readme.txt");
Extending the Asset Database
Creating a New Importer
To support a new file type, create a class that inherits from AssetImporter<T> and decorate it with the [AssetImporter] attribute.
[AssetImporter(".myfmt")]
internal class MyFormatImporter : AssetImporter<MyFormatSettings>
{
public override async Task<Result> ImportAsync(string assetPath, AssetMeta meta)
{
var settings = GetSettings(meta);
// 1. Read source file
// 2. Process data
// 3. Save imported data using AssetDatabase.SaveImportedAsset
var myAsset = new MyAsset(meta.Guid) { ... };
return AssetDatabase.SaveImportedAsset(meta.Guid, myAsset);
}
}
internal class MyFormatSettings : ImporterSettings
{
public float Scale { get; set; } = 1.0f;
}
Creating an Open Handler
To define custom behavior when an asset is opened (e.g., double-clicked in the editor), use the [AssetOpenHandler] attribute.
internal static class MyHandlers
{
[AssetOpenHandler(".myfmt")]
private static void OpenMyFormat(string path)
{
// Open custom editor window
}
}
Internal Architecture
- AssetDatabase.cs: Core initialization and event coordination.
- AssetDatabase.SQLite.cs: Database table management and queries.
- AssetDatabase.Meta.cs:
.gmetafile handling and file system watcher events. - AssetDatabase.Importer.cs: Importer discovery and execution.
- AssetDatabase.Loader.cs: Asset loading and caching logic.