Problem with playing animations and ChangeTransformOnClick in Quicklook

Hi there,
I try to implement kind of interface, where I can play animations and also use ChangeTransformOnClick etc… Both things are working, when used separately, but as soon I have any haveChangeTransformOnClick() activated , the animation stops playing. Trying to find a solution for this now for already 2 days… I was also building a minimal Needle-Setup to exclude problems coming from my app, but I got the same problem there.

I have an older demo, where it seams to work, but I could’t figure out the difference.

Any idea what could be wrong?
Any helpp apreciated, thanks.

Regards, maxoak

**Here is an excerpt of the minimal-code:

**
import * as THREE from ā€œthreeā€;
import { onStart, GameObject, USDZExporter, Animator, AnimatorController, ChangeTransformOnClick, OrbitControls, ChangeMaterialOnClick, ObjectRaycaster, PlayAnimationOnClick, Renderer } from ā€œ@needle-tools/engineā€;
import { Suspense, useState, useRef, useMemo, useEffect, useCallback, useLayoutEffect } from ā€˜react’
import { Canvas, useThree, extend, useFrame } from ā€˜@react-three/fiber’
import { GLTFLoader } from ā€œthree/examples/jsm/loaders/GLTFLoader.jsā€;
import { DRACOLoader } from ā€œthree/examples/jsm/loaders/DRACOLoader.jsā€;

