-
Notifications
You must be signed in to change notification settings - Fork 9
4. Asset loading
IAssetSource is the interface that UIComponents uses to load assets. Each source
handles both path resolution and asset loading for a given backend.
public interface IAssetSource
{
Task<T> LoadAsset<T>(string assetPath) where T : UnityEngine.Object;
Task<bool> AssetExists(string assetPath);
}UIComponents load assets from Resources by default using ResourcesAssetSource. To use a different
backend, declare a different provider for the IAssetSource dependency.
AssetDatabaseAssetSource is accessible via the
UIComponents.Editor namespace. It is useful for editor extensions.
When using convention-based [Layout] and [Stylesheet] (without explicit paths),
AssetDatabaseAssetSource searches for matching assets within the [AssetRoot] directory
using AssetDatabase.FindAssets. It supports both flat and nested directory layouts.
using UIComponents;
using UIComponents.Editor;
[AssetRoot("Packages/org.example.mypackage/UI/")]
[Layout]
[Stylesheet]
[Dependency(typeof(IAssetSource), provide: typeof(AssetDatabaseAssetSource))]
public partial class MyComponent : UIComponent {}This will search for MyComponent.uxml and MyComponent.style.uss anywhere
within the Packages/org.example.mypackage/UI/ directory tree.
Explicit paths with file extensions are passed through without searching:
[Layout("Packages/org.example.mypackage/UI/MyComponent.uxml")]
[Dependency(typeof(IAssetSource), provide: typeof(AssetDatabaseAssetSource))]
public partial class MyComponent : UIComponent {}AddressableAssetSource is accessible via the
UIComponents.Addressables namespace.
using UIComponents;
using UIComponents.Addressables;
[Layout("UI/Components/MyComponent.uxml")]
[Dependency(typeof(IAssetSource), provide: typeof(AddressableAssetSource))]
public partial class MyComponent : UIComponent {}You will likely have your layout and stylesheet assets in one place. The
[AssetRoot] attribute specifies a root path that is prepended to every asset path.
[AssetRoot] is most useful when applied to a base class and inherited:
[AssetRoot("UI/Components/")]
[Dependency(typeof(IAssetSource), provide: typeof(AddressableAssetSource))]
public abstract class BaseComponent : UIComponent {}
[Layout]
[Stylesheet]
public partial class FirstComponent : BaseComponent {}
[Layout]
[Stylesheet]
public partial class SecondComponent : BaseComponent {}With AssetDatabaseAssetSource, [AssetRoot] acts as a convention root — the source
searches for assets by name within that directory. With other sources, the root is
prepended to the asset path as a prefix.
[AssetRoot] also works with explicit paths:
[AssetRoot("UI/Components/MyComponent/")]
[Layout("MyComponent.uxml")]
[Stylesheet("MyComponent.style.uss")]
[Dependency(typeof(IAssetSource), provide: typeof(AddressableAssetSource))]
public partial class MyComponent : UIComponent {}UIComponents generates a UIComponentAssetRegistry per assembly, mapping component
types to their asset paths. You can validate these paths in the Unity Editor via
Window > UIComponents > Validate Registry Asset Paths.
The validator checks whether registered asset paths resolve to files on disk via
AssetDatabase or Resources. If a component uses a custom IAssetSource that
resolves convention paths at runtime (e.g., AssetDatabaseAssetSource), the
validator may report convention paths as unresolved — this is expected, since
convention resolution happens at runtime inside the source.