Skip to content

Player API

Find players, read where they are and what they're doing, and (carefully) move them. These APIs work from any NexusScript — the object does not have to be an NPC.

Everything keys off a player id (a string). Get one, then pass it to the other calls.

Getting a player id

Enumerate everyone:

string[] ids = Networking.GetPlayers();        // every player in the world
for (int i = 0; i < ids.Length; i++) { string id = ids[i]; /* ... */ }
Also: Networking.GetPlayerCount(), Networking.GetPlayer(index), Networking.GetPlayerById(id).

Resolve one from an object or collider (e.g. in a trigger):

string id = Player.IdOf(other.gameObject);     // "" if it isn't a player

React to join / leave (these methods are called automatically — no wiring):

public void OnPlayerJoined(string playerId) { /* greet, add a UI row, assign a team... */ }
public void OnPlayerLeft(string playerId)   { /* remove their row, free a slot... */ }

Capture identity at join, not leave

OnPlayerLeft fires after the player is despawned, so GetUsername/GetUserId/GetPosition return blank there — only the playerId argument is reliable. If you need a leaving player's name or account id, read it in OnPlayerJoined and remember it (e.g. in Storage).

Identity

There are two ids, on purpose:

Call What it is Use for
Player.IdOf(obj) per‑session id (changes when they reconnect) "right now" lookups
Player.GetUserId(id) stable account id (same across sessions) tracking identity — rewards, visit logs, allow‑lists
Player.GetUsername(id) their account username (display/spoken) when you want the name shown
Player.GetName(id) the name an NPC knows them by NPC dialogue
string userId = Player.GetUserId(id);   // stable — track by this, never speak it
string name   = Player.GetUsername(id); // safe to show/speak

This split is what lets an NPC greet generically while still knowing who you are — see World Events.

Who's talking to the NPC right now

Inside an NPC action or chat callback, you often need the id of whoever is asking — without it you can't look up "my score" or "my save". Two zero‑arg calls give you the current speaker:

Call What it is
Player.GetSpeakerId() the current speaker's per‑session id ("" if the NPC isn't handling a message)
Player.GetSpeakerUserId() their stable account id — same as GetUserId(GetSpeakerId())
// Custom action "look up the player's score"
void OnGetScore()
{
    string uid = Player.GetSpeakerUserId();          // who asked — server-verified
    if (uid == "") return;
    // key the lookup to THEM (see the HTTP / Supabase page)
    HTTP.GetVia("scores-db", "/rest/v1/scores?select=score&user_id=eq." + uid);
}

The speaker id is set by the server from the validated login — the AI never supplies it, so a player can't say "tell me Bob's score" and have the NPC fetch someone else's row. See Custom actions and HTTP / Supabase.

Reading a player

Vector3 pos  = Player.GetPosition(id);
Vector3 head = Player.GetHeadPosition(id);
bool grounded = Player.IsGrounded(id);
Vector3 vel  = Player.GetVelocity(id);
Also GetRotation, GetHeadRotation, GetBonePosition/GetBoneRotation, GetAvatarHeight, IsValid, IsLocal.

Spatial helpers:

float d   = Player.GetDistanceTo(a, b);     // between two players
bool near = Player.IsInRange(a, b, 5f);
bool front = Player.IsInFrontOf(viewer, target);   // is target in viewer's view?
bool seen  = Player.IsVisible(a, b);               // clear line of sight?

Server‑side reads are best‑effort

Reads come from the synced transform on the server. Position, facing (IsInFrontOf/IsBehind), and line‑of‑sight (IsVisible) are accurate; velocity and head/avatar height are approximate (the server doesn't simulate the full avatar rig).

Controlling a player

You can move players from a script — the command is sent to that player's client and applied there, then synced to everyone:

Player.Teleport(id, new Vector3(0, 1, 10));
Player.SetWalkSpeed(id, 6f);
Player.SetJumpHeight(id, 2.5f);
Player.Immobilize(id);        // freeze input
Player.RestoreMobility(id);
Also SetVelocity/AddVelocity, SetRunSpeed, SetJumpImpulse, SetGravityStrength, EnableFlying/DisableFlying.

Movement control is experimental

Teleport and the movement setters are new and still being hardened in‑world. They're eventually consistent (a GetPosition right after Teleport may read the old spot until the client's update round‑trips), and EnableFlying is currently hover‑only. Test before relying on them in a published world. Reading and identity are solid.

Quick reference

Group Calls
Enumerate Networking.GetPlayers / GetPlayerCount / GetPlayer / GetPlayerById
Resolve Player.IdOf(obj) · OnPlayerJoined(id) / OnPlayerLeft(id)
Identity GetUserId · GetUsername · GetName
Current speaker GetSpeakerId · GetSpeakerUserId (who's talking to the NPC right now)
Read GetPosition / GetRotation / GetVelocity / IsGrounded / GetHeadPosition / GetBonePosition / IsValid / IsLocal
Spatial GetDistanceTo · IsInRange · GetNearby · IsInFrontOf · IsBehind · IsVisible
Control (experimental) Teleport · SetVelocity · AddVelocity · SetWalkSpeed · SetRunSpeed · SetJumpHeight · SetGravityStrength · Immobilize · RestoreMobility · EnableFlying · DisableFlying

→ See PlayerRoster.cs for a copy‑pasteable list/read/join‑leave example.