Needle Engine Documentation
Getting Started
Tutorials
How-To Guides
Explanation
Reference
Help
Getting Started
Tutorials
How-To Guides
Explanation
Reference
Help

C#C# to TypeScriptTypeScript

Translate your Unity C# knowledge to TypeScript for web development with Needle Engine.

New to TypeScript?

Start with TypeScript Essentials for core language concepts without C# comparisons.


Value Types vs Reference Types

C#C# - Value Types (Structs)

In C#, Vector3 is a struct (value type)—it gets copied when passed to methods:

void MyCallerMethod() {
    var position = new Vector3(0, 0, 0);
    MyExampleVectorMethod(position);
    Debug.Log("Position.x is " + position.x); // ✅ Still 0 (copy was modified)
}

void MyExampleVectorMethod(Vector3 position) {
    position.x = 42; // Modifies the COPY, not the original
}

Key behavior: Assignment creates a copy:

var myVector = new Vector3(1, 1, 1);
var myOtherVector = myVector;  // Creates a COPY
myOtherVector.x = 42;
// Logs: 1, 42 (two separate instances)
Debug.Log(myVector.x + ", " + myOtherVector.x);

TypeScriptTypeScript - Reference Types (Objects)

In JavaScript/TypeScript, all objects are reference types—including Vector3:

import { Vector3 } from 'three'

function myCallerMethod() {
    const position = new Vector3(0, 0, 0);
    myExampleVectorMethod(position);
    console.log("Position.x is " + position.x); // ⚠️ Now 42 (original modified!)
}

function myExampleVectorMethod(position: Vector3) {
    position.x = 42; // Modifies the ORIGINAL
}

Key behavior: Assignment creates a reference:

import { Vector3 } from 'three'

const myVector = new Vector3(1, 1, 1);
const myOtherVector = myVector;  // Creates a REFERENCE
myOtherVector.x = 42;
// Logs: 42, 42 (same instance!)
console.log(myVector.x, myOtherVector.x);

Critical Difference!

In TypeScript, modifying a Vector modifies the original. To create a copy, use .clone():

const myVector = new Vector3(1, 1, 1);
const myOtherVector = myVector.clone(); // ✅ Creates a true copy
myOtherVector.x = 42;
// Logs: 1, 42 (two separate instances)
console.log(myVector.x, myOtherVector.x);

Vector Math & Operators

C#C# - Operator Overloading

C# supports operator overloading for vectors:

var myVector = new Vector3(1, 1, 1);
var myFactor = 100f;

myVector *= myFactor;          // ✅ Operators work
myVector = myVector + new Vector3(5, 0, 0);  // ✅ Addition works
// → myVector is now (105, 100, 100)

TypeScriptTypeScript - Method Calls

JavaScript/TypeScript does not support operator overloading. Use methods instead:

import { Vector3 } from "three"

const myVector = new Vector3(1, 1, 1);
const myFactor = 100;

myVector.multiplyScalar(myFactor);           // Can't use *= operator
myVector.add(new Vector3(5, 0, 0));          // Can't use + operator
// → myVector is now (105, 100, 100)

Common Vector Operations

