docs
Getting Started
Tutorials
How-To Guides
Explanation
Reference
Help
Getting Started
Tutorials
How-To Guides
Explanation
Reference
Help

Switch Between Scenes

Dynamically load and switch between fully interactive glTF content - complete scenes or individual assets - with smooth transitions and preloading.

Works with Unity and Blender

The SceneSwitcher component is available for both Unity and Blender integrations.

Needle Engine's Superpower: Interactive glTF/glb Files

A key feature of Needle Engine is that glTF/glb files are fully interactive. When you export from Unity or Blender, your scenes include not just 3D models, but all components, scripts, physics, animations, and custom logic. SceneSwitcher loads these complete, self-contained interactive experiences - not just static geometry!

What You Can Do

  • Load Fully Interactive Scenes - Each scene is a complete Unity/Blender export with all its components, scripts, physics, animations, and interactivity
  • Self-Contained Experiences - Loaded scenes bring their own logic (DragControls, particle systems, custom scripts, etc.)
  • Multiple Scenes - Switch between different 3D environments
  • Multiple SceneSwitchers - Have several independent SceneSwitchers in one scene, each managing different content
  • Keyboard Navigation - Use arrow keys, A/D, or number keys to switch scenes
  • Swipe on Mobile - Swipe left/right to navigate between scenes
  • Preloading - Automatically preload nearby scenes for instant switching
  • Loading Scenes - Optional loading screen while switching
  • Browser History - Back/forward buttons work with scene changes
  • Custom Transitions - Control scene open/close behavior with code

Perfect for:

  • Portfolio and gallery websites
  • Product showcases with multiple variations
  • Multi-level experiences
  • Interactive storytelling
  • Virtual museums and exhibitions

Quick Start

Basic Setup

In Unity or Blender:

  1. Create an empty GameObject
  2. Add the SceneSwitcher component
  3. Add your scene files to the Scenes array
  4. Export and view - first scene loads automatically!

Controls:

  • Arrow Keys or A/D - Switch scenes
  • Number Keys (1, 2, 3...) - Jump to specific scene
  • Swipe (mobile) - Swipe left/right to navigate

Three Different Scenes

The video above shows three distinct scenes:

  1. Cylinder Garden (Scene 1) - Decorative plants on cylinders
  2. Gold & Fog (Scene 2) - Golden spheres in misty atmosphere
  3. Lightmapping (Scene 3) - Statue with colored lighting

Users can navigate between them seamlessly using Previous/Next buttons or keyboard controls.

Scene Organization Patterns

SceneSwitcher is incredibly flexible - you can organize your scenes in different ways depending on your needs:

Pattern 1: Replace Entire Scene Content

For completely different environments (like the video above), use a minimal root scene:

Root Scene (main.glb):

  • Camera
  • Lights (optional - scenes can provide their own)
  • SceneSwitcher component
  • UI elements (optional - Previous/Next buttons)

Individual Scenes:

  • scene1.glb - Complete environment with all objects
  • scene2.glb - Complete environment with all objects
  • scene3.glb - Complete environment with all objects

This pattern is perfect for:

  • Portfolio galleries where each scene is completely different
  • Virtual museums with distinct exhibition rooms
  • Product showcases with entirely different setups

See it in action:

  • Multi-Scene Sample - Live example with source code

Pattern 2: Replace Parts of the Scene

For partial content switching, keep persistent elements in the root scene and load interactive files:

Root Scene:

  • Camera with OrbitControls
  • Lighting setup (stays consistent)
  • Ground plane or environment
  • UI and navigation
  • SceneSwitcher component

Individual Scenes (exported from Unity or Blender):

  • Each scene is a full glTF export with all its components
  • Loaded scenes bring their own scripts (DragControls, particle systems, etc.)
  • Scenes can have animations, physics, UI, and custom logic
  • Completely self-contained interactive experiences

