Trick Shot

TrickShot and TrickShot2D have the same basic setup and functionality 1 for 3D space and 1 for 2D space: TrickShot
lets designers compute and visualize a multi‐bounce ballistic trajectory at runtime (storing it in prediction
) and then spawn a BallisticPathFollow
prefab along that exact path via Shoot()
. It’s ideal for “grenade launcher”–style weapons or any projectile that should follow a precomputed arc with optional bounces.
Public Fields
Speed
float speed
Initial launch speed (units/sec). Combined withtransform.forward
to form the launch velocity.
Constant Acceleration
Vector3 constantAcceleration
Gravity or custom acceleration applied throughout flight. Defaults to(0, –9.81f, 0)
.
Radius
float radius
Sphere‐cast radius used when predicting collisions. Set this to roughly match your projectile’s size.
Template
BallisticPathFollow template
A reference to a prefab (or scene object) that hasBallisticPathFollow
on it.At
Shoot()
, this prefab is instantiated, and itsprojectile
andpath
fields are filled using the computedprediction
.
Resolution
float resolution
(minimum0.01
) Sampling increment for each prediction segment. Smaller values → finer trajectory at higher CPU cost.
Distance
float distance
Maximum trace length per segment (or total, seedistanceIsTotalLength
).
Collision Layers
LayerMask collisionLayers
Layers used for collision detection when predicting. Only colliders on these layers will register impacts.
Trigger Interaction
QueryTriggerInteraction triggerInteraction
Whether to include triggers in collision checks (UseGlobal
,Ignore
, orCollide
).
Bounces
int bounces
Number of allowed bounces after the first impact. Set to 0 for a single arc, >0 to simulate up to N bounces.
Bounce Damping
float bounceDamping
([0, 1]
) Fraction of velocity lost on each bounce. A value of 0.5 means the reflected velocity is halved after impact.
Distance Is Total Length
bool distanceIsTotalLength
false
(default) – Each segment’sPredict()
usesdistance
as its own distance limit.true
– After each bounce, subtract that segment’sflightDistance
fromdistance
, sodistance
becomes the maximum total arc length across all segments.
Prediciton
List<BallisticPath> prediction
The computed list ofBallisticPath
segments. After callingPredict()
, this list holds one entry per segment (first arc plus each bounce arc). Designers can inspect or draw these paths before spawning.
Public Methods
Predict
void Predict()
Compute and store a full, multi‐bounce trajectory in prediction
.
Workflow
Creates a local
BallisticsData
with:velocity = transform.forward * speed
radius
as assigned.
Clears any previous contents of
prediction
.If
bounces == 0
, simply does oneproj.Predict(...)
from the current position:csharpCopyEditprediction.Add( projectileSettings.Predict( selfTransform.position, null, resolution, distance, collisionLayers, triggerInteraction, constantAcceleration ) );
If
bounces > 0
, runs a loop up tobounces
times:Calls
proj.Predict(...)
from the current launch point (pos
) with the currentproj.velocity
and either:distance
(ifdistanceIsTotalLength == false
), orthe remaining distance (if
distanceIsTotalLength == true
).
Adds the returned
BallisticPath
toprediction
.If there’s no impact, breaks out (no further bounces).
Otherwise, reflects the last‐step velocity against the impact normal and multiplies by
(1 – bounceDamping)
, then uses that as the newproj.velocity
for the next segment.If
distanceIsTotalLength == true
, subtracts the just‐used segment’sflightDistance
from remaining distance.
Designer Usage
Call
Predict()
whenever you want to update the visible trajectory (e.g., on aim adjustment or when parameters change).After
Predict()
, inspectprediction
(for example, draw gizmos from eachBallisticPath.steps[i].position
) or feed it directly into aLineRenderer
/debug draw.
Shoot
void Shoot()
Instantiate the BallisticPathFollow
prefab and assign the precomputed trajectory so the spawned object moves exactly along it.
Workflow
Instantiates a copy of
template.gameObject
attransform.position
/transform.rotation
.Retrieves its
BallisticPathFollow
component (comp
).Creates a new
BallisticsData
insidecomp
with:velocity = transform.forward * speed
radius
as configured.
Assigns
comp.path
to a newList<BallisticPath>(prediction)
(makes a copy).If
prediction
is empty, logs a warning: “No prediction path available, projectile spawned but may not behave as expected.”
Designer Usage
After calling
Predict()
, simply callShoot()
. The newly spawned object will begin its path in its nextLateUpdate
call.You do not need to manually set
comp.projectile
orcomp.path
—Shoot()
handles it.
Typical Designer Workflow
Scene Setup
Place a GameObject in the scene (e.g., a “Launcher”) and attach:
TrickShot
Any aiming/rotation scripts you want (e.g., rotating to face a target).
Assign a
BallisticPathFollow
prefab astemplate
onTrickShot
. Ensure that prefab has aBallisticPathFollow
component and is configured (layer masks, events, etc.).
Configure Parameters in Inspector
speed
: E.g.,25f
for a medium‐range launch.constantAcceleration
: Leave at(0, –9.81f, 0)
for earth‐like gravity.radius
: E.g.,0.1f
for a small projectile.resolution
: E.g.,0.02f
for a smooth curve.distance
: E.g.,50f
to trace up to 50 units.collisionLayers
: Tick “Environment” or “Obstacles.”bounces
: E.g.,1
if you want exactly one bounce.bounceDamping
: E.g.,0.3f
to lose 30% speed on each bounce.distanceIsTotalLength
: Enable if you want the sum of all segments capped atdistance
(otherwise each segment is capped individually).
Call
Predict()
In a custom aiming script or UI (e.g., when the player adjusts aim), call:
csharpCopyEditGetComponent<TrickShot>().Predict();
Use
prediction
to draw a debug arc or aLineRenderer
so the player sees the full flight + bounce.
Call
Shoot()
When the player fires, simply call:
csharpCopyEditGetComponent<TrickShot>().Shoot();
A new object (from your
BallisticPathFollow
template) spawns attransform.position
and immediately begins moving along the precomputedpath
.
Designer Tips & Gotchas
Ensure
prediction
Is Up to Date Always callPredict()
right beforeShoot()
(or enablePredict()
in an “OnAimChanged” event). If you forget,Shoot()
will warn thatprediction
is empty, and the projectile might not travel correctly.Matching Radius & Collider Use the same
radius
in bothTrickShot
and theBallisticPathFollow
’sprojectile
so that collisions align perfectly during prediction and actual flight.Distance Logic
If
distanceIsTotalLength == false
, each segment can travel up todistance
before ending—even if the first bounce happened early.If
true
, the sum of all segments’flightDistance
cannot exceeddistance
, ensuring a hard cap on total arc length.
Multiple Bounces Set
bounces
to the maximum number of bounces you expect. If the path never actually collides before reachingdistance
, the loop breaks early.Performance Consideration A small
resolution
(e.g.,0.005f
) plus many bounces can generate hundreds of samples—use a slightly larger value (e.g.,0.02f
–0.05f
) unless you need extreme precision.Custom Gravity If you want no gravity, set
constantAcceleration = Vector3.zero
. For unusual physics fields (e.g., a planet with weak gravity), adjust accordingly.
Last updated