OperationUnity (C#)Needle Engine (TypeScript)
Multiplyvector *= 2vector.multiplyScalar(2)
Addvector += othervector.add(other)
Subtractvector -= othervector.sub(other)
Lengthvector.magnitudevector.length()
Normalizevector.normalizedvector.normalize()
DistanceVector3.Distance(a, b)a.distanceTo(b)

three.js Vector Methods

Most three.js vector methods modify the original vector. For immutable operations, clone first:

const result = myVector.clone().multiplyScalar(2); // Original unchanged

Time & Delta Time

C#Unity Time

void Update() {
    transform.position.x += speed * Time.deltaTime;
    float currentTime = Time.time;
}

TypeScriptNeedle Engine Time

Access time data via this.context.time:

update() {
    this.gameObject.position.x += this.speed * this.context.time.deltaTime;
    const currentTime = this.context.time.time;
}

Property Mapping

Unity (C#)Needle Engine (TypeScript)Description
Time.timethis.context.time.timeScaled time since app started
Time.deltaTimethis.context.time.deltaTimeTime since last frame
Time.frameCountthis.context.time.frameCountTotal frames rendered
Time.realtimeSinceStartupthis.context.time.realtimeSinceStartupUnscaled time
Time.timeScalethis.context.time.timeScaleTime multiplier

Frame-Rate Independent Movement

Always multiply movement by deltaTime:

this.gameObject.position.x += speed * this.context.time.deltaTime;

Read more about Time


Raycasting

C#Unity Physics.Raycast

if (Physics.Raycast(origin, direction, out RaycastHit hit, maxDistance)) {
    Debug.Log("Hit: " + hit.collider.name);
}

TypeScriptNeedle Engine Raycast

// Screen-space raycast from mouse/touch
const hits = this.context.physics.raycast();
if (hits.length > 0) {
    console.log("Hit:", hits[0].object.name);
}

// Custom ray with options
const hits = this.context.physics.raycast({
    maxDistance: 100,
    lineOfSight: true
});

// Physics-based (requires colliders)
const hit = this.context.physics.engine?.raycast();

Key differences:

  • Unity: Requires colliders for all raycasts
  • Needle Engine: Default raycasts hit visible geometry, optional physics-based raycasts require colliders

Read more about Raycasting


Input

C#Unity Input

void Update() {
    if (Input.GetMouseButtonDown(0)) {
        Debug.Log("Click!");
    }

    if (Input.GetKey(KeyCode.Space)) {
        Debug.Log("Space pressed");
    }
}

TypeScriptNeedle Engine Input

Polling input state:

update() {
    if (this.context.input.getPointerDown(0)) {
        console.log("Click!");
    }

    if (this.context.input.getKeyDown("Space")) {
        console.log("Space pressed");
    }
}

Event subscription:

import { InputEvents, NEPointerEvent } from "@needle-tools/engine";

onEnable() {
    this.context.input.addEventListener(InputEvents.PointerDown, this.onPointerDown);
}

onDisable() {
    this.context.input.removeEventListener(InputEvents.PointerDown, this.onPointerDown);
}

private onPointerDown = (evt: NEPointerEvent) => {
    console.log("Pointer down at:", evt.point);
}

Read more about Input


InputSystem Callbacks

C#Unity IPointerClickHandler

using UnityEngine.EventSystems;

public class Clickable : MonoBehaviour, IPointerClickHandler {
    public void OnPointerClick(PointerEventData eventData) {
        Debug.Log("Clicked!");
    }
}

TypeScriptNeedle Engine Pointer Events

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

export class Clickable extends Behaviour {
    onPointerClick(args: PointerEventData) {
        console.log("Clicked at:", args.point);
    }
}

Available events:

  • onPointerDown
  • onPointerUp
  • onPointerEnter
  • onPointerMove
  • onPointerExit
  • onPointerClick

All receive a PointerEventData argument.

Read more about Input Events


Debug.Log

C#Unity Debug

Debug.Log("Hello Unity");
Debug.LogWarning("Warning message");
Debug.LogError("Error message");

TypeScriptJavaScript Console

console.log("Hello web");
console.warn("Warning message");
console.error("Error message");

// Log multiple values
console.log("Score:", score, "Player:", player);

Debug Gizmos

C#Unity Gizmos

void OnDrawGizmos() {
    Gizmos.color = Color.red;
    Gizmos.DrawWireSphere(transform.position, 1.0f);
    Gizmos.DrawLine(start, end);
}

TypeScriptNeedle Engine Gizmos

import { Gizmos, isDevEnvironment } from "@needle-tools/engine";

update() {
    if (isDevEnvironment()) {
        Gizmos.DrawWireSphere(this.gameObject.position, 1.0, 0xff0000, 1);
        Gizmos.DrawLine(start, end, 0x00ff00, 0);
    }
}

Key differences:

UnityNeedle Engine
OnDrawGizmos() methodCall Gizmos from anywhere
OnDrawGizmosSelected()Use if(isDevEnvironment()) to filter
Only in EditorVisible in browser (filter for production!)

Available methods:

  • DrawArrow - Arrow between two points
  • DrawBox / DrawBox3 - Wireframe boxes
  • DrawDirection - Direction arrow from origin
  • DrawLine - Line between two points
  • DrawRay - Infinite ray from origin
  • DrawSphere / DrawWireSphere - Solid/wireframe spheres

See full Gizmos API


Useful Utility Methods

Common Unity Methods

Unity (C#)Needle Engine (TypeScript)
Check if in Editor#if UNITY_EDITOR
Get URL parameterN/A
Check mobile deviceApplication.isMobilePlatform
Check iOSApplication.platform == RuntimePlatform.IPhonePlayer

Example:

import { getParam, isDevEnvironment, DeviceUtilities } from "@needle-tools/engine";

// Check URL parameter
if (getParam("debug")) {
    console.log("Debug mode enabled");
}

// Platform detection
if (DeviceUtilities.isMobileDevice()) {
    // Mobile-specific logic
}

// Development vs production
if (isDevEnvironment()) {
    // Show debug UI, gizmos, etc.
}

Read more about Platform Detection


Quick Reference Cheat Sheet

TaskUnity (C#)Needle Engine (TypeScript)
ComponentMonoBehaviourBehaviour
GameObjectGameObjectObject3D
Transformtransform.positionthis.gameObject.position
World Positiontransform.positionthis.gameObject.worldPosition
Find ComponentGetComponent<T>()getComponent(T)
TimeTime.deltaTimethis.context.time.deltaTime
InputInput.GetMouseButtonDown(0)this.context.input.getPointerDown(0)
RaycastPhysics.Raycast(...)this.context.physics.raycast(...)
Debug LogDebug.Log(...)console.log(...)
GizmosOnDrawGizmos()Gizmos.Draw...()
Vector Addvector += othervector.add(other)
Vector Multiplyvector *= 2vector.multiplyScalar(2)

What's Next?

Continue learning:

  • Working with Unity Integration - Unity workflow and glTF export
  • Create Components - Build interactive components
  • Lifecycle Methods - Complete lifecycle API

Reference:

  • TypeScript Essentials - Core TypeScript/JavaScript concepts
  • Component Reference - Built-in components
  • Scripting Examples - Code examples
Suggest changes
Last Updated: 1/28/26, 10:47 AM

On this page

Extras

Copy for AI (LLMs)