Develop

Animations sample overview

Updated: May 7, 2026

Overview

This sample demonstrates four animation techniques in the Meta Spatial SDK: glTF-embedded clip playback, Android ValueAnimator effects, per-frame procedural animation using custom ECS systems, and experimental panel shape morphing. An interactive drone sequence combines these techniques with hover effects, spatial audio synchronization, smooth target following, and grabbable object tracking.
Note: The panel shape animation uses PanelAnimationFeature, which is experimental and requires @OptIn(SpatialSDKExperimentalAPI::class). This API may change in future SDK releases.

What you will learn

  • Play glTF animation clips in sequence using the Animated component
  • Apply Android ValueAnimator to 3D objects for hover, click, and continuous pulse effects
  • Build custom ECS systems that compute rotation, tilt, and position smoothing every frame
  • Animate panel geometry between quad and cylinder shapes using PanelAnimationFeature
  • Combine multiple animation techniques to create responsive, interactive experiences

Requirements

  • Meta Quest device
  • Android Studio with the Spatial SDK configured
For detailed setup instructions, see Getting started with Spatial SDK. For build configuration details, see the sample README.

Get started

Clone the Meta-Spatial-SDK-Samples repository from GitHub. Open the AnimationsSample project in Android Studio, connect your Meta Quest device, and run the app. The sample loads a scene with a 3D button, drone model, target sphere, and UI panels.

Explore the sample

File / SceneWhat it demonstratesKey concepts
Main activity entry point, feature/component/system registration, GLXF scene loading
Panel shape animation via PanelAnimationFeature, ECS registration patterns
3D button hover and click visual feedback
ValueAnimator with color interpolation and overshoot effects
Drone animation sequence orchestration, target setup, follow mode toggle
glTF clip sequencing via Animated component, ValueAnimator scale effects, spatial audio sync
Per-frame drone rotation and tilt toward target
Custom SystemBase implementation, quaternion rotation, velocity-based tilt
Per-frame smooth position following via exponential decay
Frame-based procedural animation, Freya Holmer smoothing technique
GLXF scene object discovery and initialization
Reactive system that waits for named entities to load
panel/PanelAnimationPanel.kt
UI toggle for experimental panel shape animation
Jetpack Compose integration in panels
droneScene.glxf
Scene with drone model containing four animation tracks, environment, buttons, panels
glTF animation track discovery, named entity references

Runtime behavior

When you run this sample, you see a VR room with an about panel behind you, an info panel with instructions in front, a 3D button, and a panel animation toggle to the side. Hovering over the button changes its color from orange to purple. Clicking the button depresses it with a bounce effect and plays a click sound. The info panel hides.
The drone unfolds its arms over 3.5 seconds, lifts off with spatial audio synchronized to the takeoff animation, then performs a fly-around sequence. After that, the drone enters an idle hover loop. A translucent blue sphere appears with a scale-up overshoot effect and continuous pulse, and a grab panel appears offering a follow mode toggle.
When you grab the sphere, the drone rotates to face it, tilts based on velocity, and follows using exponential decay smoothing. Toggling to built-in mode switches to the SDK’s Followable component and changes the sphere to orange. Separately, the panel animation toggle morphs a panel between flat quad and curved cylinder shapes.

Key concepts

glTF clip playback and sequencing

The sample discovers animation tracks embedded in the drone glTF model by calling SceneObject.mesh.getAnimationTracks() and builds a name-to-index map. DroneSceneController.kt plays clips in sequence by setting the Animated component with the track index:
droneEnt.setComponent(Animated(
    System.currentTimeMillis(),
    playbackState = PlaybackState.PLAYING,
    playbackType = PlaybackType.CLAMP, track = track))
The sequence chains four clips (openarm, takeoff, fancyflyaround, idleground) using Timer().schedule() with hardcoded durations. For looping animations like idle hover, the sample uses PlaybackType.LOOP. For more on glTF animation integration, see Animations and glTFs.

Android ValueAnimator for 3D object effects

The sample applies Android’s ValueAnimator to 3D objects for smooth interpolation effects. In ButtonController.kt, the button uses ArgbEvaluator for color transitions and OvershootInterpolator for click depression. The drone target in DroneSceneController.kt applies overshoot for scale-up, then runs an infinite pulse animator. All animators call activity.runOnUiThread() to ensure execution on a Looper thread.

Per-frame procedural animation with custom systems

The sample implements two custom ECS systems that compute transformations every frame. DroneSystem.kt calculates rotation toward the target using Quaternion.lookRotationAroundY(), applies velocity-based tilt, and smooths rotation via Quaternion.slerp(). FollowerSystem.kt implements exponential decay position smoothing using Freya Holmer’s technique. Both extend SystemBase and override execute() to run each frame. For system architecture, see Entity Component System.

Experimental panel shape animation

The sample demonstrates panel geometry morphing using the experimental PanelAnimationFeature:
entity.setComponent(PanelQuadCylinderAnimation(
    startTime = DataModel.getLocalDataModelTime(),
    animationType = PanelQuadCylinderAnimationType.QUAD_TO_CYLINDER,
    durationInMs = 500L,
    targetRadius = Random.nextFloat() * 2f + 0.67f))
The animation transitions the panel between flat quad and curved cylinder over 500 milliseconds. The radius is randomized between 0.67 and 2.67 meters, producing varying degrees of curvature each toggle.

Extend the sample

  • Change the follow behavior: Replace the exponential decay smoothing in FollowerSystem with spring physics or add acceleration curves for different motion characteristics.
  • Add new animation clips: Import a custom glTF model with your own animation tracks and wire them into the sequencing pattern from DroneSceneController.
  • Extend the panel animation: Modify the PanelQuadCylinderAnimation parameters to experiment with different radii, durations, or create a cycling animation between multiple shapes.