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

Create Components

Learn how to create interactive components for Needle Engine using TypeScript or JavaScript.

Prefer to see it running first? The Scripting Walkthrough builds this up one concept at a time, live.

Prerequisites

New to TypeScript? Start here:

  • TypeScript Essentials - Language fundamentals
  • Needle Engine for Unity Developers - Unity to web workflow
Video: Creating Custom Components in Unity

This video gives a short introduction to the easiest and fastest way to create custom Needle Engine components in Unity.


Quick Start

Direct File Approach

Add a .ts or .js file to src/scripts/ in your web project:

your-project/
└── src/
    └── scripts/
        └── MyFirstScript.ts  ← Add your component here

Benefits:

  • Simple and direct
  • Perfect for small projects
  • Automatic hot reload

Unity - NPM Definition Approach

Organize code into reusable npm packages using NPM Definition files:

  1. In Unity: Create > NPM Definition
  2. Right-click the NpmDef: Create > TypeScript
  3. Write your component

Benefits:

  • Modular code organization
  • Share code between projects
  • Standard npm package format

Learn more about NPM Definitions


Your First Component

Create src/scripts/Rotate.ts:

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

export class Rotate extends Behaviour
{
    @serializable()
    speed : number = 1;

    start(){
        // Logging is useful for debugging in the browser
        // Open the developer console (F12) to see your component's data
        console.log(this);
    }

    // update will be called every frame
    update(){
        this.gameObject.rotateY(this.context.time.deltaTime * this.speed);
    }
}

What happens next:

  • 🔄 C# stub (Unity) or Blender panel auto-generates on save
  • ⚡ Hot reload in browser—no Unity recompilation needed
  • 🚀 Instant iteration—see changes in ~1 second

Component with Custom Function

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

export class PrintNumberComponent extends Behaviour
{
    start(){
      this.printNumber(42);
    }

    private printNumber(myNumber : number){
        console.log("My Number is: " + myNumber);
    }
}

Multiple Components Per File

You can export multiple components from one file:

export class MyComponent1 extends Behaviour { }
export class MyComponent2 extends Behaviour { }

Component Architecture

Components attach to three.js Object3D instances:

  • Access the Object3D: this.gameObject
  • Access the scene: this.context.scene
  • Access components: this.gameObject.getComponent(Type)

Visibility & Active State

Setting visible = false on an Object3D acts like Unity's SetActive(false):

  • Disables all components on this object and its children
  • No update events called until visible = true again
  • To hide visually without affecting components, disable the Renderer component instead

Serialization

Use @serializable() to expose properties in the editor (Unity/Blender) and ensure they get saved/loaded correctly.

Basic Types

Primitives (number, string, boolean) only need @serializable():

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

export class MyComponent extends Behaviour
{
    @serializable()
    speed: number = 5;

    @serializable()
    playerName: string = "Player";

    @serializable()
    isActive: boolean = true;
}

Object References

For object references and complex types, you must specify the type:

import { Behaviour, serializable } from "@needle-tools/engine";
import { Object3D, Light, Camera } from "three";

export class MyComponent extends Behaviour
{
    @serializable(Object3D)
    myTarget?: Object3D;

    @serializable(Light)
    targetLight?: Light;

    @serializable(Camera)
    mainCamera?: Camera;
}

Arrays

Primitive arrays don't need a type:

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

export class MyComponent extends Behaviour
{
    @serializable()
    speeds: number[] = [1, 2, 3];

    @serializable()
    names: string[] = ["Player1", "Player2"];
}

Arrays with object references need the type specified:

import { Behaviour, serializable } from "@needle-tools/engine";
import { Object3D, Light } from "three";

export class MyComponent extends Behaviour
{
    // Correct: type specified for object references
    @serializable(Object3D)
    waypoints: Object3D[] = [];

    @serializable(Light)
    lights: Light[] = [];

    // Wrong: will not serialize correctly
    // waypoints: Object3D[] = [];
}

Reference

See the complete @serializable decorator reference for more details and advanced usage.


Version Control

While generated C# components use the type name to produce stable GUIDs, we recommend checking in generated components in version control as a good practice.


Next Steps

  • Use Lifecycle Hooks - awake, start, update methods
  • Handle User Input - Mouse, touch, keyboard
  • Find Components - Query the scene graph
  • Use Coroutines - Sequenced operations
  • Component Lifecycle Reference - Complete API

Need Help?

  • TypeScript Essentials
  • Scripting Examples
  • API Documentation
  • Discord Community
Suggest changes
Last Updated: 8/5/26, 11:40 AM

Extras

Needle AI Ask Needle AI
Copy Markdown

Navigation

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

Extras

Needle AI Ask Needle AI
Copy Markdown