Player
Everything the player is and does. Attached to the player's own avatar (the `body` entity inside the player prototype, so every peer gets one).
game.systems.Player
Everything the player is and does. Attached to the player's own avatar (the
body entity inside the player prototype, so every peer gets one).
It owns the torch and its battery, sprint and crouch with stamina, health, what is carried, which clues have been read, how far along the objective chain the player is, and what happens when they press E at something. It publishes all of it as fields so the interface can draw it and the creatures can hear it.
What it does not own
The house owns the doors and the hiding places; this reads an Interactable
marker on them and decides whether the player may pass. The run — objectives,
clues, the ending — lives in game.systems.PlayerState and in the shared
store, so a reload cannot lose it.
How it touches the engine
Two patterns worth keeping, both learned the hard way here:
- Finding what the player can use goes through the
scene.findtool, neverqueryEntitiesFlex: that function ignores a component filter and answers with every entity in the scene, so "nearest thing in front" becomes a wall. - Changing a field is a write onto the component object
(
comp.brightness = v). There is nocomponent.set. - Reach is three-dimensional. The house is stacked — the living room sits under the attic — so a distance test on x/z alone lets a player take the attic key from the room below.
Fields
active, difficulty, health, stamina, battery, torchOn, hiding,
objective, prompt, carrying, clues, ending — all read-only mirrors
of the state, for the interface.
Interface
What this asset declares: the schema it conforms to, what it exposes, and the rendered structured payload.
conforms to
zero/source-extract/v2game/systems/Player.component — everything the player IS and DOES. Attached to the player's own avatar. It owns the torch, stamina, health, the things carried, and what happens when the player presses a key at something — and it publishes all of it so the interface can draw it and the creatures can hear it. WHAT IT DOES NOT OWN. The house owns the doors and the hiding places; this reads an `Interactable` marker on them and decides whether the player may pass. The run — objectives, clues, the ending — lives in PlayerState and the shared store, not here, so a reload cannot lose it. SPRINTING IS THE CONTROLLER'S SPEED FIELDS, not a second mover. The character controller (the engine's own) already walks the body; stamina reaches it by moving `Locomotion.sprintSpeed` down to a walk the moment the bar empties, which is why running out of breath slows the player rather than being a number on a screen that means nothing.
setField(entityRef: any, componentType: string, values: { [string]: any }) → boolean
Changing a field on a component. There is no `component.set`: you read the component and write its field. Writing a field that does not exist is an error the engine reports, so this checks the read and reports the write rather than swallowing both — a torch whose brightness silently never changes is a bug nobody sees.
| arg | type | description |
|---|---|---|
| entityRef | any | |
| componentType | string | |
| values | { [string]: any } |
findAvatar( ) → void
findMyCamera( ) → void
The player's own camera, so the torch lights where they LOOK. The rig is a sibling of the body under the per-peer clone and there is more than one camera in the scene, so it is found by being the one nearest this avatar.
scanInteractables( ) → void
Interactables. Found by component, so one query gives every door, pickup, note, switch and hiding place in the house. Interactables, with their positions cached. Found with the `scene.find` TOOL, not `queryEntitiesFlex`: the latter ignores a component filter and answers with the whole population — 421 entities, cameras and staircase spindles among them — so "the nearest thing in front" becomes a wall. The tool filters properly and hands back each position, which is also 421 reads saved.
lookedAt( ) → void
What the player is looking at: near, and in front. The dot against the camera's forward is what makes "in front" mean the view rather than a radius, so a player is not offered a door behind them. The facing is the camera's own forward: `transform.forward` on the entity is its local -Z in world space, which is the direction the first-person controller aims. There is no `transform.direction(entity)` — that namespace's `direction` takes two POINTS (from and to) — so calling it with the camera threw, the pcall swallowed it, and the facing stayed at (0, -1): a player who could only ever reach what happened to be due north, wherever they were actually looking.
labelFor(row: any) → string
Using it.
| arg | type | description |
|---|---|---|
| row | any |
tryInteract( ) → void
publish( ) → void
publishShared( ) → void
The shared half of the state, so a second player sees the same door, the same key taken and the same objective.
attachTorch( ) → void
The torch: a spot light on the player's own camera, so it lights where they LOOK rather than where the body happens to face. IT HAS TO BE RETRIED. The avatar does not exist when this component starts — a player joins after the scene is already up — so attaching the light once in `awake` is a torch that nobody ever gets. This is called every frame until it succeeds.
awake( ) → void
update(dt: ?) → void
| arg | type | description |
|---|---|---|
| dt | ? |
onDestroy( ) → void
Sub-parts
Everything contained inside this part. Assets are composite children (clickable cards). Files are leaf payloads. Expand any row to view its source.
Showing up to 3 levels deep. Open a part to see what it holds further down.
Problems
Everything affecting this asset right now: its own problems, anything wrong inside it, and problems on its direct dependencies.
agent_score is exposed.+ quality × 0.35
+ performance × 0.25
± compat factor
Usability ratings
Did the part work as advertised when consumers tried to drop it in. Separate from upvotes: those are taste; this is "did it function".
Scoped to this part · feeds back into the world's score.