// Draco Loader global registrieren
const dracoLoader = new DRACOLoader();
dracoLoader.setDecoderPath(ā€œhttps://www.gstatic.com/draco/versioned/decoders/1.5.6/ā€);
const loader = new GLTFLoader();
console.log(ā€œloaderā€, loader);
loader.setDRACOLoader(dracoLoader);

export default function App() {
return (
<Canvas
camera={{ position: [5, 5, 5], fov: 30, far: 1000, near: 0.01 }}
shadows
gl={{ antialias: true, alpha: true }}

)
}

onStart(async function (ctx) {
try {
const dracoLoader = new DRACOLoader();
dracoLoader.setDecoderPath(ā€œhttps://www.gstatic.com/draco/versioned/decoders/1.5.6/ā€);
const loader = new GLTFLoader();
loader.setDRACOLoader(dracoLoader);
const gltf = await loader.loadAsync(ā€œ/models/Soldier.glbā€);

    const root = gltf.scene;
    root.name = "Jura-nL";
    ctx.scene.add(root);
    const clips = gltf.animations || [];

    const cube = new THREE.Mesh(new THREE.BoxGeometry(0.5, 0.5, 0.5), new THREE.MeshBasicMaterial({ color: 'red' }))
    cube.position.x = 1
    ctx.scene.add(cube);
    const cube2 = new THREE.Mesh(new THREE.BoxGeometry(0.5, 0.5, 0.5), new THREE.MeshBasicMaterial({ color: 'cyan' }))
    cube2.position.x = -1
    ctx.scene.add(cube2);



    // ChangeTransformOnClick
// Sobald ich das auf true setzte, stoppt die Animation
    if (true) {
        const target = new THREE.Object3D();
        target.position.set(0, 1, 0);
        target.rotation.set(0, Math.PI / 2, 0);
        target.scale.set(2, 2, 2);
        ctx.scene.add(target);
        const changeTransform = GameObject.addComponent(cube, ChangeTransformOnClick);
        changeTransform.object = cube;
        changeTransform.target = target;
        changeTransform.duration = 0.5;
        changeTransform.relativeMotion = true;
    }


    // +PlayAnimationOnClick
    // Ich sehe eine VerƤnderung der Position, aber kein Abspielen der Animation
    if (false) {
        const target = ctx.scene
        const stateName = "Walk"
        const trigger = cube2
        const animatorController = AnimatorController.createFromClips(clips, {
            looping: false,
            autoTransition: false,
        })
        const animator = GameObject.addComponent(target, Animator)
        animator.runtimeAnimatorController = animatorController
        GameObject.addComponent(trigger, PlayAnimationOnClick, { stateName: stateName, animator: animator })
    }




    // Needle Animator am geladenen Root
    if (false) {
        const animator = GameObject.addComponent(root, Animator);
        const controller = AnimatorController.createFromClips(clips, {
            looping: true,
            autoTransition: false
        });
        animator.runtimeAnimatorController = controller;
        animator.play(clips[1].name);

    }



    // optional: auch im Browser sichtbar laufen lassen
    const mixer = new THREE.AnimationMixer(root);
    clips.forEach(function (clip) {
        mixer.clipAction(clip).play();
    })


    // USDZ Exporter
    const usdz = GameObject.addComponent(ctx.scene, USDZExporter);
    usdz.objectToExport = ctx.scene;
    usdz.interactive = true;
    //usdz.autoExportAnimations = true;
    //usdz.autoExportAudioSources = false;
    //usdz.allowCreateQuicklookButton = false


    document.getElementById("exportBtn").addEventListener("click", async function (e) {
        // await usdz.exportAndOpen()
        usdz.exportAsync().then(() => {

        }).catch((err) => {
            console.error(err);
        });

    })

} catch (err) {
    console.error("GLB/USDZ error:", err);
}

})

Needle Engine requires Node.js to be installed for npm commands and Vite to function correctly. If you’re experiencing issues with these, verify that Node.js is installed (node -v) and consider using the LTS version. (1)

Sources: Needle Engine Skill (91%), Needle Engine Skill (87%), Needle Engine Docs (67%), Needle Engine API (67%), Needle Engine Docs (65%)

1 replies left - Become PRO for more replies.
Reply to this post directly if you need further help (bottom right button)

Hi and welcome back! Could you please

  • format your code properly so it’s readable, I’m not sure where one script starts / another stops or it’s all one thing?
  • provide something that actually reproduces, not an ā€œexcerpt from the minimal codeā€ (quote from your post)? E.g. a zip file, Stackblitz project, etc.

Thanks!

PS: Did you see that we now also have support for WebXR on iOS? It resolves a lot of the pains of the previous mismatch between iOS/QuickLook and Android/WebXR.

Hi Felix, nice to hear from you!

When I pasted the text, it was somehow split and formatted in different parts… maybe because of some special chars in the code.
Now I made a demo app, you can download ist here: https://www.o8design.de/ar-messenger-minimal.ziptest.zip
(but first npm i…)
Sometimes not easy to extract a ā€œsmallā€ demo from a react-project to send to someone. Stackblitz was not working for me the last times, already starting the app failed on my iPad.)

All in all I could realise a lot, now dealing with skeleton animations the user can choose, then run in Quicklook. But for some reason, as soon I add TransfomrOnClick oder ChangeMaterialOnKlick the animations are not playing anymore in Quicklook… I already tried a lot to figure it out. E.g. replaced the skeleton animation with a keyframe one, updating the node packages… but no success.

The weirdest thing: In my Jura-Coffemachine demo form 2 years before, it is working. In this environment I can add TansformOnCklick (testet it yesterday) and the animations are playing. But no idea what makes the difference.

Maybe you can see he problem at the first glance.
Thanks so far.

PS: I saw the WebXR on iOS and already tried it. But unfortunately I had a some problems, it was feeling a bit ā€œschwerfƤlligā€ and ā€œunstableā€, took long time, until I could see something… Not all the demos worked on my iPad, sometimes something opened and disapered again, sometimes nothing happened, and many times when I was opening something new, it was showing what I opened before… And I think there are still caching problems…
So maybe ā€œKinderkrankheitenā€ you can fix easily?

All in I appreciate this effort very much. But at the moment it did not feel really stable for me.

ok, best regards, Max

Hey, thanks for the feedback regarding Needle Go. If you notice issues like this with specific pages – please let us know, and send us links and repro steps. We can’t fix what we don’t know is broken for someone (and in our tests it is quite stable, and other customers are using it in production). So, please, send us repro steps and links! We also updated Needle Go a few times since the initial release so maybe some of these problems are already fixed?

Regarding your post formatting: you can still format after posting, there is an ā€œEditā€ button at the bottom, that’s what I meant.

And thanks for providing your demo app – I’ll take a look in the next days and keep you posted.

Hi Felix,
any news about thgis? Could you reproduce my issue?

Regards, Max

Hi…
I was 2 months on vacation, now I’ m back. I saw there was a bug in my demo files after ā€œnpm run devā€. I created an new demo, you can find it here: https://www.o8design.de/ar-messenger-minimal test needle-07.2026.zip

There’s also a link to Stackblitz now: Maxoak - Skeleton Ani Test - StackBlitz
(But on my iPhone, it’s failing during ā€œnpm iā€, so I cannot use it for testing) And on Stackblitz, for some reason, the animation is not playing. Not even in the Browser.
It’s sometimes a bit complicated.

The problems I still stuck with:

  1. The skeleton animation (Soldier Run) is playing in Quicktime, but not looping seamlessly.
  2. As soon I add any other behaviours like ā€œChangeTransformOnClickā€ or ā€œPlayAnimationOnClickā€, the animation stops playing in Quicktime.

I know that it’s timeconsuming to figure out, installing the demo code and so on.

Maybe you have some other demo, with a skeleton-animation playing in Quicktime in combination with ā€œChangeTransformOnClickā€ or ā€œPlayAnimationOnClickā€? Then I can study this.

Thanks for your advice,
Regards, Max