Skip to content

prisma-dev/delta

Repository files navigation

Delta

A deterministic physics simulation library for Roblox written in TypeScript.

Table of Contents

Overview

The library provides a modular, deterministic physics simulation system for Roblox. The library operates entirely in world units (meters, m/s, m/s²) and features:

  • Translation and Rotation: Euler integration for position, velocity, and rotation.
  • Collision Detection: Supports both simple AABB (for point and box collisions) and oriented bounding box (OBB) collision detection for static, rotated objects.
  • Collision Resolution: Impulse-based resolution with restitution and friction impulses.
  • Friction & Damping: Applies friction and damping on dynamic objects when in contact with static objects.
  • Customizable Time Control: Fixed time step integration with a SetTime method for fast-forwarding the simulation.

Features

  • World-Unit Integration: All positions, velocities, and forces are expressed in world units.
  • Oriented Static Collision: Supports collisions with rotated static platforms via OBB calculations (no physical part is required).
  • Dynamic Collision Resolution: Uses impulse-based resolution with friction between dynamic objects.
  • Rotational Dynamics: Updates rotation, angular velocity, and angular acceleration.
  • Time Control: A fixed time-step integrator and a SetTime method that advances simulation until the target time is reached.

Installation

NPM

  1. In the terminal run: npm i @rbxts/delta

Pesde

  1. For luau you must use the pesde package manager
  2. To add the package run: pesde add prismatyx/delta
  3. to install the package run pesde install

Roblox

  1. For Roblox, navigate to the github releases page
  2. Download the rbxm file of the latest version

Usage

TypeScript

import { PhysicsEngine, PhysicsObject } from "@rbxts/delta";

// Create engine and start it.
const engine = new PhysicsEngine();
engine.Start();

// Create a ball.
const ball = new PhysicsObject(
	"ball",
	{
		mass: 10,
		friction: 0.5,
		elasticity: 0.8,
		collisionMethod: "box",
		size: new Vector3(2, 2, 2),
		ignoreGlobalForces: false,
	},
	{
		position: new Vector3(0, 10, 0),
		velocity: new Vector3(0, 0, 0),
		acceleration: new Vector3(0, 0, 0),
		forces: [],
	},
);

// Create a static platform.
const platform = new PhysicsObject(
	"platform",
	{
		mass: 1e9,
		friction: 0.4,
		elasticity: 0.4,
		collisionMethod: "box",
		size: new Vector3(20, 2, 20),
		ignoreGlobalForces: true,
	},
	{
		position: new Vector3(0, 0, 0),
		velocity: new Vector3(0, 0, 0),
		acceleration: new Vector3(0, 0, 0),
		forces: [],
	},
);

// Add objects to the engine.
engine.AddObject("ball", ball);
engine.AddObject("platform", platform);

// Add gravity.
engine.AddGlobalForce("gravity", new Vector3(0, -9.81, 0));

// Simulate.
game.GetService("RunService").Stepped.Connect((_, dt) => {
	engine.Step(dt);
});

Luau

local delta = require(game.ReplicatedStorage.delta)
local PhysicsEngine = delta.PhysicsEngine
local PhysicsObject = delta.PhysicsObject

local engine = PhysicsEngine.new()
engine:Start()

local ball = PhysicsObject.new("ball", {
	mass = 10,
	friction = 0.5,
	elasticity = 0.8,
	collisionMethod = "box",
	size = Vector3.new(2, 2, 2),
	ignoreGlobalForces = false,
}, {
	position = Vector3.new(0, 10, 0),
	velocity = Vector3.new(0, 0, 0),
	acceleration = Vector3.new(0, 0, 0),
	forces = {}
})

local platform = PhysicsObject.new("platform", {
	mass = 1e9,
	friction = 0.4,
	elasticity = 0.4,
	collisionMethod = "box",
	size = Vector3.new(20, 2, 20),
	ignoreGlobalForces = true,
}, {
	position = Vector3.new(0, 0, 0),
	velocity = Vector3.new(0, 0, 0),
	acceleration = Vector3.new(0, 0, 0),
	forces = {}
})

engine:AddObject("ball", ball)
engine:AddObject("platform", platform)
engine:AddGlobalForce("gravity", Vector3.new(0, -9.81, 0))

game:GetService("RunService").Stepped:Connect(function(_, dt)
	engine:Step(dt)
end)

API Documentation

PhysicsObject

  • Constructor:
    new(id: string, properties: PhysicsObjectProperties, state?: ObjectState, part?: BasePart)
    Creates a new physics object.
    Properties:

    • mass: Mass of the object.
    • friction: Friction coefficient (default 0.3).
    • damping: Additional damping for contact with static objects (default 0.5).
    • elasticity: Restitution coefficient (default 0.4).
    • momentOfInertia: Rotational inertia (default 1).
    • collisionMethod: "box", "point", or "none".
    • size: For box collisions, the dimensions of the hitbox.
    • ignoreGlobalForces: If true, the object will not receive global forces (e.g. static objects).
  • ApplyForce(force: Vector3, offset?: Vector3): void
    Applies a force (and optional offset for torque) to the object.

  • Update(dt: number): void
    Updates the object state (position, velocity, rotation) over a time step.

  • GetWorldPosition(): Vector3
    Returns the current world position.

  • GetState(): PhysicsObjectState
    Returns the current state (position, velocity, acceleration).

  • Destroy(): void
    Cleans up the object.

PhysicsEngine

  • Constructor:
    new()
    Creates a new physics engine instance.

  • Start(): void
    Starts the simulation.

  • Stop(): void
    Stops the simulation.

  • Step(realDeltaTime: number): void
    Advances the simulation by the given delta time (adjusted by timeScale).

  • SetTime(targetTime: number): void
    Advances the simulation until the current time reaches the target time.

  • AddGlobalForce(name: string, accel: Vector3): void
    Adds a global force (provided as acceleration) to all dynamic objects.

  • AddObject(id: string, object: PhysicsObject): void
    Adds a physics object to the simulation.

  • DestroyObject(id: string): void
    Removes and destroys the object with the given id.

  • GetObject(id: string): PhysicsObject | undefined
    Retrieves an object by its id.

  • GetObjects(): PhysicsObject[]
    Returns all physics objects.

Notes

  • Rotational Collisions:
    The library currently updates rotation via applied torques but doesn't automatically compute collision based torques. This will be added sometime in the future

  • Performance:
    Point collision detection is simpler and is more performant than box collision. However, the performance difference is generally negligible unless you have a very large number of objects

  • Customization:
    Adjust parameters (mass, friction, damping, elasticity, fixedDeltaTime) to tune the simulation behavior to your needs

License

This project is licensed under the MIT License. See the LICENSE file for details.

About

Deterministic physics library for Roblox

Resources

Stars

Watchers

Forks

Packages

No packages published