Exporting Assets, Animations, Prefabs, Materials, Lightmaps...

To mark any Unity scene as "exportable", add an ExportInfo component to a root object. This component helps you to generate your new web project from a template, set up dependencies to other component libraries (we call them NpmDef) and to deploy your project.

By default, your scene is exported on save. This setting can be changed by disabling Auto Export in the ExportInfo component.

📦 Exporting glTF files

To export meshes, materials, animations, textures (...) create a new GameObject in your hierarchy and add a GltfObject component to it. This is the root of a new glTF file. It will be exported whenever you make a change to the scene and save.

Only scripts and data on and inside those root objects is exported. Scripts and data outside of them are not exported.

Add a cube as a child of your root object and save your scene. Note that the output assets/ folder (see project structure) now contains a new .glb file with the same name as your root GameObject.

You can enable the Smart Export setting (via Edit/Project Settings/Needle ) to only export when a change in this object's hierarchy is detected.

How to prevent specific objects from being exported

Objects with the EditorOnly tag will be ignored on export including their child hierarchy.
Be aware that this is preferred over disabling objects as disabled will still get exported in case they're turned on later.

Lazy loading and multiple levels / scenes

If you want to split up your application into multiple levels or scenes then you can simply use the SceneSwitcher component. You can then structure your application into multiple scenes or prefabs and add them to the SceneSwitcher array to be loaded and unloaded at runtime. This is a great way to avoid having to load all your content upfront and to keep loading times small (for example it is what we did on needle.toolsopen in new window by separating each section of your website into its own scene and only loading them when necessary)

  • Max. 50 MB export size uncompressed (usually ends up ~10-20 MB compressed)
  • Max. 500k vertices (less if you target mobile VR as well)
  • Max. 4x 2k lightmaps

You can split up scenes and prefabs into multiple glTF files, and then load those on demand (only when needed). This keeps loading performance fast and file size small. See the AssetReference section in the Scripting docs.

The scene complexity here is recommended to ensure good performance across a range of web-capable devices and bandwidths. There's no technical limitation to this beyond the capabilities of your device.


Prefabs can be exported as invidual glTF files and instantiated at runtime. To export a prefab as glTF just reference a prefab asset (from the project browser and not in the scene) from one of your scriptsopen in new window.

Exporting Prefabs works with nesting too: a component in a Prefab can reference another Prefab which will then also be exported.
This mechanism allows for composing scenes to be as lightweight as possible and loading the most important content first and defer loading of additional content.

Scene Assets

Similar to Prefab assets, you can reference other Scene assets.
To get started, create a component in Unity with a UnityEditor.SceneAsset field and add it to one of your GameObjects inside a GltfObject. The referenced scene will now be exported as a separate glTF file and can be loaded/deserialized as a AssetReference from TypeScript.

You can keep working inside a referenced scene and still update your main exporter scene/website. On scene save or play mode change we will detect if the current scene is being used by your currently running server and then trigger a re-export for only that glb. (This check is done by name - if a glb inside your <web_project>/assets/ folder exists, it is exported again and the main scene reloads it.)

As an example on our websiteopen in new window each section is setup as a separate scene and on export packed into multiple glb files that we load on demand:


Loading a Prefab or Scene from a custom script

If you want to reference and load a prefab from one of your scripts you can declare a AssetReference type.
Here is a minimal example:

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

export class MyClass extends Behaviour {