This pattern is perfect for:

  • Product configurators where environment stays the same
  • Loading interactive demos or mini-games
  • Character customization with persistent background
  • Swapping focal content while keeping context
  • Portfolio of interactive 3D experiences

See it in action:

  • Interactive Content Demo - Live example loading interactive scenes

Pattern 3: Multiple SceneSwitchers (Very Powerful!)

You can have multiple SceneSwitcher components in the same scene, each managing different parts:

Example: Showroom with Multiple Products

Root Scene:
├── Camera
├── Showroom Environment (persistent)
├── ProductDisplay1 (with SceneSwitcher)
│   ├── Switches between: chair1.glb, chair2.glb, chair3.glb
├── ProductDisplay2 (with SceneSwitcher)
│   ├── Switches between: lamp1.glb, lamp2.glb, lamp3.glb
└── ProductDisplay3 (with SceneSwitcher)
    ├── Switches between: table1.glb, table2.glb, table3.glb

Each SceneSwitcher:

  • Operates independently
  • Has its own scene array
  • Can use different navigation (one via UI, another via keyboard)
  • Loads/unloads only its own content

This pattern is perfect for:

  • Showrooms with multiple independent product displays
  • Comparison tools (left side vs right side)
  • Multi-panel presentations
  • Complex configurators with multiple customization areas

Example Code for Multiple Switchers:

import { Behaviour, SceneSwitcher } from "@needle-tools/engine";

export class MultiSwitcherController extends Behaviour {

    start() {
        // Get all SceneSwitchers in the scene
        const switchers = this.gameObject.getComponentsInChildren(SceneSwitcher);

        console.log(`Found ${switchers.length} scene switchers`);

        // Control them independently
        if (switchers[0]) switchers[0].select(0); // First display: scene 0
        if (switchers[1]) switchers[1].select(1); // Second display: scene 1
        if (switchers[2]) switchers[2].select(2); // Third display: scene 2
    }
}

Multiple SceneSwitchers Power

Having multiple SceneSwitchers is what makes Needle Engine's scene management incredibly powerful and flexible. You're not limited to switching entire environments - you can switch specific parts independently!

Settings

Basic Settings

SettingWhat it doesDefault
ScenesArray of scene files to switch between[]
Auto Load First SceneLoad first scene automatically on starttrue
Loading SceneOptional scene to display while loadingundefined

Navigation Settings

SettingWhat it doesDefault
Use KeyboardEnable keyboard shortcuts (arrows, A/D, numbers)true
Use SwipeEnable swipe navigation on mobiletrue
ClampStop at first/last scene (or loop around)true

URL & History

SettingWhat it doesDefault
Query Parameter NameURL parameter for current scene (e.g., ?scene=1)"scene"
Use Scene NameUse scene name in URL instead of indextrue
Use HistoryAdd scene changes to browser historytrue

Scene Settings

SettingWhat it doesDefault
Use Scene LightingApply lighting from loaded scenetrue
Use Scene BackgroundApply skybox from loaded scenetrue

Preloading

SettingWhat it doesDefault
Preload NextHow many scenes ahead to preload1
Preload PreviousHow many scenes behind to preload1
Preload ConcurrentMax concurrent downloads2

UI

SettingWhat it doesDefault
Create Menu ButtonsAdd Previous/Next to Needle menufalse

Examples

Simple Gallery

Create a 3-scene portfolio:

In Editor:

  1. Add SceneSwitcher component
  2. Add 3 scenes to the Scenes array:
    • Scene1.glb
    • Scene2.glb
    • Scene3.glb
  3. Enable Clamp to stop at first/last scene
  4. Users navigate with arrows or swipe

Infinite Loop Gallery

Let users loop through scenes endlessly:

In Editor:

  1. Add scenes to SceneSwitcher
  2. Disable Clamp
  3. After the last scene, pressing "next" returns to first scene
  4. Great for continuous presentations

Product Configurator

Show different product variations:

