Skip to content

Physics

NexusScript exposes Unity's physics: cast rays, find overlapping objects, push rigidbodies, and react to collisions and triggers. Semantics match Unity exactly.

Physics runs on the client

Queries and forces execute in each player's local simulationPhysics.Raycast sees that client's scene. This is perfect for local gameplay (what am I looking at, did my shot hit, is the ground below me). For anything that must be the same for everyone — who got hit, did the door open for all — drive it through an authoritative path: an NPC/server action, a networked world object, or Player reads (which come from the server's synced transforms). Don't let each client raycast and reach its own conclusion about a shared outcome.

Raycasts — "what's in this direction?"

RaycastHit hit;
if (Physics.Raycast(transform.position, transform.forward, out hit, 50f))
{
    Vector3 where = hit.point;            // world point of contact
    Vector3 n     = hit.normal;           // surface normal
    float dist    = hit.distance;
    GameObject obj = hit.collider.gameObject;
    Debug.Log("Looking at " + obj.name + " at " + dist + "m");
}

The signature is the Unity one: Physics.Raycast(origin, direction, out hit, maxDistance, layerMask). maxDistance and layerMask are optional; omit out hit if you only need a yes/no.

Cast Use
Physics.Raycast(origin, dir, out hit, dist, mask) single thin ray
Physics.RaycastAll(origin, dir, dist) array of everything along the ray
Physics.SphereCast(origin, radius, dir, out hit, dist, mask) thick ray (e.g. a ball's path)
Physics.BoxCast · Physics.CapsuleCast swept box / capsule
Physics.Linecast(start, end, out hit, mask) ray between two points
Camera cam = Camera.main;
Ray ray = cam.ScreenPointToRay(Input.mousePosition);   // ray from where the cursor points
if (Physics.Raycast(ray.origin, ray.direction, out hit, 100f)) { /* clicked-on object */ }

Overlaps — "what's here?"

Collider[] near = Physics.OverlapSphere(transform.position, 5f);  // everything within 5 m
for (int i = 0; i < near.Length; i++)
{
    string pid = Player.IdOf(near[i].gameObject);
    if (pid != "") { /* a player is in range */ }
}

bool blocked = Physics.CheckSphere(spawnPoint, 1f);   // is the spot occupied?

Also Physics.OverlapBox(center, halfExtents) and Physics.OverlapCapsule(p0, p1, radius).

Queries are capped at 32 results

For performance, overlap and RaycastAll queries return at most 32 colliders. If you expect dense crowds, query a tighter radius or filter with a layer mask rather than relying on getting everything back.

Layer masks

Restrict a cast to specific layers:

int mask = LayerMask.GetMask("Interactable", "Enemy");
if (Physics.Raycast(origin, dir, out hit, 30f, mask)) { /* only those layers */ }
LayerMask.NameToLayer(name) → layer index; LayerMask.LayerToName(index) → name.

Rigidbodies — push things around

Get the Rigidbody off an object, then apply force, set velocity, or move it. Forces belong in FixedUpdate.

Rigidbody rb = ball.GetComponent<Rigidbody>();

protected override void FixedUpdate()
{
    rb.AddForce(Vector3.up * 10f);                 // continuous push (ForceMode.Force)
    rb.AddForce(transform.forward * 5f, 1);        // ForceMode.Impulse (instant) — see below
}

rb.velocity = new Vector3(0, jump, 0);  // set velocity directly (also: angularVelocity)
rb.AddTorque(Vector3.up * 2f);          // spin it
rb.MovePosition(target);                // kinematic move that still collides

AddForce/AddTorque take an optional ForceMode as an int: 0 Force, 1 Impulse, 2 VelocityChange, 3 Acceleration. Tunables: mass, drag, angularDrag, useGravity, isKinematic, position, rotation.

CharacterController — move avatars/NPCs without physics jitter

For controller‑style movement (no bouncing, climbs steps, slides along walls):

CharacterController cc = GetComponent<CharacterController>();
cc.Move(new Vector3(x, fall, z) * Time.deltaTime);   // collide-and-slide
bool grounded = cc.isGrounded;
cc.SimpleMove(dir * speed);                          // applies gravity for you
Properties: height, radius, center, slopeLimit, stepOffset, skinWidth, velocity, isGrounded, collisionFlags.

Collision & trigger callbacks

Define these by name (no override) — the runtime calls them when this object's collider touches another. Use triggers for "passed through" zones, collisions for solid impacts.

void OnTriggerEnter(Collider other)        // a collider entered our trigger volume
{
    string pid = Player.IdOf(other.gameObject);
    if (pid != "") Debug.Log(Player.GetUsername(pid) + " entered the zone");
}
void OnTriggerExit(Collider other) { }
void OnTriggerStay(Collider other) { }      // every frame while overlapping

void OnCollisionEnter(Collision c)         // solid hit
{
    Vector3 force = c.impulse;
    Vector3 vel   = c.relativeVelocity;
    ContactPoint p = c.GetContact(0);       // p.point, p.normal
    if (vel.magnitude > 8f) { /* hard hit — break / sfx */ }
}
On the argument Read
Collider other other.gameObject · other.transform · other.bounds · other.isTrigger · other.attachedRigidbody · other.CompareTag(t)
Collision c c.collider · c.gameObject · c.relativeVelocity · c.impulse · c.contactCount · c.GetContact(i)

A trigger needs a trigger collider

OnTrigger* fires only if one of the two colliders has Is Trigger checked (set it in the editor or col.isTrigger = true), and at least one of the objects has a Rigidbody. OnCollision* fires for solid (non‑trigger) colliders.

2D physics

The common 2D calls exist too: Physics2D.Raycast, and Rigidbody2D (AddForce, AddTorque, MovePosition, velocity, gravityScale, …), Collider2D (enabled, isTrigger). Use them only in 2D worlds.

Global gravity is read‑only

Physics.gravity can be read but not set from a creator script (it's a world‑wide setting that would affect everyone unpredictably). To make one object float or fall differently, set rb.useGravity = false and apply your own force, or use Player.SetGravityStrength for a player.

Quick reference

Group Calls
Casts Physics.Raycast · RaycastAll · SphereCast · BoxCast · CapsuleCast · Linecast
Overlaps Physics.OverlapSphere · OverlapBox · OverlapCapsule · CheckSphere · IgnoreCollision
Hit info RaycastHit.point / normal / distance / collider / transform / rigidbody
Layers LayerMask.GetMask · NameToLayer · LayerToName
Rigidbody AddForce · AddTorque · velocity · angularVelocity · MovePosition · MoveRotation · mass · useGravity · isKinematic
Controller CharacterController.Move · SimpleMove · isGrounded · velocity
Callbacks OnTriggerEnter/Stay/Exit(Collider) · OnCollisionEnter/Stay/Exit(Collision)

→ See the Look‑to‑interact recipe for a complete look‑and‑use script. Next: Player API for server‑authoritative spatial reads.