Projectile Toolkit > Projectile Aerodynamics Version 3.1
Projectile aerodynamics models aerodynamic forces on projectiles without compromising their ability to hit targets.
You can use this feature to simulate curve effect seen in sports such as football, baseball, golf (draw/fade), etc. You can also use it to simulate wind, air drag, or implement creative weapons, like boomerangs.
Templates are "high-level" prefabs that contain all essential components needed for specific use cases, with no-code/low-code development capability.
Template location: .../Blobcreate/Projectile Toolkit/Templates/Aero Projectile Launcher.prefab
Drag and drop the template to the scene.
Add your projectile prefab to the inspector property Projectile Prefab.
To control the template with scripting API, make sure Controlled By Another Script is turned on in the inspector. Otherwise, the template has a default behavior: launching when the left mouse button is pressed.
Tweak the settings in the inspector, and control the template in your scripts by calling AimAt(...)
and Launch()
. Example:
βxusing Blobcreate.ProjectileToolkit.Aerodynamics;
public class LaunchController : MonoBehaviour
{
[SerializeField] AeroProjectileLauncher launcher;
[SerializeField] Transform target;
void Update()
{
launcher.AimAt(target.position);
if (Input.GetMouseButtonDown(0))
{
launcher.Launch();
}
}
}
π‘Tip: We have utilized a quality-of-life feature: From the inspector, you can click on the question icon, it will open your browser and bring you directly here.
Projectile Prefab: Projectile you want to launch. The projectile must have a Rigidbody
component and an AeroRuntime
component attached.
Launch Point: Start position of the projectile.
Height Above Target: Highest point of the trajectory relative to the target point (end point). Internally it uses Projectile.VelocityByHeight(...)
to compute launch velocity. doc link. Advanced users can modify line 98
to change the computation method.
Max Offset: Maximum displacement along local space for a curved trajectory. This shapes the horizontal movement of the trajectory.
The local space is formed by using end - start
vector (ignoring y) as forward vector, and use the middle point between end
and start
as the origin.
The figure below is a top-down view of a scene, it explains the definition and shows two example values of maxOffset vector (you can also set a non-zero value to y axis, it changes the gravity and thus changes the overall movement speed of the projectile).
Use Callback: Whether to invoke the Action you assigned to the Action OnFinished
. See "Scripting API > OnFinished".
Use Prediction: Whether to predict the trajectory of the movement and display it.
Predictor: PEB Trajectory Predictor that is used for trajectory prediction and rendering. The template comes with one preconfigured.
Controlled By Another Script: Make sure this is on so that you can control the template using scripting API.
The API is intuitive and straightforward.
AimAt
and Launch
are the methods you'll use most of the time.
β° AimAt(...)
Aim at the target point.
xxxxxxxxxx
public void AimAt(Vector3 point)
β° Launch()
Launch the Projectile Prefab you defined in the inspector, using the velocity you calculated earlier by calling AimAt(...)
.
xxxxxxxxxx
public void Launch()
UsePrediction
Whether to predict the trajectory of the movement and display it.
xxxxxxxxxx
public bool UsePrediction { get; set; }
OnFinished
Custom callback that is triggered when the projectile reaches its target, providing the projectile's Rigidbody as an arg for use. Note that it is triggered after a pre-calculated time, not by collision.
xxxxxxxxxx
public Action<Rigidbody> OnFinished { get; set; }
Other Properties
The properties in the Inspector (we described earlier in the Inspector Properties section) are all public and you can modify them through scripts.
Note
This section is intended for advanced users, to be used in conjunction with the Low-Level Reference. Most users will only need the high-level template and Scripting API.
Tip
A concrete example script (the main script of the template) can be found here: .../Blobcreate/Projectile Toolkit/Core/Projectile Aerodynamics/AeroProjectileLauncher.cs
The template can handle 99% of scenarios, but sometimes you may want to implement the Projectile Aerodynamics feature into your own class for custom purpose, here's how:
1. Create a solver
In Start()
or Awake()
, create a new AeroSolver
instance.
xxxxxxxxxx
aeroSolver = new AeroSolver();
2. Solve
Calculate all the data needed by calling Solve(...)
. You can add the code below directly into your logic or encapsulate it to a method.
xxxxxxxxxx
var offY = new Vector3(0, maxOffset.y, 0);
// You can use any velocity method in the Projectile class.
var vRaw = Projectile.VelocityByHeight(startPoint, targetPoint + offY, 10f);
var vReal = aeroSolver.Solve(startPoint, targetPoint, maxOffset, vRaw);
3. Run
This is the final step, we launch the projectile, and then set up execution of projectile aerodynamics through AeroRuntime
component. And now your projectile moves in the air in curve!
xxxxxxxxxx
var myProjectile = Instantiate(projectilePrefab, startPoint, Quaternion.identity);
myProjectile.AddForce(vReal + Projectile.VelocityCompensation, ForceMode.VelocityChange);
myProjectile.TryGetComponent<AeroRuntime>(out var rt);
rt ??= myProjectile.gameObject.AddComponent<AeroRuntime>();
rt.Configure(aeroSolver, myProjectile);
rt.Run();
Options:
You can add any custom methods to the Action OnFinished
, it will be called when the projectile reaches target.
xxxxxxxxxx
aeroSolver.OnFinished = (ball) =>
{
ball.angularVelocity = Vector3.zero;
ball.velocity = new Vector3(0, 10, 0);
};
If you also want to predict the trajectory, in Start()
, set up a PEBTrajectoryPredictor
instance (here we call it predictor
), the instance will be used later:
xxxxxxxxxx
var b = Instantiate(ballPrefab, startPoint, Quaternion.identity);
predictor.Simulatee = b;
predictor.AeroSolverInstance = aeroSolver;
b.gameObject.SetActive(false);
Call the predictor
when you want to predict the trajectory.
xxxxxxxxxx
predictor.LaunchVelocity = vReal + Projectile.VelocityCompensation;
predictor.SimulateAndRender();
Note
This section is intended for advanced users as a low-level scripting reference, to be used in conjunction with the Low-Level Implementation Guide. Most users will only need the high-level template and Scripting API.
Projectile Aerodynamics' code is in namespace Blobcreate.ProjectileToolkit.Aerodynamics
.
The low-level code consists of 2 classes:
AeroSolver
: Pure C# class that do the computation.
AeroRuntime
: Unity component that needs to be attached to a projectile to use.
Below, the items marked with a starβ° are the most important.
xxxxxxxxxx
public Vector3 SolvedVelocity { get; }
The returned value of Solve(...)
β the computed launch velocity that takes projectile aerodynamics into account. Only valid after Solve(...)
has been called.
xxxxxxxxxx
public Vector3 Acceleration { get; }
Computed continuous acceleration that is used to conduct projectile aerodynamics.
xxxxxxxxxx
public Vector3 WorldOffset { get; }
World space version of maxOffset
(one parameter you passed to method Solve(...)
). It is used internally to get offset target point (= target + OffsetVector).
xxxxxxxxxx
public float TimeOfFlight { get; }
Time needed for projectile to reach endpoint. The acceleration (force) is applied during this period of time.
xxxxxxxxxx
public Action<Rigidbody> OnFinished { get; set; }
Custom callback that is triggered when the projectile reaches its target, providing the projectile's Rigidbody as an arg for use. Note that it is triggered after a pre-calculated time, not by collision.
Computes the data required for projectile aerodynamics.
xxxxxxxxxx
public Vector3 Solve(Vector3 start, Vector3 end, Vector3 maxOffset, Vector3 v)
start
: Launch point.
end
: Target point.
maxOffset
: Maximum displacement along local space for a curved trajectory. The local space is formed by using "end - start" vector (ignoring y) as forward vector.
v
: The original launch velocity that makes the projectile move from start point to end point without taking aerodynamics into account.
returns
: The modified launch velocity that takes aerodynamics into account.
Executes one physics update of projectile aerodynamics.
This is used internally in PEBTrajectoryPredictor
class for projectile aerodynamics prediction, but for the execution applied to real projectile, we recommend using AeroRuntime
class.
xxxxxxxxxx
public bool ApplyAcceleration(Rigidbody rBody, ref float timer)
rBody
: The Rigidbody of the object to which the acceleration is applied.
timer
: This is used as a runtime context, it records how much time has been passed since the projectile launch.
returns
: Whether or not the acceleration is applied. False means the procedure is finished.
xxxxxxxxxx
public float TimeOfFlight { get; }
Time needed for projectile to reach endpoint. The acceleration (force) is applied during this period of time.
xxxxxxxxxx
public float Timer { get; }
How much time has been passed since the projectile launched.
Configure the runtime. A valid AeroSolver instance should have been called Solve(...)
beforehand.
xxxxxxxxxx
public void Configure(AeroSolver solver, Rigidbody rBody)
solver
: AeroSolver instance to get data from.
rBody
: Rigidbody you want to control.
Starts the internal timer and logic (applying Acceleration, etc.).
xxxxxxxxxx
public void Run()
Stops applying Acceleration, and resets the internal timer. Useful for replay, handling collisions, etc.
xxxxxxxxxx
public void Stop()