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);
}
})