Movement with momentum
The controller follows the Quake and Titanfall school: instead of setting the velocity every frame, it accelerates toward where you want to go and only friction takes speed away. Speed is kept across jumps, so players can build it with air-strafing, wall-runs and slide-hops.
A small state machine (grounded, airborne, wall-running, sliding, mantling) owns the rigidbody, and the camera leans and kicks its field of view from the controller's signals. The core math is pure functions, so it can be unit-tested outside of play mode.
// Only adds speed along the wish direction, and only up to
// wishSpeed along that axis. Total speed is never clamped,
// which is what makes air-strafing build speed.
public static Vector3 Accelerate(Vector3 vel, Vector3 wishDir,
float wishSpeed, float accel, float dt)
{
if (wishDir == Vector3.zero) return vel;
float current = Vector3.Dot(vel, wishDir);
float add = wishSpeed - current;
if (add <= 0f) return vel;
float accelSpeed = Mathf.Min(accel * wishSpeed * dt, add);
return vel + wishDir * accelSpeed;
}
Enemies built from blocks
In a jam, the designers need new enemies faster than a programmer can write them. So there is exactly one enemy component. It handles targeting and aggro, and everything else is picked from dropdowns in the inspector: one movement (stationary, ground chase, hover chase) and any number of abilities (shoot, explode), with shot patterns (single, burst, spread, radial, wave, sequence) as swappable assets.
A flying kamikaze and a turret that fires spirals are the same component with different blocks, built without writing a line of code.
public sealed class EnemyBrain : MonoBehaviour
{
public FloatReference AggroRange = new(14f);
[SerializeReference] // pick one from a dropdown
public EnemyMovement Movement = new GroundChaseMovement();
[SerializeReference] // stack as many as you like
public List<EnemyAbility> Abilities = new();
}
[Serializable]
public abstract class EnemyMovement
{
public abstract void Tick(in EnemyContext ctx);
}
Made with Canozalez, Chaos-1001 (art) and Pierre-Henri Barralis (music & audio).