Skip to content

4. Asset loading

Joni Savolainen edited this page Oct 22, 2022 · 2 revisions

IAssetResolver

IAssetResolver is an interface for classes whose purpose is to load assets and determine whether they exist.

public interface IAssetResolver
{
    Task<T> LoadAsset<T>(string assetPath) where T : UnityEngine.Object;

    Task<bool> AssetExists(string assetPath);
}

ResourcesAssetResolver

UIComponents load assets from Resources by default using ResourcesAssetResolver. To use a different method, declare a different provider for the IAssetResolver dependency. See an example below.

AddressableAssetResolver

AddressableAssetResolver is accessible via the UIComponents.Addressables namespace.

using UIComponents;
using UIComponents.Addressables;

[Layout("UI/Components/MyComponent.uxml")]
[Dependency(typeof(IAssetResolver), provide: typeof(AddressableAssetResolver))]
public partial class MyComponent : UIComponent {}

Create your own

Creating your own IAssetResolver is simple. An implementation for loading assets from AssetDatabase may look something like this:

using UnityEditor;
using System.Threading.Tasks;

public class AssetDatabaseAssetResolver : IAssetResolver
{
    public Task<T> LoadAsset<T>(string assetPath) where T : UnityEngine.Object
    {
        var asset = AssetDatabase.LoadAssetAtPath<T>(assetPath);
        return Task.FromResult(asset);
    }

    public Task<bool> AssetExists(string assetPath)
    {
        var assetGuid = AssetDatabase.AssetPathToGUID(assetPath);
        var assetExists = !string.IsNullOrEmpty(assetGuid);
        return Task.FromResult(assetExists);
    }
}
[Layout("Assets/Components/MyComponent.uxml")]
[Dependency(typeof(IAssetResolver), provide: typeof(AssetDatabaseAssetResolver))]
public partial class MyComponent : UIComponent {}

Common asset paths

You will likely have your layout and stylesheet assets in one place. The [AssetPrefix] attribute is used to attach a prefix to every asset path.

Here is an example of its usage alongside asset loading using Addressables:

[AssetPrefix("UI/Components/MyComponent/")]
[Layout("MyComponent.uxml")]
[Stylesheet("MyComponent.style.uss")]
[Dependency(typeof(IAssetResolver), provide: typeof(AddressableAssetResolver))]
public partial class MyComponent : UIComponent {}

[AssetPrefix] doesn't have much of an impact when applied to a single component. However, it can be applied to a parent class and inherited.

[AssetPrefix("UI/Components/")]
[Dependency(typeof(IAssetResolver), provide: typeof(AddressableAssetResolver))]
public abstract class BaseComponent : UIComponent {}

[Layout("MyComponent/MyComponent.uxml")]
[Stylesheet("MyComponent/MyComponent.style.uss")]
public partial class FirstComponent : BaseComponent {}

[Layout("SecondComponent/SecondComponent.uxml")]
[Stylesheet("SecondComponent/SecondComponent.style.uss")]
public partial class SecondComponent : BaseComponent {}
Clone this wiki locally