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.

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: 1/28/26, 3:00 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