import { Behaviour, SceneSwitcher, serializable } from "@needle-tools/engine";

export class ProductConfigurator extends Behaviour {

    @serializable(SceneSwitcher)
    sceneSwitcher?: SceneSwitcher;

    start() {
        // Add product variations dynamically
        this.sceneSwitcher?.addScene("products/red-variant.glb");
        this.sceneSwitcher?.addScene("products/blue-variant.glb");
        this.sceneSwitcher?.addScene("products/green-variant.glb");

        // Load the first one
        this.sceneSwitcher?.select(0);
    }

    selectColor(colorName: string) {
        // Switch to specific product by name
        this.sceneSwitcher?.select(colorName);
    }
}

Custom Loading Screen

Show a loading scene while switching:

In Editor:

  1. Create a simple loading scene (e.g., spinner, progress bar)
  2. Export it as loading.glb
  3. Assign it to Loading Scene on SceneSwitcher
  4. The loading scene appears during transitions

Scripting

Switch Scenes Programmatically

import { Behaviour, SceneSwitcher } from "@needle-tools/engine";

export class SceneController extends Behaviour {

    start() {
        const switcher = this.gameObject.getComponent(SceneSwitcher);

        if (switcher) {
            // Navigate between scenes
            switcher.selectNext();  // Go to next scene
            switcher.selectPrev();  // Go to previous scene

            // Jump to specific scene by index
            switcher.select(2);  // Load scene at index 2

            // Jump to scene by name
            switcher.select("my-scene-name");

            // Get current scene info
            console.log("Current index:", switcher.currentIndex);
            console.log("Current scene:", switcher.currentlyLoadedScene?.url);
        }
    }
}

Add Scenes Dynamically

const switcher = this.gameObject.getComponent(SceneSwitcher);

// Add a new scene
const newScene = switcher.addScene("path/to/scene.glb");

// Switch to it
switcher.switchScene(newScene);

Listen to Scene Events

import { Behaviour, SceneSwitcher } from "@needle-tools/engine";

export class SceneMonitor extends Behaviour {

    start() {
        const switcher = this.gameObject.getComponent(SceneSwitcher);

        // When scene starts loading
        switcher.addEventListener("loadscene-start", (e) => {
            console.log("Loading scene:", e.detail.scene.url);
            console.log("Scene index:", e.detail.index);
        });

        // Loading progress
        switcher.addEventListener("progress", (e) => {
            const percent = (e.loaded / e.total) * 100;
            console.log(`Loading: ${percent.toFixed(1)}%`);
        });

        // When scene finished loading
        switcher.addEventListener("loadscene-finished", (e) => {
            console.log("Finished loading:", e.detail.scene.url);
        });

        // When scene is added and opened
        switcher.addEventListener("scene-opened", (e) => {
            console.log("Scene opened:", e.detail.scene.url);
        });
    }
}

Check Loading State

const switcher = this.gameObject.getComponent(SceneSwitcher);

// Check if a scene is currently loading
if (switcher.currentlyLoadingScene) {
    console.log("Loading:", switcher.currentlyLoadingScene.url);

    // Get loading progress
    const progress = switcher.currentLoadingProgress;
    if (progress) {
        const percent = (progress.loaded / progress.total) * 100;
        console.log(`Progress: ${percent}%`);
    }
}

Preload Scenes

const switcher = this.gameObject.getComponent(SceneSwitcher);

// Preload a specific scene by index
switcher.preload(2);

// Preloading happens automatically based on settings:
// - preloadNext: scenes ahead of current
// - preloadPrevious: scenes behind current

Reload Current Scene

const switcher = this.gameObject.getComponent(SceneSwitcher);

// Reload the currently loaded scene
await switcher.reload();

Unload Scene

const switcher = this.gameObject.getComponent(SceneSwitcher);

// Unload the current scene completely
await switcher.unload();

Advanced Features

ISceneEventListener Interface

Add custom logic when scenes open or close:

