Recipes
Turrets auto-aim and target tracking guns
A fixed gun watches an area, swivels to the closest enemy, and fires without a player pulling the trigger. There is no TurretComponent; a turret is a find-rotate-fire loop composed from world queries, a Transform patch, and the projectile recipe.
engine v1.0.234since script-semantic-patch-ops.v1, action-catalog.v1.0.232, world.v1, physics.v1, timer.v1, spawn.v1, mutation.v1Copy for LLM
Use this for
a stationary turret or sentry that finds a target and fires on its own; a tower or cannon that rotates to track the nearest enemy; auto-aiming mounted guns; lock-on tracking
Not for
a player-aimed weapon fired by input (see projectiles-and-ranged-weapons); a moving enemy that walks and chases (see npc-enemy-navigation); melee contact damage (see combat-damage-and-respawn)
Pairs with: Projectiles bullets and ranged weapons, NPC and enemy navigation chase and patrol behavior, Timers countdowns cooldowns and enemy waves, Combat damage health and respawn scripting
The recipe
Author with project_apply_script_semantic_patch using the ai_safe op pack.
- Acquire a target each think:
addTickHandler{ "handlerKey":"onTrack" }, and inside a GessaScript body (replaceScriptFromGessaScript) callctx.world.findwith a tag and a radius (orfindEntitiesByTag) to list candidates, then pick the nearest by comparing positions. - Face the target: compute the aim direction to the chosen target and
ctx.entity.patchComponentthe turret barrelTransformComponentrotationto point at it. Parent the barrel under a base pivot withctx.entity.setParentif only the barrel should swivel. - Line of sight (optional):
ctx.physics.shapecastfrom the muzzle toward the target and only fire if the cast reaches the target and is not blocked. - Fire on a cooldown: gate firing with a
TimerComponentplusaddTimerHandler(or a last-fired timestamp in state withsetBooleanStateareadyflag). On fire,spawnEntityFromTemplate{ "prefabKey": <projectile> }at the muzzle and launch it withctx.physics.command(see projectiles-and-ranged-weapons for the launch and impact damage). - Idle when no target: if the query returns nothing, hold or slowly sweep the barrel and do not fire.
Pitfalls
- Recompute the nearest target on a throttled tick, not every frame; unbounded per-tick world scans are costly (keep the query radius and limit small).
- Rotate the barrel through
ctx.entity.patchComponent; never writeVelocityComponentto spin it (it is engine-internal and hidden from authoring). - Aim uses the target's live position; lead the shot for fast movers by aiming ahead, since the projectile takes time to travel.
- The turret fires for all players from the authority; do not run a parallel client-side turret or shots will duplicate.
Verify
simulation_run(qa.run.start) to prove the turret acquires the nearest target, rotates to face it, and fires on its cooldown.project_get_graph_snapshotto confirm the tracking tick handler and the fire cooldown timer landed.