Numerical Integration: Making Calculus Run in Real-Time
Game engines can’t compute perfect Integrals—they need to approximate continuous math with discrete timesteps. This is numerical integration, and it’s running every physics tick in your game.
The Problem
Calculus assumes continuous, infinite precision. Game engines have:
- Fixed timesteps (60 FPS = 0.016s intervals)
- Limited floating-point precision
- Real-time performance constraints
So we approximate.
Euler Integration: The Simplest Method
void updatePhysics(Particle& p, float deltaTime) {
// Approximate: velocity += acceleration * dt
p.velocity += p.acceleration * deltaTime;
// Approximate: position += velocity * dt
p.position += p.velocity * deltaTime;
}Why It Works (and When It Doesn’t)
Euler integration approximates the derivative using finite differences:
Works well when: timestep is small, forces are gentle Breaks down when: timestep is large, forces are strong
Seeing the Instability
// Large timestep = unstable physics
void badPhysics() {
float dt = 0.1f; // 10 FPS - too large!
updatePhysics(particle, dt);
// Objects will gain energy and explode
}
// Small timestep = stable physics
void goodPhysics() {
float dt = 0.016f; // 60 FPS
updatePhysics(particle, dt);
// Smooth, realistic motion
}Better Methods
Verlet Integration
More stable for physics simulation:
void verletUpdate(Particle& p, float dt) {
Vector3 newPos = 2.0f * p.position - p.oldPosition + p.acceleration * dt * dt;
p.oldPosition = p.position;
p.position = newPos;
}Runge-Kutta (RK4)
Higher accuracy, more expensive:
// Evaluates the derivative at multiple points for better approximation
Vector3 rk4Step(Vector3 pos, Vector3 vel, float dt) {
// Implementation details...
// 4x more function evaluations than Euler
}Real Engine Examples
Unity: Uses PhysX (proprietary), likely Verlet or semi-implicit Euler Unreal: Uses Chaos Physics, multiple integration methods Custom engines: Often start with Euler, upgrade to Verlet for stability
Timestep Trade-offs
You can observe this in Unity:
- Edit → Project Settings → Time
- Change Fixed Timestep from 0.02 to 0.1
- Watch physics become less smooth/stable
Smaller timestep = better accuracy, worse performance Larger timestep = better performance, worse accuracy/stability
Numerical Approximation in Action
Here’s how a custom OpenGL engine might approximate a derivative (which is defined using limits):
// The mathematical definition uses a limit:
// f'(x) = lim(h→0) [f(x+h) - f(x)] / h
// In code, we approximate with a small h:
float approximateDerivative(float x, float h = 0.001f) {
return (f(x + h) - f(x)) / h;
}The smaller h gets, the closer we are to the true limit—and the more accurate our derivative becomes.e computing numerically