import { Behaviour, ISceneEventListener, SceneSwitcher } from "@needle-tools/engine";

// Add this to the root of your scene (the scene being loaded)
// or on the same object as the SceneSwitcher
export class MySceneTransition extends Behaviour implements ISceneEventListener {

    async sceneOpened(sceneSwitcher: SceneSwitcher) {
        console.log("My scene opened:", sceneSwitcher.currentlyLoadedScene?.url);

        // Fade in effect, play audio, etc.
        await this.fadeIn();
    }

    async sceneClosing() {
        console.log("My scene is closing");

        // Fade out, save state, etc.
        await this.fadeOut();
    }

    private async fadeIn() {
        // Your fade-in animation logic
    }

    private async fadeOut() {
        // Your fade-out animation logic
    }
}

URL Parameters

SceneSwitcher syncs with URL parameters automatically:

https://example.com/?scene=2        // Load scene at index 2
https://example.com/?scene=gallery  // Load scene named "gallery"

Users can:

  • Bookmark specific scenes
  • Share direct links to scenes
  • Use browser back/forward to navigate scenes

Keyboard Shortcuts

Default keyboard controls:

  • Arrow Right / D - Next scene
  • Arrow Left / A - Previous scene
  • Number keys (1-9) - Jump to scene by index (1 = first scene)

Disable with useKeyboard = false.

Mobile Swipe

Swipe left/right to navigate on touch devices.

Configure threshold or disable with useSwipe = false.

Common Questions

How many scenes can I add?
No hard limit, but be mindful of total file size. Use preloading settings to control memory usage.

Can scenes have different lighting?
Yes! Enable Use Scene Lighting and Use Scene Background to apply each scene's lighting/skybox.

How do I prevent users from jumping scenes?
Set useKeyboard = false and useSwipe = false, then only provide your own UI for navigation.

Can I load scenes from external URLs?
Yes! Use addScene("https://example.com/scene.glb") to add external scenes.

What's the difference between Loading Scene and regular scenes?
The loading scene appears while other scenes load. It's optional but improves UX for large scenes.

How does preloading work?
SceneSwitcher automatically downloads nearby scenes based on Preload Next and Preload Previous settings. This makes transitions instant.

Can I use this with multiplayer?
Yes! Scene changes can be synced across users with custom networking code using the scene events.

Performance Tips

Preload Settings:

  • Set preloadNext = 1 and preloadPrevious = 0 for linear galleries
  • Set both to 0 to disable preloading (saves memory, slower transitions)
  • Increase preloadConcurrent for faster preloading on good connections

Scene Size:

  • Keep scenes under 10MB for fast loading
  • Use compressed textures
  • Optimize geometry

Loading Scene:

  • Keep loading scenes very small (< 1MB)
  • Use simple geometry and minimal textures

URL Parameters:

  • Set queryParameterName = "" to disable URL syncing if not needed

Debugging

Enable debug mode by adding ?debugsceneswitcher to your URL:

http://localhost:3000?debugsceneswitcher

This shows:

  • Scene loading start/finish
  • Progress bars in console
  • Preloading schedule
  • Scene add/remove operations

More Information

Live Example:

  • Multi-Scene Sample - Interactive demo with source code

Real-World Examples:

  • Needle Website - Company website
  • Songs Of Cultures - Interactive cultural experience

API Documentation:

  • SceneSwitcher API - Complete technical reference
  • ISceneEventListener API - Scene transition interface

Related Guides:

  • Loading Scenes - Load scenes programmatically
  • Asset References - Reference external assets
Suggest changes
Last Updated: 1/28/26, 2:44 PM

Extras

ChatGPT Ask ChatGPT Claude Ask Claude
Copy Markdown

Navigation

  • Getting Started
  • Tutorials
  • How-To Guides
  • Explanation
  • Reference
  • Help

Extras

ChatGPT Ask ChatGPT Claude Ask Claude
Copy Markdown