Project 04: Vehicle spawner
In Project 03, you built an allied bodyguard who follows on foot. In Project 04, you tackle motorized vehicles. Your objective is to build a reliable vehicle spawner that queries the navigation mesh, snaps an empty car to the nearest legal road node ahead of the player, settles its tires on the asphalt using physical ground alignment, and cleans up properly.
The mission
Build an empty vehicle spawner fulfilling five core technical deliverables:
- Query the game's road navigation grid to locate the nearest valid street node ahead of the player.
- Gracefully handle off-road terrain where no street node exists without throwing exceptions.
- Stream a vehicle model asynchronously into memory with timeout safety.
- Spawn an empty vehicle at the snapped road coordinates and stabilize its suspension via
PlaceOnGround. - Maintain single-vehicle ownership to prevent multiple cars spawning on top of each other.
- Cleanly delete the vehicle when reloading the script.
Specifications, constraints
- Empty vehicle exclusively: Do not spawn an AI driver in this project; AI driving navigation is taught in Lesson 48 before the Complete Mod.
- Road node snapping: Always query candidate positions using
World.GetNextPositionOnStreetand test againstVector3.Zero. - Ground collision settling: Invoke
PlaceOnGround()immediately after vehicle creation to avoid physics glitches or vehicles falling through the world. - Persistence flag: Set
_car.IsPersistent = trueto protect the vehicle from ambient culling when walking away. - Zero orphan vehicles: Enforce complete entity deletion in
OnAborted.
Implementation steps
- Declare vehicle tracking: Define a private field
private Vehicle _car;in your script class. - Wire lifecycle events: In the constructor, attach event handlers to
TickandAborted. - Check active ownership: In
OnTick, check if_caris non-null and exists. If so, return immediately to enforce single-car ownership. - Locate the nearest street: Calculate a candidate position 25 meters forward (
player.Position + player.ForwardVector * 25f) and queryWorld.GetNextPositionOnStreet. - Handle off-road fallback: If the returned coordinate equals
Vector3.Zero, exit the method cleanly without spawning. - Stream vehicle model: Create a
ModelwithVehicleHash.Dominatorand callmodel.Request(2000). Abort if streaming fails. - Instantiate and settle: Inside a
try-finallyblock, callWorld.CreateVehicle, assignIsPersistent = true, and execute_car.PlaceOnGround(). - Release model handle: In the
finallyblock, callmodel.MarkAsNoLongerNeeded(). - Implement teardown: In
OnAborted, verify that_carexists and call_car.Delete().
APIs, tools to explore
GTA.World.GetNextPositionOnStreet(Vector3 position): Scans the game's navigation network to find the closest road node coordinate.GTA.Vehicle: High-level wrapper representing motor vehicles, planes, helicopters, and watercraft.GTA.World.CreateVehicle(Model model, Vector3 position, float heading): Spawns a physical vehicle entity in the world.Vehicle.PlaceOnGround(): Snaps the vehicle's wheels and collision chassis firmly onto the underlying terrain mesh.Entity.IsPersistent: Informs the ambient garbage collector that this entity must remain loaded regardless of camera distance.GTA.VehicleHash.Dominator: Model hash representing the Vapid Dominator muscle car.
Validation checklist
Your mod is validated when:
- Standing on or near a roadway causes the Dominator to spawn directly on the asphalt ahead of the player.
- The vehicle sits stable on its wheels with zero bouncing, clipping, or chassis deformation.
- Standing in deep mountains or open water far from roads prevents spawning without generating script errors.
- Walking away from the vehicle does not cause the engine to despawn it prematurely.
- Reloading the script with
Insertdeletes the vehicle cleanly.
Solution, explanations
Partner
Verified solution and code explanations
The mission, specifications, and guided steps remain 100% free and open for everyone. The complete verified reference code and production explanations are reserved for Partner members.