Asset Loading#
Load images, fonts, and data files from your project. The asset system handles path resolution automatically between Editor and builds.
Quick Start#
Place files in the assets/ folder inside your working directory, then load them by relative path:
~/ ← Working directory
├── assets/
│ ├── logo.png
│ ├── fonts/
│ │ └── Inter.ttf
│ └── data/
│ └── config.json
├── index.tsx
└── esbuild.config.mjsimport { loadImage, loadFont, loadJson } from "onejs-unity/assets"
const logo = loadImage("logo.png")
const font = loadFont("fonts/Inter.ttf")
const config = loadJson("data/config.json")All paths are relative to assets/. No absolute paths needed.
Functions#
| Function | Returns | Description | |
|---|---|---|---|
loadImage(path) | Texture2D \ | VectorImage | Load an image (PNG, JPG, SVG) |
loadFont(path) | Font | Load a font file (TTF, OTF) | |
loadFontDefinition(path) | FontDefinition | Load a font for UI Toolkit styling | |
loadText(path) | string | Load a text file | |
loadJson<T>(path) | T | Load and parse a JSON file | |
loadBytes(path) | Uint8Array | Load raw bytes | |
assetExists(path) | boolean | Check if an asset exists | |
getAssetPath(path) | string | Get the resolved full path |
Using with Components#
The <Image> component's src prop is the simplest way to display images:
import { Image } from "onejs-react"
// Loads from assets/hero.png
<Image src="hero.png" style={{ width: 200, height: 200 }} />For background images and custom fonts, use the load functions directly:
import { loadImage, loadFontDefinition } from "onejs-unity/assets"
// Background image on any element
<View style={{ backgroundImage: loadImage("bg.png"), width: 300, height: 200 }} />
// Custom font
<Label style={{ unityFontDefinition: loadFontDefinition("fonts/Inter.ttf") }}>
Custom font text
</Label>Path Resolution#
In the Editor, assets load directly from the filesystem. In builds, they load from StreamingAssets.
| Context | Resolved path for logo.png |
|---|---|
| Editor | {WorkingDir}/assets/logo.png |
| Build | {StreamingAssets}/onejs/assets/logo.png |
Builds#
Assets are copied to StreamingAssets automatically during Unity builds. The JSRunnerBuildProcessor handles this:
- Finds each JSRunner's working directory
- Copies
{WorkingDir}/assets/toAssets/StreamingAssets/onejs/assets/ - Skips
.metafiles - Flushes the destination first to remove stale files
assets/ and they'll be available in builds.
Unity Resources#
For assets that Unity processes at import time, you can use Unity's built-in Resources folder instead. Place files in Assets/Resources/, and Unity will import them as native asset types (e.g., SVG → VectorImage, PNG → Texture2D).
import { Image } from "onejs-react"
import { VectorImage } from "UnityEngine/UIElements"
const icon = CS.UnityEngine.Resources.Load("icon", VectorImage)
<Image image={icon} style={{ width: 64, height: 64 }} />The path passed to Resources.Load is relative to any Resources/ folder and omits the file extension.
assets/ vs Resources/#
assets/ folder | Resources/ folder | |
|---|---|---|
| Location | {WorkingDir}/assets/ | Assets/Resources/ |
| Loading | loadImage(), loadFont(), etc. | Resources.Load() |
| Processing | Raw files, read at runtime | Unity-imported at build time |
| Best for | Images, fonts, JSON, text data | Assets needing Unity import processing |
assets/ folder is all you need. Use Resources/ when you specifically need Unity's asset pipeline to process the file first.
Async Resource Loading#
For loading Unity resources without blocking, use the loadResourceAsync global:
// Load a TextAsset from Resources/
const textAsset = await loadResourceAsync("MyData/config", CS.UnityEngine.TextAsset)
console.log(textAsset.text)
// Load without specifying type (returns UnityEngine.Object)
const asset = await loadResourceAsync("MyData/config")
// Returns null for non-existent resources (no exception)
const missing = await loadResourceAsync("DoesNotExist")
// missing === nullloadResourceAsync is also available as a named import from onejs-unity/assets:
import { loadResourceAsync } from "onejs-unity/assets"With React:
import { useState, useEffect } from "react"
function ConfigPanel() {
const [config, setConfig] = useState(null)
useEffect(() => {
let cancelled = false
async function load() {
const asset = await loadResourceAsync("GameConfig", CS.UnityEngine.TextAsset)
if (!cancelled && asset) {
setConfig(JSON.parse(asset.text))
}
}
load()
return () => { cancelled = true }
}, [])
if (!config) return <Label text="Loading..." />
return <Label text={`Difficulty: ${config.difficulty}`} />
}loadImage / loadText | loadResourceAsync | |
|---|---|---|
| Source | assets/ folder (raw files) | Unity Resources/ folder |
| Sync/Async | Synchronous | Asynchronous (returns Promise) |
| Asset processing | Raw bytes/text at runtime | Unity-imported at build time |
| Not found | Throws error | Returns null |
Package Assets#
npm packages can distribute assets using the @namespace/ convention:
my-ui-kit/
├── package.json
├── assets/
│ └── @my-ui-kit/
│ ├── icons/
│ │ └── check.png
│ └── backgrounds/
│ └── gradient.png
└── src/
└── index.tsLoad them with the @ prefix:
const icon = loadImage("@my-ui-kit/icons/check.png")The @namespace/ folder is detected automatically. In the Editor, assets resolve through node_modules. In builds, they're copied alongside project assets to StreamingAssets/onejs/assets/@my-ui-kit/.
To include package assets in the manifest for Editor resolution, add copyAssetsPlugin to your esbuild config:
import { copyAssetsPlugin } from "onejs-unity/esbuild"
const config = {
plugins: [
copyAssetsPlugin(),
],
}This generates .onejs/assets-manifest.json which maps @namespace/ prefixes to their node_modules locations.