Throwing
Updated: May 7, 2026
This sample demonstrates a multi-game throwing gallery where users can grab and throw nine different objects (axe, basketball, bowling ball, corn bag, dart, frisbee, paper plane, pong ball, and rugby ball) using hand or controller tracking. The sample shows how to implement object pooling, custom physics profiles per throwable, weight simulation during grab, and target-based scoring systems using Meta XR Interaction SDK for Unity.
- Use Grabbable and VelocityThrow for hand and controller-based throwing
- Create custom physics profiles using ThrowProfile ScriptableObjects to control velocity, spin, gravity, and in-flight behavior
- Implement object pooling for throwables using Unity’s
ObjectPool<T> - Customize grab behavior by implementing the ITransformer interface
- Handle collision-based gameplay with tag routing and scoring systems
- Meta Quest device with hand tracking or controllers
- Unity development environment
- See the sample README for detailed build and setup instructions
Clone or download the Unity-InteractionSDK-Samples repository from GitHub. Open the project in Unity and navigate to Assets/ShowcaseSamples/Throwing/Scenes/ThrowingSample.unity. Build and deploy to your Quest device following the instructions in the sample README. Use hand tracking or controllers to grab objects from the spawn points and throw them at the targets.
The sample includes nine mini-games, each demonstrating different physics profiles and interaction patterns.
| File / Scene | What it demonstrates | Key concepts |
|---|
ThrowingSample.unity | Main scene with all nine mini-games arranged in a gallery | Scene composition, target switching, multi-game coordination |
PooledThrowable.cs | Object pooling system using static dictionaries and Unity ObjectPool<T> | Pool lifecycle, auto-despawn (kill plane, sleep timer), component cleanup on reuse |
ThrowingPrefabDefinition.cs | ScriptableObject data container linking prefabs to pool system | Asset-based configuration pattern |
HeavyFreeTransformer.cs | Custom ITransformer implementation simulating object weight | Grab behavior customization, velocity dampening, upward resistance |
SpawnPoint.cs | Grab-triggered spawning using WhenPointerEventRaised | ISDK event system, delayed instantiation |
CollisionHandler.cs | Tag-based collision routing for scoring and freeze-on-hit behavior | Collision filtering, scoring integration, dart/axe sticking |
SwapTargets.cs | Target scene switching with animated scale transitions | Coroutine-based animation, multi-game state management |
ThrowProfiles/*.asset | Nine ThrowProfile assets defining unique physics per throwable | Per-object physics tuning (velocity, gravity, spin, lift, alignment) |
BowlingPinsManager.cs | Bowling pin positioning, off-screen hiding, and reset system | Target lifecycle, NaN validation |
BowlingExtendedVelocity.cs | Floor collision detection with Z-velocity boost and damping | Custom physics extension for bowling ball rolling |
When you run the sample, you see nine spawn points arranged in a gallery, each displaying a different throwable object. Grab an object using hand tracking (pinch gesture) or controllers (grip button). The spawn point immediately creates a replacement. Each throwable has unique physics: darts fly fast and stick to the board, paper planes glide slowly with lift force, frisbees float with reduced gravity, and bowling balls gain speed on floor impact. Targets scale in and out as you switch between games. Successful hits trigger scoring, sound effects, and visual feedback. Objects auto-despawn after falling below the kill plane (Y < -1) or remaining still for 3 seconds after throw.
Custom physics profiles with ThrowProfile
The sample uses ISDK’s ThrowProfile ScriptableObject system to define unique flight characteristics for each throwable. The sample creates nine separate .asset files in Prefabs/ThrowProfiles/, each configuring properties like maxSpeed, gravity, alignForward, and liftForce. The ThrowTuner component on each prefab applies these settings at runtime. For example, the paper plane profile sets maxSpeed=5 and liftForce=4 for a slow glide, while the rugby ball uses maxSpeed=50 with continuous forward alignment during flight.
See ThrowProfiles/PlaneProfile.asset and ThrowProfiles/RugbyProfile.asset for contrasting examples.
Object pooling with PooledThrowable
The sample implements allocation-free throwable management using a static dictionary of ObjectPool<PooledThrowable> instances keyed by prefab. PooledThrowable.Get() retrieves or creates instances, while Despawn() returns them to the pool. The pool performs critical cleanup on reuse: stripping duplicate InteractableTriggerBroadcaster components and destroying RigidbodyKinematicLocker to prevent state corruption from ISDK’s internal kinematic management.
See PooledThrowable.cs — the static Get() factory method and Despawn() method.
The sample’s HeavyFreeTransformer implements ISDK’s ITransformer interface to add weight simulation during grab. When isHeavy=true, upward hand movement accumulates velocity over time with increasing dampening, making objects feel heavy to lift. The transformer uses TransformerUtils for position, rotation, and scale constraints, and employs ArrayPool<GrabPointDelta>.Shared for allocation-free delta tracking across multiple grab points.
See HeavyFreeTransformer.cs — the UpdateTransform() method contains the dampening calculation.
Grab-triggered spawning with PointerEvent
The sample’s SpawnPoint component demonstrates ISDK’s event-driven architecture by subscribing to Grabbable.WhenPointerEventRaised and filtering for PointerEventType.Select. The spawn point waits for the grab event, notifies the target swap system via SwapTargets.IsGrabbed(), then spawns a replacement from the pool after a configurable delay. This pattern ensures seamless respawning without visible gaps.
See SpawnPoint.cs — the HandlePointerEventRaised() method.
- Add a new throwable object by creating a prefab with Grabbable, Rigidbody, ThrowTuner, and PooledThrowable components, then author a custom ThrowProfile asset to define its flight behavior.
- Modify SwapTargets.cs to add a new target scene with different scoring rules or obstacles.
- Combine patterns from this sample with the Locomotion sample to create a throwing game where players navigate between different target areas.