Entities and EntityRef
Find existing Runtime entities and control them safely through EntityRef.
On this page
Use api.entities() when you want to find an entity that already exists and control it from your game code.
EntityRef player = api.entities().requireTag("player");
player.transform().moveBy(4f, 0f);
player.animation().play("run");
The usual workflow is simple: find an entity, keep its EntityRef, and use the entity’s facades.
What EntityRef provides
EntityRef is the normal handle for an existing Runtime entity. It lets you check the entity, remove it, and read authored data without using lower-level ECS access directly.
Entity facades
EntityRef exposes focused facades for the capabilities of an entity:
EntityRef player = api.entities().requireTag("player");
player.transform();
player.sprite();
player.animation();
player.particles();
player.shader();
player.spatial();
Each facade stays tied to the EntityRef that produced it. If that entity is removed or its scene is replaced, it follows the same inactive-reference lifetime rules described below. Use the focused API pages for sprite, shader, animation, particle, and Spatial controls.
ecs() is a separate advanced escape hatch. Ordinary gameplay should normally use EntityRef and focused APIs first.
Transform
transform() provides the normal position, movement, rotation, scale, and origin controls used across Runtime APIs:
player.transform()
.setPosition(120f, 64f)
.moveBy(4f, 0f)
.setScale(2f)
.setRotationRad(0.5f);
For a standalone entity or top-level Game Object root, this is the normal authored world pose. For a Game Object member, it is the local transform relative to its parent, not the resolved world transform. See Game Objects for the hierarchy rules.
Authored geometry
geometry() reads rectangle, polygon, or polyline geometry authored on an entity. The geometry is read-only and reports whether it exists through exists() and kind():
EntityRef trigger = api.entities().requireTag("DamageZone");
AuthoredGeometryFacade shape = trigger.geometry();
if (shape.exists() && shape.kind() == AuthoredGeometryKind.RECTANGLE) {
float width = shape.width();
float height = shape.height();
}
Rectangle geometry provides width() and height(). Polygon and polyline geometry provide vertexCount(), localX(index), and localY(index); closed() distinguishes a polygon from a polyline.
Custom properties
Use properties() to read generic, read-only data authored on an entity, including properties imported from Tiled objects:
EntityRef enemy = api.entities().requireTag("Enemy");
int health = enemy.properties().getInt("health", 100);
float speed = enemy.properties().getFloat("speed", 80f);
boolean aggressive = enemy.properties().getBoolean("aggressive", false);
The typed getters return their fallback when a property is absent and throw when a present property has a different type. Properties can also store strings, colors, stable object references, and nested Class values.
Render order
Use renderOrder() to change an entity’s scene layer or local z-index from gameplay code:
EntityRef enemy = api.entities().requireName("Enemy");
enemy.renderOrder().set(4, 10);
layerIndex(...) preserves the z-index, zIndex(...) preserves the layer, and set(layerIndex, zIndex) changes both. Valid z-index values are -32768 through 32767. Spatial ordering can add 2.5D ordering for participating entities; it does not replace normal layer placement.
A Game Object root owns the hierarchy’s global Layer placement. Members inherit that effective Layer and keep their own local z-index, so layerIndex(...) and set(...) throw IllegalStateException on a member. Use zIndex(...) for member-local ordering or move the root to another Layer. See Game Objects.
Light capabilities
light() is a small read-only capability check. Use hasPoint() or hasCone() when application code needs to know which authored light type an entity has.
Finding an entity
Use a strict lookup when your game expects the entity to exist:
EntityRef player = api.entities().requireTag("player");
EntityRef enemy = api.entities().requireName("Enemy");
EntityRef savedEntity = api.entities().requireStableId(42);
EntityRef runtimeEntity = api.entities().requireEntityId(7);
require... throws if the entity cannot be found when you call it.
When several entities can share a tag, use findAllByTag(...). It returns a caller-owned snapshot with no ordering guarantee. A missing, blank, or null tag produces an empty array. Use requireTag(...) when one match is enough and absence is an error; if several entities share that tag, it does not promise which one it returns.
Use a tolerant lookup when a missing entity is an expected result:
EntityRef target = api.entities().ofStableId(42);
if (target.exists()) {
target.transform().moveBy(8f, 0f);
}
ofStableId(...) and ofEntityId(...) always return an EntityRef. When no matching entity exists, exists() is false and the reference can be handled safely.
stableId and entityId
Both ID types are Java int values, but they serve different purposes.
stableId
Use stableId when you need an identity that belongs to the Pixscape scene/runtime model and may need to be found again.
int stableId = player.stableId();
EntityRef samePlayer = api.entities().requireStableId(stableId);
entityId
entityId is the entity’s current ECS/runtime ID. It is useful when integrating with lower-level Artemis code, but it may be short-lived and can eventually be recycled.
int entityId = player.entityId();
A stable ID does not make an EntityRef permanent. The reference still represents the particular entity it originally found.
Converting IDs
Most gameplay code can keep an EntityRef and avoid manual ID conversion. When integration code needs the bridge, EntitiesAPI provides it:
EntitiesAPI entities = api.entities();
int stableId = entities.ensureStableId(player.entityId());
int entityId = entities.entityIdOf(stableId);
int sameStableId = entities.stableIdOf(entityId);
entityIdOf(...) returns -1 when the stable ID is missing. findEntityId(...) lets you choose a different fallback. You can also probe with existsStableId(...) and existsEntityId(...).
If the entity is removed
An EntityRef stays attached to the particular entity it originally resolved. If that entity is removed, or a new scene replaces the Runtime World:
exists()returnsfalsestableId()returns-1entityId()still returns the captured runtime ID for diagnostics- facades obtained from the reference remain attached to the original entity
- facade changes do nothing, and facade queries return their documented safe defaults
An EntityRef never jumps to another entity just because Artemis reuses the same numeric ID.
You do not need to constantly look up a live reference again during normal gameplay. After loading a different scene, look up the entities you need from that new scene.
Removing an entity
The simplest removal path is:
player.remove();
You can also remove through EntitiesAPI when you have a reference or an ID:
api.entities().destroy(player);
When all you have is an ID, use destroyEntityId(...) or destroyStableId(...).
Removal is scheduled and becomes visible through normal Runtime processing, such as the next rendered frame. Pixscape does not force an immediate World process just because one of these methods was called. Calling remove() on an inactive reference has no effect.
For a standalone entity, remove() removes that entity. For a Game Object hierarchy node, it removes that node’s surviving descendant subtree and any Physics joints made invalid by the removal. See Game Objects for hierarchy lifecycle behavior.
Direct ECS access
If a custom system or component really needs direct Artemis access, use api.ecs() or the escape hatch exposed by entity.ecs().
Most gameplay code can stay with EntityRef and its facades. See Expert ECS Access when lower-level integration is necessary.
Code examples
Find the player
Move a player entity after application input has produced a movement vector.
EntityRef player = api.entities().requireTag("player");
// inputX and inputY are application movement values.
player.transform().moveBy(inputX, inputY);
Find every enemy
Apply a short application-controlled freeze effect to every authored enemy.
EntityRef[] enemies = api.entities().findAllByTag("Enemy");
for (EntityRef enemy : enemies) {
// The returned array is an unordered snapshot.
enemy.transform().moveBy(-2f, 0f);
}
Create gameplay objects from tagged entities
Create application enemy controllers from Tiled or Studio-authored entities.
List<Enemy> enemies = new ArrayList<>();
for (EntityRef source : api.entities().findAllByTag("Enemy")) {
// Read read-only gameplay data authored on the entity.
int health = source.properties().getInt("health", 100);
float speed = source.properties().getFloat("speed", 80f);
// Enemy belongs to application gameplay code.
Enemy enemy = new Enemy(source, health, speed);
enemy.setPosition(source.transform().x(), source.transform().y());
enemies.add(enemy);
}
See Tiled Maps for how imported Object Layers map to entities.