Physics
Altruist includes a built-in 3D physics engine (BEPU-based) for collision detection, rigid body simulation, and character controllers. However, physics is entirely optional — many game types don't need real-time collision detection and perform better without it.
When to Use Physics
| Game Type | Physics? | Why |
|---|---|---|
| FPS / action games | Yes | Real-time collision, projectile tracing, character controllers |
| Racing / vehicle games | Yes | Rigid body dynamics, surface collision |
| Top-down RPG with grid movement | No | Distance-based combat, grid walkability checks |
| MMO with large open worlds | Partial | Physics for players (character controller), lightweight spawns for NPCs/monsters |
| Turn-based strategy | No | No real-time movement or collision needed |
Note:
Disabling physics for entities that don't need it is a major performance optimization. A game with 10,000 entities using lightweight spawns will tick significantly faster than one with 10,000 physics bodies.
Physics-Based vs Heuristic-Based Games
Physics-Based
Entities have rigid bodies, colliders, and participate in the physics simulation. The engine resolves collisions, applies forces, and syncs transforms every tick.
// Spawn with full physics — body + colliders created
var profile = new HumanoidCapsuleBodyProfile(0.28f, 0.62f, 0f, isKinematic: true);
entity.BodyDescriptor = profile.CreateBody(entity.Transform);
entity.ColliderDescriptors = profile.CreateColliders(entity.Transform);
await world.SpawnDynamicObject(entity);
Use this when you need:
- Real-time collision detection and response
- Character controllers with gravity, slopes, and sweep collision
- Projectile hit detection
- Trigger volumes (enter/exit zones via physics)
Heuristic-Based (No Physics)
Entities are tracked spatially for visibility and queries, but have no physics body. Combat uses distance calculations, movement uses walkability grids, and collision is resolved through game logic rather than physics simulation.
// Lightweight spawn — spatial tracking only, no physics body
world.SpawnLightweight(entity);
Use this when you need:
- Distance-based combat (attack range checks instead of collider overlap)
- Grid-based or tile-based movement
- Thousands of NPCs/monsters that only need position tracking
- Server-validated movement using walkability maps
Note:
SpawnLightweight adds the entity to world partitions for spatial queries and visibility tracking — it works with FindAllObjects, GetNearbyObjectsInRoom, and the visibility tracker. The only difference is: no physics body, no colliders, no collision events.
Mixing Both Approaches
A common pattern is using physics for players and lightweight spawns for NPCs:
// Player — full physics with character controller
var profile = new HumanoidCapsuleBodyProfile(0.28f, 0.62f, 0f, isKinematic: true);
player.BodyDescriptor = profile.CreateBody(player.Transform);
player.ColliderDescriptors = profile.CreateColliders(player.Transform);
await world.SpawnDynamicObject(player);
// Monster — lightweight, uses distance checks for combat
world.SpawnLightweight(monster);
// Static world geometry — loaded from JSON with colliders
// Players collide with walls/terrain, monsters don't (they use walkability grid)
Note:
Lightweight entities have no physics colliders, but [CollisionHandler] still works for them — the combat system uses distance-based dispatch when physics is off. See Collision Handling.
Spawn Methods Reference
| Method | Physics Body | Colliders | Visibility | Spatial Queries | Use Case |
|---|---|---|---|---|---|
SpawnDynamicObject | Yes (dynamic) | Yes | Yes | Yes | Players, vehicles, projectiles |
SpawnStaticObject | Yes (static) | Yes | Yes | Yes | Walls, terrain, buildings |
SpawnLightweight | No | No | Yes | Yes | NPCs, monsters, collectibles |
Distance-Based Combat Example
For games that don't use physics collision, validate combat with distance checks:
[Gate("attack")]
public async Task OnAttack(AttackPacket packet, string clientId)
{
var attacker = GetPlayerEntity(clientId);
var target = world.FindObject(packet.TargetInstanceId);
if (target == null) return;
// Distance check instead of physics collision
float dx = target.Transform.Position.X - attacker.Transform.Position.X;
float dy = target.Transform.Position.Y - attacker.Transform.Position.Y;
float distSq = dx * dx + dy * dy;
float attackRange = 200f; // Game units
if (distSq > attackRange * attackRange)
return; // Too far
// Apply damage
if (target is MonsterEntity monster)
{
monster.Hp -= CalculateDamage(attacker);
if (monster.Hp <= 0)
monster.Expired = true;
}
}
Note:
This approach is used by many classic MMOs — combat is validated by server-side distance checks rather than physics overlap. It scales to thousands of entities because there's no per-frame collision detection overhead.
Physics-Independent Features
Both the character controller and collision system work without physics enabled:
| Feature | Physics ON | Physics OFF |
|---|---|---|
| Character Controller | BEPU capsule casts | Heightmap + collider math |
| Collision Handlers | BEPU body overlap | Distance-based dispatcher |
| Your code | Identical | Identical |
The framework auto-selects the right backend based on altruist:game:physics:enabled. You never need to change your game code.
What's Under Physics
- Movement & Character Controller — Kinematic character controller, gravity, capsule sweep, abilities (works with and without physics)
- Collision Handling —
[CollisionHandler]and[CollisionEvent]with Enter/Stay/Exit/Hit lifecycle (works with and without physics)