Iβm currently working on an AR project and trying to display image assets through component schema bindings. I referenced the official Scavenger Hunt example and followed a similar structure β defining the assets in my component schema and assigning the correct assets in the UI editor (as shown in the screenshot below).
Despite setting up the component and assigning the image files (e.g., Bat01.png
, Dog02.png
, etc.) in the Inspector panel under scan_ui_component
, the assets are not loading or displaying as expected during runtime.
Iβve confirmed that:
The schema includes entries like Bat01
, Dog02
, etc., which match the asset filenames
The component is properly added to the entity
The assets are correctly uploaded under the assets/card
folder
There are no console errors thrown during runtime
Can you show the code that uses the asset paths?
The component[cardName] returns the asset path I use for the AR entity, which works fine in the AR scene.
However, when I use the same path for an HTML , the image fails to load (onerror is triggered).
The asset is definitely present in my project and can be selected in the Studio asset dropdown.
I want to know if thereβs a recommended way to get a usable URL for HTML from a Studio asset, or if thereβs something wrong with my approach.
const loadCardImage = (cardName: string, targetImage: HTMLImageElement) => {
const assetPath = component[cardName]
if (!assetPath) {
console.error(`Cannot find asset path for card ${cardName}`)
console.log('Available cards:', Object.keys(component))
return
}
console.log(`Trying to load card ${cardName}:`, assetPath)
ecs.assets.load({ url: assetPath })
.then((asset) => {
targetImage.src = asset.remoteUrl
console.log(`β
${cardName} loaded successfully, URL:`, asset.remoteUrl)
})
.catch((error) => {
console.error(`β Failed to load ${cardName}:`, assetPath)
console.error('Error details:', error)
})
}
Do you have to use HTML in your Studio project? Your best bet is broadcasting out a window level event so the HTML can update it with the correct image.
I tried using window broadcasting to load assets, but the image still shows as not registered. How can I solve this issue?
const loadCardImage = (cardName: string, targetImage: HTMLImageElement) => {
console.log(`π― Attempting to load card: ${cardName} (Broadcasting preferred)`)
// Strategy 1: Check if the Broadcasting system has this card
if ((window as any).isCardAssetReady && (window as any).isCardAssetReady(cardName)) {
const url = (window as any).getCardAssetUrl(cardName)
if (url) {
targetImage.src = url
targetImage.style.backgroundColor = 'transparent'
console.log(`β
${cardName} successfully loaded from Broadcasting`)
return
}
}
// Strategy 2: Check if asset is configured in Schema
const schemaAssetPath = component[cardName]
if (schemaAssetPath && schemaAssetPath.trim() !== '') {
console.log(`π¦ Attempting to load ${cardName} from Schema`)
ecs.assets.load({url: schemaAssetPath})
.then((asset: any) => {
targetImage.src = asset.remoteUrl
targetImage.style.backgroundColor = 'transparent'
console.log(`β
${cardName} successfully loaded from Schema`)
// Auto-register to Broadcasting system
if ((window as any).registerCardAsset) {
(window as any).registerCardAsset(cardName, asset.remoteUrl)
.catch(() => {})
}
})
.catch((error: any) => {
console.warn(`β οΈ Failed to load ${cardName} from Schema. Waiting for Broadcasting...`)
waitForBroadcasting()
})
return
}
// Strategy 3: Listen for Broadcasting event (async)
const waitForBroadcasting = () => {
const placeholder = createPlaceholder(cardName)
if (placeholder) {
targetImage.src = placeholder
}
let timeoutId: any
let isResolved = false
const handleCardLoaded = (event: Event) => {
const customEvent = event as any
const asset = customEvent.detail
if (asset && asset.name === cardName && asset.loaded && !isResolved) {
isResolved = true
targetImage.src = asset.url
targetImage.style.backgroundColor = 'transparent'
console.log(`β
${cardName} successfully loaded asynchronously via Broadcasting`)
cleanup()
}
}
const cleanup = () => {
if (timeoutId) clearTimeout(timeoutId)
window.removeEventListener('card-asset-loaded', handleCardLoaded)
}
window.addEventListener('card-asset-loaded', handleCardLoaded)
timeoutId = setTimeout(() => {
if (!isResolved) {
console.log(`β³ ${cardName} waiting for external registration (using placeholder)`)
cleanup()
}
}, 3000)
console.log(`β³ ${cardName} waiting for Broadcasting registration...`)
}
waitForBroadcasting()
}
I can help, but there might be an easier way to accomplish your end goal. Can you tell me a bit more about what youβre trying to accomplish?
The outcome I want to achieve is as shown in the video below. The entire process involves detecting an image target, then allowing the user to press the shutter to capture the currently recognized image target. The image shown on screen should be displayed in the UI (e.g., in the three slots on the screen), and the images displayed must reference assets.
I was able to get it working like this, with a custom component.
import * as ecs from '@8thwall/ecs'
ecs.registerComponent({
name: 'image-target-to-url',
stateMachine: ({world, eid, schemaAttribute, dataAttribute}) => {
const testMap = new Map()
testMap.set('tower', 'assets/tower.png')
ecs.defineState('default')
.initial()
.onEnter(() => {
const img = document.createElement('img')
img.src = 'https://placehold.co/600x400'
img.style.width = '300px'
img.style.height = 'auto'
img.style.position = 'absolute'
img.style.top = '0'
img.style.left = '0'
img.style.zIndex = '9999'
document.body.appendChild(img)
window.addEventListener('imagefound-update-html', (e) => {
// @ts-ignore
ecs.assets.load({url: testMap.get(e.detail.name)})
.then((asset) => {
console.log(asset)
img.src = `${asset.localUrl}`
})
.catch((e) => {
console.error(e)
})
})
})
.listen(world.events.globalId, 'reality.imagefound', (e) => {
window.dispatchEvent(new CustomEvent('imagefound-update-html', {detail: e.data}))
})
},
})
The most important part in my approach is that I uploaded my image target to my assets folder as well. I had to do this since the image target events donβt send back anything about the image url.
I successfully displayed the assets, thank you for your example!
1 Like
system
Closed
June 22, 2025, 2:11am
10
This topic was automatically closed 4 days after the last reply. New replies are no longer allowed.