Skip to content

feat: add zero-allocation scalar getters/setters for RigidBody, Collider, and KinematicCharacterController#365

Open
GbGr wants to merge 1 commit intodimforge:masterfrom
GbGr:feat/scalar-getters-setters
Open

feat: add zero-allocation scalar getters/setters for RigidBody, Collider, and KinematicCharacterController#365
GbGr wants to merge 1 commit intodimforge:masterfrom
GbGr:feat/scalar-getters-setters

Conversation

@GbGr
Copy link

@GbGr GbGr commented Mar 6, 2026

Summary

Add scalar component getters and setters that return/accept individual f32number values, bypassing all intermediate struct creation, WASM heap allocation, and JS wrapper object overhead.

Motivation

Every call to RigidBody.translation(), .rotation(), .linvel(), etc. currently creates multiple short-lived allocations:

  1. Rust allocates a RawVector/RawRotation struct on the WASM heap (Box::new)
  2. wasm-bindgen wraps the WASM pointer in a JS object (Object.create + FinalizationRegistry)
  3. VectorOps.fromRaw() reads .x/.y via WASM getter calls, creates a new Vector2/Vector3/Quaternion, calls raw.free()

For game engines doing syncDynamicFromRapier with hundreds of entities at 60+ ticks/sec (with rollback resimulation multiplying that), this creates tens of thousands of short-lived allocations per second — unnecessary GC pressure.

The new scalar methods return primitives directly through the WASM stack, eliminating all allocations.

Per-call savings (getter)

Old path New path
WASM boundary crossings 4 1
WASM heap allocs 1 0
JS object allocs 2 0
WASM free calls 1 0

Changes

Rust (src/)

Getters (return f32, zero-alloc):

  • RawRigidBodySet: rbTranslationX/Y(/Z), rbRotationAngle (2D), rbRotationX/Y/Z/W (3D), rbLinvelX/Y(/Z)
  • RawColliderSet: coTranslationX/Y(/Z), coRotationAngle (2D), coRotationX/Y/Z/W (3D)
  • RawKinematicCharacterController: computedMovementX/Y(/Z)

Setters (accept scalar args, avoid RawVector heap allocation):

  • RawRigidBodySet: rbSetLinvelXY/XYZ, rbAddForceXY/XYZ, rbApplyImpulseXY/XYZ

TypeScript (src.ts/)

Corresponding methods on RigidBody, Collider, and KinematicCharacterController classes. All existing methods remain unchanged for backwards compatibility.

Tests

  • rapier-compat/tests/ScalarGetters2d.test.ts
  • rapier-compat/tests/ScalarGetters3d.test.ts

Verifies scalar getters match existing struct-returning methods, and scalar setters work correctly.

Backwards compatibility

Purely additive — no existing method signatures or return types were changed.

…der, and KinematicCharacterController

Add scalar component getters that return individual f32→number values,
bypassing all intermediate struct creation, WASM heap allocation, and
JS wrapper object overhead.

Getters:
- RigidBody: translationX/Y(/Z), rotationAngle (2D), rotationX/Y/Z/W (3D), linvelX/Y(/Z)
- Collider: translationX/Y(/Z), rotationAngle (2D), rotationX/Y/Z/W (3D)
- KinematicCharacterController: computedMovementX/Y(/Z)

Setters (scalar-argument alternatives avoiding VectorOps.intoRaw() allocation):
- RigidBody: setLinvelXY/XYZ, addForceXY/XYZ, applyImpulseXY/XYZ

Each existing struct-returning method (translation(), rotation(), linvel(), etc.)
remains unchanged for backwards compatibility.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant