Skip to content

Server scripts (authoritative)

Normally a NexusScript runs on each player's client. That's right for most world logic, but it means the script can't be authoritative — it can't own the truth of where an enemy is or how much damage it dealt, because every client runs its own copy. The server-only Combat.* / Health.* APIs simply aren't reachable from a client script.

Add a Server Script component (Add Component ▸ Social Scape/Server Script (Authoritative)) next to your NexusScript and that script instead runs its whole lifecycle (Start, Update, FixedUpdate, …) on the server — the single authority. Now it can move a server-owned object, and it can call Combat.* / Health.*. This is the advanced, scripted path for custom server logic and enemy AI; the no-code path is the Enemy component.

Use Enemy for turnkey combat NPCs

A fully autonomous enemy that hunts players — perception, chase, attack, flee, respawn — is a drop-in with the Enemy component, no scripting. Reach for a Server Script when you want behaviour Enemy doesn't cover: a custom state machine, a scripted boss phase, a turret with your own targeting rules, a server-driven puzzle or spawner.

How it runs

Where Does the flagged script tick?
Dedicated server Yes — this is the authority.
Editor test player Yes — the editor is treated as the authority, so you can develop offline.
A remote player's client No — clients only see the synced result.

Because only the server runs it, there's no double-execution and a modified client can't move the object or fake its hits. The script stays fully sandboxed and runs under a tighter per-frame budget than a client script, so a runaway can't stall the shared server tick — keep per-frame work light.

Set it up

A server script that moves an object (an NPC) needs a few companions on the same GameObject:

  1. Your NexusScript (the logic).
  2. Server Script (Social Scape/Server Script (Authoritative)) — the marker that moves execution to the server.
  3. Network Transform (Social Scape/Network Transform) — server-owned, so clients see the motion the script drives.
  4. A NavMeshAgent + a baked NavMesh if the script pathfinds, and a Collider if it should be shootable.

A server script that only reacts (a timer, a scripted door, a spawner) needs just items 1–2.

What you can call server-side

  • Combat & HealthCombat.ApplyDamage, Combat.Kill, Combat.ApplyRadiusDamage, Health.GetHealth / GetSelfHealth, etc. (These are server-only and are the whole reason to run on the server.)
  • PerceptionPlayer.GetNearby(range) returns the players within range of this object (see the Player API); from a server script the origin is the NPC itself, so it's real server-side perception.
  • MovementNavMeshAgent.SetDestination, speed, stoppingDistance, velocity, remainingDistance, hasPath, pathPending, isStopped, isOnNavMesh, Warp(pos) (teleport onto the mesh — spawn/respawn), ResetPath, and NavMesh.SamplePosition(point, maxDistance) (snap a point onto the mesh — pick a valid flee/target spot).
  • Everything a normal script can: GameObjects/Transforms, math, timing, your own state.

Don't read input or the camera

There is no player on the server — Input.* and camera reads return empty values. A server script must decide everything from world state, not local input.

Example — a simple patrol

Move between two points, pausing at each. Pure server-side motion — no client involved:

public class Patrol : NexusBehaviour
{
    private Vector3 a;
    private Vector3 b;
    private bool goingToB;

    void Start()
    {
        a = transform.position;
        b = a + new Vector3(10f, 0f, 0f);   // 10 m along X
        NavMeshAgent.SetDestination(b);
        goingToB = true;
    }

    void Update()
    {
        // Arrived? head back the other way.
        if (NavMeshAgent.hasPath && NavMeshAgent.remainingDistance <= 0.4f)
        {
            goingToB = !goingToB;
            NavMeshAgent.SetDestination(goingToB ? b : a);
        }
    }
}

Swap the patrol logic for your own state machine — a boss that changes attacks by HP (Health.GetSelfHealth()), a turret that fires when a target is in range, a wave spawner. When you have a target, deal damage with Combat.ApplyDamage.

Building a combat NPC in script

You now have the pieces for a fully autonomous scripted hunter: perceive with Player.GetNearby, read a player's position from the Player API, chase with NavMeshAgent.SetDestination, attack in range with Combat.ApplyDamage, and flee to a valid spot with NavMesh.SamplePosition. Use Warp to place the NPC on the mesh at spawn/respawn and isOnNavMesh to guard moves. If you just want that behaviour with no scripting, the Enemy component still does it out of the box — reach for a Server Script when you need rules Enemy doesn't cover.

Perceiving players on the server

A server script sees players three ways: Player.GetNearby / Player.GetDistance (the roster), Physics.OverlapSphere / Raycast / Linecast against the player's collider, and the networked Player.GetPosition / GetHeadPosition / GetHandPosition. Player avatar meshes aren't created on the server (they're client-only visuals), so avatar-bone reads (Player.GetBonePosition) return nothing for a player server-side — use the position and head/hand reads instead. NPCs, by contrast, are fully present server-side.

Current limit

  • Inspector list fields don't reach scripts. A public List<Transform> / array on your script arrives empty at runtime (you'll see a warning). Set waypoints in code, or reference a single container GameObject and gather its children at Start() with GetComponentsInChildren (or find by name/tag).
  • Enemies — the no-code combat NPC (perception + chase + attack + respawn).
  • Health & combat — the Combat.* / Health.* APIs a server script can call.
  • Basics & lifecycleStart / Update and the normal (client) execution model this overrides.

Component class names (for scripts and search): SSServerScript.