Skip to content

Author a resource provider asset

A GUIResourceProvider is a ScriptableObject asset that holds fonts, images, and shaders for one provider in the chain. The asset has Inspector tooling that bulk-imports assets from a directory, which scales well when a project ships dozens of icons or font sizes. This page covers creating the asset, populating it manually, and using the auto-import toggles.

For the chain itself and how providers stack, refer to Resource providers. For the narrower task of registering a single font, refer to Add a custom font.

Create a provider asset

To create a provider asset:

  1. Right-click in the Project window.
  2. Choose Create > Interlude Software > UI > GUIResourceProvider.
  3. Name the asset for what it carries (ThemeDarkResources, LocalisedFR, etc.).
  4. Add the asset to the Resource Providers array on BaseGameUI in priority order. Index 0 is checked first.

Asset fields

Field Type Purpose
m_images List<Texture> Icon and image entries. Looked up by Texture.name through TryGetImage.
m_fonts List<FontDefinition> Font entries. Each holds an MSDF atlas texture and a JSON metrics asset.
m_shaders List<Shader> Shape and text shader overrides. Looked up by Shader.name through TryGetShader.
m_sortAndRemoveDupes bool Editor toggle. On the next OnValidate, sorts m_images by name, removes duplicates, and clears the flag.
m_populateFromFontDir bool Editor toggle. On the next OnValidate, walks the subdirectories of m_directory for matching .png and .json pairs and rebuilds m_fonts.
m_populateImagesFromDirectory bool Editor toggle. On the next OnValidate, loads every .png in m_directory into m_images.
m_copyTexturesToDirectory bool Editor toggle. On the next OnValidate, copies the textures already in m_images into m_directory.
m_directory string The filesystem path used by the three import toggles. Project-relative (Assets/...) or absolute.

The Init*ByName methods build name-keyed dictionaries lazily on the first TryGet* call. Editing the asset at runtime requires forcing a re-initialisation. To swap resources at runtime, create a new provider and push it through CompositeResourceProvider.Push.

FontDefinition

A FontDefinition is a class holding two references:

Field Type Purpose
Texture Texture2D The MSDF atlas image.
MetricsPath TextAsset A JSON file with kerning and glyph rects.

Font lookups key on the file name with any atlas-type suffix (_msdf, _mtsdf, or _sdf) and the trailing _NN size segment stripped. A pair named roboto_mono_14_msdf.png plus roboto_mono_14_msdf.json registers as font name roboto_mono at size 14 — the layout the Font Atlas Generator produces. The size comes from the JSON. The file-name convention keeps the listing readable.

The bundled DefaultTickConfig ships fourteen roboto_mono font entries (sizes 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, and 64), eight icon textures, and ten shape and text shaders. A project that defines no providers still renders correctly because every lookup falls through to the default.

Bulk-import fonts from a directory

m_populateFromFontDir rebuilds m_fonts from a directory of font subdirectories. Each subdirectory holds one font family and its size variants:

Assets/UI/Fonts/
├── inter/
│   ├── inter_14_msdf.png
│   ├── inter_14_msdf.json
│   ├── inter_18_msdf.png
│   ├── inter_18_msdf.json
│   ...
└── jetbrains_mono/
    ├── jetbrains_mono_14_msdf.png
    ├── jetbrains_mono_14_msdf.json
    ...

To run the import:

  1. Set m_directory to the parent directory (Assets/UI/Fonts in the example above).
  2. Tick m_populateFromFontDir.
  3. Save the asset (or trigger another OnValidate by clicking off and back onto the asset).

The walker collects every .png plus matching .json pair in each subdirectory, builds a FontDefinition, and clears the toggle. Tick the toggle again to re-run.

Bulk-import images from a directory

m_populateImagesFromDirectory imports images. With m_directory set, the toggle loads every .png in that directory into m_images. The load is non-recursive, so it skips subdirectories.

m_copyTexturesToDirectory copies the textures already referenced in m_images into m_directory. Use it to collect scattered icons into one folder before sharing the provider.

m_sortAndRemoveDupes operates only on m_images. It sorts by texture name and drops anything that shares a name with an earlier entry. It leaves the fonts and shaders lists untouched.

Verify the asset

After you populate the asset, add it to BaseGameUI and confirm the following:

  • Text renders with the expected font at the expected sizes. A missing size logs a warning and falls back to the next provider in the chain.
  • Icon lookups resolve. ImageByName("missing") draws nothing. Check the resource provider chain if an icon is unexpectedly blank.
  • Shaders compile. A missing shader renders pink. The bundled default ships the standard set. A custom provider with half-populated shaders lets the missing slots fall through.

Pitfalls

The font shows up but at the wrong size. : The font registers under a key derived from the JSON file name. If two fonts share a key, the first wins. Rename one of the JSON metrics files.

m_populateFromFontDir rebuilds an empty list. : m_directory does not contain the expected subdirectories, or the import is running against an absolute path on a different machine. Use a project-relative path.

m_directory looks wrong on a teammate's machine. : The string is serialised as an absolute path on the machine that imported it. Edit the asset YAML or re-run the import locally.

Auto-import toggles re-fire every save. : OnValidate clears each toggle after it runs, but a third-party tool might re-tick the field. Inspect the asset with Open as Text if a teammate reports surprise re-imports.

A custom provider shadows the default. : The custom provider lists a font with the same name as the bundled default. The custom version wins because it sits higher in the chain. Rename the font, or remove it from the custom provider so the default supplies it.

Additional resources