Uniform grid
Divide space into fixed-size cells; each cell lists the objects in it.
Two questions dominate game simulation at scale: what is near me? (spatial queries) and how do I get there? (pathfinding). Both become impossibly slow if answered naively — checking every object against every other is O(n²). This page covers the acceleration structures that make spatial queries cheap and the pathfinding algorithms that move agents through a world.
This expands on the Spatial Partition pattern with concrete structures and trade-offs.
A spatial query — “what’s within radius r?”, “what does this ray hit?”, “which objects overlap?” — naively scans every object: O(n) per query, O(n²) for all-pairs. Acceleration structures organize objects by position so a query only visits nearby candidates, turning O(n) into roughly O(log n) or O(1) per query.
The universal trade-off: build/update cost vs query speed. Static geometry can afford an expensive structure built once; objects that move every frame need cheap updates or a structure rebuilt each frame.
Uniform grid
Divide space into fixed-size cells; each cell lists the objects in it.
Quadtree / Octree
Recursively split space into 4 (2D) or 8 (3D) until each node holds few objects.
BVH
Tree of nested bounding volumes wrapping the objects themselves.
R-tree
Balanced tree of bounding rectangles; database-style, disk-friendly.
k-d tree
Binary tree splitting on one axis at a time; great for nearest-neighbor.
BSP tree
Recursive splits by arbitrary planes; exact front-to-back ordering.
Space is divided into equal cells; each object is bucketed into the cell(s) it overlaps. A range query visits only the cells the query touches.
Start with one node covering the whole space; when a node holds too many objects, subdivide it into 4 (quadtree, 2D) or 8 (octree, 3D) children and redistribute. Recursion adapts depth to local density.
A tree where each node is a bounding volume (usually an AABB) enclosing its children, and leaves wrap actual objects. Unlike quadtrees (which partition space), a BVH partitions objects — volumes may overlap, but each object lives in exactly one leaf.
A height-balanced tree of minimum bounding rectangles, related to the B-tree. Designed for databases and on-disk spatial indexes (GIS, PostGIS), it keeps the tree balanced under insertion/deletion.
A binary tree that splits on one axis per level (x, then y, then z, cycling). Excellent for nearest-neighbor and k-nearest queries.
Binary Space Partitioning recursively splits space by arbitrary planes (not axis-aligned). It yields an exact ordering of geometry from any viewpoint — the classic Doom/Quake visibility and sorting structure.
Once you can ask “what’s near me?”, agents still need “how do I get there?”
A* searches a graph (grid cells, waypoints, nav-mesh polygons) from start to goal, guided by a heuristic that estimates remaining distance. It’s optimal and complete with an admissible heuristic, and the workhorse of single-agent pathfinding.
Instead of pathing each agent individually, compute one field over the whole map that, at every cell, stores the direction toward the goal. Every agent just samples its cell and follows the arrow. The cost is amortized: one Dijkstra-style pass from the goal builds a cost (integration) field, then a flow field of directions — then N agents path for free.
A nav mesh represents walkable space as convex polygons instead of a grid. Pathfinding runs over the polygon graph (fewer nodes than a fine grid), then a string-pulling/funnel pass smooths the polygon path into a direct route.
Partition the map into clusters, precompute paths between cluster portals, and search the coarse graph first, refining only within clusters along the route. Trades optimality for huge speedups on large maps (HPA*).