Projectiles
Overview
The ProjectileSystem
provides a mechanism for updating projectiles and detecting hits.
It supports continuous collision detection (CCD) through a 2 phase process:
- Query Phase: At the beginning of each frame, the
ProjectileQuerySystem
sets up broadphase queries for each projectile. It runs after thePredictionAreaSystem
but before thePhysicsSystem3D
. By default it queries a linecast or shape overlap from the projectile's current position to next position calculated based on its velocity. These queries are then resolved during thePhysicsSystem3D
tick. - Logic Execution Phase: The results of the broadphase queries are retrieved by the
ProjectileSystem
from thePhysicsSystem3D
and forwarded to theProjectileController
. This is the stage at which the projectiles' logic is executed in the frame. If a system depends on a projectile having executed its logic, that system needs to run afterProjectileSystem
- the order in which systems are executed is defined by their order inSystemSetup.cs
.
Projectile
A projectile is its own entity. Every projectile entity carries:
- a
Projectile
component; - a concrete implementation of the
ProjectileController
; - a
PhysicsCollider3D
; and, - a
PhysicsBody3D
.
The requirements regarding the PhysicsCollider3D
and PhysicsBody3D
can be overriding via the concrete implementation of the ProjectileController
methods. Please check implementations included with the FPS Template for more details.
Controller API
The ProjectileController
is an abstract class. It is used to create concrete implementation for each type of projectiles. The following API is used to process all projectile conctrollers in the ProjectileQuerySystem
and ProjectileSystem
:
OnInitialize()
: Called once when the projectile is spawnedOnDeinitialize()
: Called once when the projectile is destroyedOnUpdate()
: Called every frame, updates projectile position / velocity / ...OnProcessHits()
: Base implementation resolves closest hit, optionally ignores owner, teleports projectile to hit point and destroys the projectile on first hitAddPhysicsQuery()
: Base implementation add linecast / shape overlap query based on position and velocity in thePhysicsBody3D
, shape is defined by thePhysicsCollider3D
Concrete Implementations
The concrete implementations of the ProjectileController
included in the FPS Template are:
FPSProjectileController
: Extends the default behavior with damage, knockback, target penetration, bouncing settings and hit effects. This is the base controller for all FPS projectiles.DynamicProjectileController
: Adds linear impulse on spawn. The projectile is moved by Quantum Physics.KinematicProjectileController
: Projectile moves forward at constant speed.MagneticProjectileController
: Projectile homes in on a specific target upon spawning and updates its rotation towards the target.InstanceProjectileController
: Projectile does not move, instead it spawns a physics query with a long distance and process hits instantly. It still uses the query-process approach which means there is a 1 frame delay before getting hits.
Creating a New Projectile
This is the step-by-step procedure to create a new Projectile in the FPS Template.
- In the Quantum solution, create a new
MyProjectileController
which inherits fromProjectileController
: to define custom behavior; and,FPSProjectileController
: to support basic predefined behavior (damage, layer filtering, knockback, bouncing, hit effects, ...)
- Add serializable fields to the controller (configuration)
- If needed, create a
MyProjectile.qtn
which contains the definition for theMyProjectile
component and other data structures such as roll-backable data - Override the base properties if needed and implement
OnInitialize()
,OnDeinitialize()
,OnUpdate()
,OnProcessHits()
andAddPhysicsQuery()
in the controller - Implement the available controller interfaces (e.g.
IPreProcessComponentDesires
, ...) - Recompile the
quantum.code
solution. - In Unity, create an empty GameObject and the visual components / model as a child object.
- Add the
Entity
,EntityPrototype
,EntityComponentController
andEntityComponentProjectile
scripts to the GameObject. - On the
Entity
component, setTransform Synchronization
toError Correction
. - On the
EntityComponentController
component, selectMyProjectileController
from theProjectileController
drop-down menu and fill out the defined properties. - On the
EntityComponentProjectile
component fill out defined properties. - Add other entity components to define the behavior of the entity (EntityComponentMyProjectile
,
EntityComponentPhysicsCollider3D`, ...). - If
EntityComponentPhysicsCollider3D
is used, set the Projectile's layer and enable theIsTrigger
boolean. - Create a prefab of the entity.
- Execute the asset resource generation via the
Quantum > Generate Asset Resources
menu. - Your projectile is ready to use - i.e. referenced as an
EntityPrototype
.