Skip to main content

Actor state

An actor is a concrete character instance in the world — the thing that walks around in a specific game (app), at a position (chunk). An actor optionally references an avatar (the reusable "class"/identity), and carries its own state.

Like avatars, actors follow the rule: only the owner can write; everyone can read the public parts. All operations require a logged-in player.

Actors vs avatars: an avatar is a position-less identity a player owns and can reuse across games; an actor is one in-world instance of a character in a single game, with a position and its own per-instance state.

The actor record

FieldMeaning
uuidThe actor's id — a 32-byte string used by the realtime protocol (not a hyphenated UUID)
appIdThe game this actor lives in
userIdThe owner
avatarIdOptional link to one of the owner's avatars
chunkThe chunk the actor is in ({ x, y, z })
publicStateVisible to everyone (base64 binary)
privateStateVisible to the owner only (base64 binary)

An actor record can come into existence two ways:

  • Explicitly, by calling createActor (below).
  • Automatically, when the player starts moving in the world — the realtime layer creates/updates the actor as actor updates arrive. See GraphQL UDP Proxy API.

Creating an actor

mutation {
createActor(input: {
appId: "1",
uuid: "0123456789abcdef0123456789abcdef", # exactly 32 bytes (UTF-8)
avatarId: "5", # optional
chunk: { x: "0", y: "0", z: "0" },
publicState: "AAEC",
privateState: "BQYH"
}) { uuid appId chunk { x y z } }
}

You can only attach an avatarId that you own.

Writing state (owner only)

Use updateActorState for state-only changes, or updateActor to also move the actor or change its avatar:

mutation {
updateActorState(uuid: "0123...", input: {
publicState: "AAEC",
privateState: "BQYH"
}) { uuid }
}

deleteActor(uuid) removes an actor you own.

Reading state

OperationReturns
actor(uuid)One actor. The owner sees privateState; everyone else sees public state only.
actors(filter)Your own actors (filter by appId, avatarId, uuid, or chunk).
batchLookupActors(input: { uuids })Public state for the given actors — use this to read other players' actors in bulk.
query {
actor(uuid: "0123...") { uuid chunk { x y z } publicState privateState }
}

query {
batchLookupActors(input: { uuids: ["0123...", "89ab..."] }) {
uuid publicState
}
}

Realtime movement vs persisted state

The publicState / privateState on the actor record are persisted state you set with the mutations above. A player's fast-changing live transform (position within the chunk, rotation, animation) flows over the realtime channel via sendActorUpdate and is broadcast to nearby players — see GraphQL UDP Proxy API. Sending actor updates is also what makes a player a host candidate.

Use persisted actor state for things that should survive and be queryable (equipment, status, customization); use the realtime channel for per-frame motion.

Grid permissions and actors

When grid permissions are active in your world, what an actor may do as it moves is governed by grid permissions: a player needs access to enter/act in a region, update_voxel_data to build there, and use_voice_chat for voice. See Permissions overview.

Reference

See the Game API GraphQL reference for the exact inputs and return types.