From a986341387ff12f63949929bd87b3f388962ec69 Mon Sep 17 00:00:00 2001 From: Victor Giers Date: Tue, 14 Apr 2026 13:46:33 +0200 Subject: [PATCH] Add animation handling for NPCs in runtime-host.ts --- src/runtime-three/runtime-host.ts | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/runtime-three/runtime-host.ts b/src/runtime-three/runtime-host.ts index e09bec8b..4c21e0b7 100644 --- a/src/runtime-three/runtime-host.ts +++ b/src/runtime-three/runtime-host.ts @@ -1834,6 +1834,10 @@ export class RuntimeHost { npc.modelAssetId === null ? null : (this.projectAssets[npc.modelAssetId] ?? null); + const loadedAsset = + npc.modelAssetId === null + ? null + : (this.loadedModelAssets[npc.modelAssetId] ?? null); const renderGroup = npc.modelAssetId === null || asset?.kind !== "model" ? this.createNpcColliderFallbackRenderGroup(npc) @@ -1862,12 +1866,32 @@ export class RuntimeHost { } }, asset, - this.loadedModelAssets[npc.modelAssetId], + loadedAsset, false ); renderGroup.visible = npc.visible && npc.active; this.modelGroup.add(renderGroup); this.modelRenderObjects.set(npc.entityId, renderGroup); + + if (loadedAsset?.animations && loadedAsset.animations.length > 0) { + const mixer = new AnimationMixer(renderGroup); + this.animationMixers.set(npc.entityId, mixer); + this.instanceAnimationClips.set(npc.entityId, loadedAsset.animations); + + if (npc.animationClipName !== null) { + const clip = AnimationClip.findByName( + loadedAsset.animations, + npc.animationClipName + ); + + if (clip) { + const action = mixer.clipAction(clip); + action.loop = npc.animationLoop === false ? LoopOnce : LoopRepeat; + action.clampWhenFinished = npc.animationLoop === false; + action.reset().play(); + } + } + } } this.applyShadowState();