UNAVI Docs unavi.xyz
Build · Scripting API

wired:physics

The rigid-body simulation: raycasts, and the motion of bodies a script may write.

The simulation runs on every peer. A body's motion is decided by the peer holding its document and sent to the others, so a write made on any other peer is overwritten by the holder's.

Interface simulation

Uses vec3, ray, document-id, prim-id, prim-ref, error, document.

ray-hit

record
target: prim-refThe prim whose collider was hit.
point: vec3
normal: vec3Unit length, facing back along the ray.
distance: f32

ray-filter

record

What a raycast passes through.

exclude-local-agent: boolSkips the local user's own body, so a ray from the camera does not stop at the head it starts in.
exclude-documents: list<document-id>Skips every collider in these documents. At most 64.

body-velocity

record

How a body is moving this step.

linear: vec3Meters per second, world space.
angular: vec3Radians per second about each world axis.

raycast

funcraycast: func(ray: ray, max-distance: f32, filter: ray-filter) -> result<option<ray-hit>, error>

The closest collider along ray within max-distance.

velocity

funcvelocity: func(document: borrow<document>, prim: prim-id) -> result<body-velocity, error>

Fails with not-ready until the prim's body is in the simulation, and invalid-argument for a body that is not dynamic.

set-velocity

funcset-velocity: func(document: borrow<document>, prim: prim-id, linear: option<vec3>, angular: option<vec3>) -> result<_, error>

Sets either velocity of a dynamic body, leaving none unchanged.

set-force

funcset-force: func(document: borrow<document>, prim: prim-id, force: vec3) -> result<_, error>

A world-space force the simulation applies every step until it is set again. Zero clears it.

Source

/// The rigid-body simulation: raycasts, and the motion of bodies a script
/// may write.
///
/// The simulation runs on every peer. A body's motion is decided by the peer
/// holding its document and sent to the others, so a write made on any other
/// peer is overwritten by the holder's.
package wired:physics;

interface simulation {
  use wired:core/math.{vec3, ray};
  use wired:core/ids.{document-id, prim-id, prim-ref};
  use wired:core/error.{error};
  use wired:scene/document.{document};

  record ray-hit {
    /// The prim whose collider was hit.
    target:   prim-ref,
    point:    vec3,
    /// Unit length, facing back along the ray.
    normal:   vec3,
    distance: f32,
  }

  /// What a raycast passes through.
  record ray-filter {
    /// Skips the local user's own body, so a ray from the camera does not
    /// stop at the head it starts in.
    exclude-local-agent: bool,
    /// Skips every collider in these documents. At most 64.
    exclude-documents:   list<document-id>,
  }

  /// How a body is moving this step.
  record body-velocity {
    /// Meters per second, world space.
    linear:  vec3,
    /// Radians per second about each world axis.
    angular: vec3,
  }

  /// The closest collider along `ray` within `max-distance`.
  raycast: func(ray: ray, max-distance: f32, filter: ray-filter) -> result<option<ray-hit>, error>;

  /// Fails with `not-ready` until the prim's body is in the simulation, and
  /// `invalid-argument` for a body that is not dynamic.
  velocity: func(document: borrow<document>, prim: prim-id) -> result<body-velocity, error>;

  /// Sets either velocity of a dynamic body, leaving `none` unchanged.
  set-velocity: func(
    document: borrow<document>,
    prim:     prim-id,
    linear:   option<vec3>,
    angular:  option<vec3>,
  ) -> result<_, error>;

  /// A world-space force the simulation applies every step until it is set
  /// again. Zero clears it.
  set-force: func(document: borrow<document>, prim: prim-id, force: vec3) -> result<_, error>;
}