Set fallback material for USDZ exporter

If you want to set a fallback material for an object that will be exported as USDZ (for AR-mode on iOS), you can add this script to the object, which material should be replaced.

This is especially useful if you use custom shaders in your scene (they are visible on Desktop+WebXR, but not in AR on iOS).

import { Behaviour, GameObject, Renderer, USDZExporter, serializable } from "@needle-tools/engine";
import { Material, Object3D } from "three";

export class FallbackMaterial extends Behaviour {

    fallbackMaterial!: Material;

    private originalMaterial?: Material;
    private usdzExporter!: USDZExporter;

    onEnable() {
        this.usdzExporter = GameObject.findObjectOfType(USDZExporter)!;

    onDisable() {

    private subscribeToBeforeExportEvent() {
        this.usdzExporter.addEventListener("before-export", this.onBeforeExport);
        this.usdzExporter.addEventListener("after-export", this.onAfterExport);

    private unsubscribeFromBeforeExportEvent() {
        this.usdzExporter.removeEventListener("before-export", this.onBeforeExport);
        this.usdzExporter.removeEventListener("after-export", this.onAfterExport);

    onBeforeExport = () => {
        const renderer = this.gameObject.getComponent(Renderer)!;
        this.originalMaterial = renderer.sharedMaterial;
        renderer.sharedMaterial = this.fallbackMaterial;


    onAfterExport = () => {
        const renderer = this.gameObject.getComponent(Renderer)!;
        renderer.sharedMaterial = this.originalMaterial;