    // if you export a prefab or scene as a reference from Unity you'll get a path to that asset
    // which you can de-serialize to AssetReference for convenient loading
    myPrefab?: AssetReference;
    async start() {
      // directly instantiate
      const myInstance = await this.myPrefab?.instantiate();

      // you can also just load and instantiate later
      // const myInstance = await this.myPrefab.loadAssetAsync();
      // this.gameObject.add(myInstance)
      // this is useful if you know that you want to load this asset only once because it will not create a copy
      // since ``instantiate()`` does create a copy of the asset after loading it

🏇 Exporting Animations

Needle Engine supports a considerable and powerful subset of Unity's animation features:

  • Timeline incl. activation tracks, animation tracks, track offsets
  • Animator incl. top-level state transitions
    • Blend trees are currently not supported.
    • Sub state machines are currently not supported.
  • AnimationClips incl. Loop modes
  • Procedural Animations can be created via scripting

Needle Engine is one of the first to support the new glTF extension KHR_ANIMATION_POINTERopen in new window.
This means that almost all properties, including script variables, are animatable.

One current limitation is that materials won't be duplicated on export — if you want to animate the same material with different colors, for example, you currently need to split the material in two.

🌍 Exporting the Skybox

The Unity skybox and custom reflection (if any) are baked into a texture on export and automatically exported inside the NEEDLE_lightmaps extension.

To change the skybox resolution you can add a SkyboxExportSettings component to your scene.


If you don't want to skybox to be exported at all in a glb file you can untick the Embed Skybox option on your GltfObject component


✨ Exporting Materials

Physically Based Materials (PBR)

By default, materials are converted into glTF materials on export. glTF supports a physically based material model and has a number of extensions that help to represent complex materials.

For full control over what gets exported, it's highly recommended to use the glTF materials provided by UnityGltf:

  • PBRGraph
  • UnlitGraph

These materials are exported as-is, with no conversion necessary. They allow for using advanced material properties such as refractive transmission and iridescence, which can be exported as well.

Materials that can be converted out-of-the-box:

  • BiRP/Standard
  • BiRP/Autodesk Interactive
  • BiRP/Unlit
  • URP/Lit
  • URP/Unlit

Other materials are converted using a propery name heuristic. That means that depending on what property names your materials and shaders use, you might want to either refactor your custom shader's properties to use the property names of either URP/Lit or PBRGraph, or export the material as Custom Shader.

Custom Shaders

To export custom shaders (e.g. ShaderGraph shaders), add an ExportShader Asset Label (see bottom of the inspector) to the shader you want to export.


Please see limitations listed below


Note that Custom Shaders aren't part of the ratified glTF material model. The resulting GLB files will not display correctly in other viewers (the materials will most likely display white).

Current limitations

  • We currently only support custom Unlit shaders — Lit shader conversion is not officially supported.
  • Custom Lit Shaders are currently experimental. Not all rendering modes are supported.
  • Shadow receiving on custom shaders is not supported
  • Skinned meshes with custom shaders are not supported
  • As there's multiple coordinate system changes when going from Unity to three.js and glTF, there might be some changes necessary to get advanced effects to work. We try to convert data on export but may not catch all cases where conversions are necessary.
    These coordinate changes are
    • UV coordinates in Unity start at the bottom left; in glTF they start at the top left.
    • X axis values are flipped in glTF compared to Unity (a variant of a left-handed to right-handed coordinate system change).

💡 Exporting Lightmaps


To export lightmaps simply generate lightmapsopen in new window in Unity. Lightmaps will be automatically exported.

When working on multiple scenes, disable "Auto Generate" and bake lightmaps explicitly. Otherwise, Unity will discard temporary lightmaps on scene change.

  • Lightmap Encoding: Normal Quality (adjust in Project Settings > Player)
  • Progressive GPU (faster and usually accurate enough for small scenes)
  • Non-Directional Lightmaps
  • Max Lightmap Size 2k (you can go higher, but expect large files)
  • Max 4x 2k lightmaps per scene (you can go higher, but expect large files)
  • Compress Lightmaps OFF (increases quality; otherwise will be compressed again at export time)


Mixing Baked and Non-Baked Objects

There's no 100% mapping between how Unity handles lights and environment and how three.js handle that. For example, Unity has entirely separate code paths for lightmapped and non-lightmapped objects (lightmapped objects don't receive ambient light since that is already baked into their maps), and three.js doesn't distinguish in that way.

This means that to get best results, we currently recommend specific settings if you're mixing baked and non-baked objects in a scene:

Environment Lighting: Skybox
Ambient Intensity: 1
Ambient Color: black



If you have no baked objects in your scene, then the following settings should also yield correct results:

Environment Lighting: Color
Ambient Color: any