Collision

Collision is a Serious Business



A Game of Two Halves


There are two main aspects to the problem of handling collisions in a simulation...

  1. Detecting the collision
  2. Handling the consequences

The first of these is, essentially, a geometry problem.
The second is, to some extent, a physics problem.

Detection


At its simplest, detecting a collision within some group of objects requires us to calculate whether the volumes of any
of those objects overlap in (virtual) space.

(More correctly, we might actually have to think about
the extruded shapes of those volumes over time.)

Anyway, if we represent the physical "collision volume" of
our objects in terms of geometric primitives such as triangles, circles (spheres), rectangles (cuboids), this becomes
a solvable maths problem.

Handling


Handling a collision is more of a physics problem, potentially involving the calculation of collision-resolution impulses and so on --- or, at the very least, the "brute-force physics" of simply moving things out of the way of each other.

The details very much depend on how sophisticated a "physics system" your simulation has.

Up till now, we've just been doing things like negating the velocity of one of the moving objects, to implement a simple form of point-based solid body physics.

Context


But, above both of these aspects is the broader
question of where/when/how to process
collisions within the mainloop...

A Naive Approach


One way of addressing the whole problem is to
allow the mainloop to proceed essentially as normal,
updating the positions of each entity in turn.

Then, after all of that has been done, you make another sweep over the objects to detect and resolve any resulting collisions.

In a sense, this is quite an "honest" approach, and is consistent with the illusion that our entities are, in fact, moving simultaneously (rather than in any particular order).

Simultaneous


This strategy provides a nice, clean, separation of concerns
and seems quite appealing on those grounds.


Detecting the collisions is no more difficult, and no less efficient, with this approach than it would be in any other.

And, in fact, during its early development, the original
"Grand Theft Auto" (1997) worked this way.

The Problem


The problem is Collision Resolution (aka Collision Response).

If all of the objects have already moved to new, provisional, positions before you attempt to resolve the collisions,
it becomes very difficult (in some cases) to figure out
what to actually do when a collision is detected...

Collision Response


The main job of a collision response is to prevent an interpenetration from being seen --- because we expect separate solid bodies not to overlap each other in space,
rather by definition.

Ultimately, you do this by moving one or more of the
colliding objects to some unoccupied region of space.

But where?

Collision Cascades


A very naive approach might just shift one (or all) of the intersecting objects apart by some sufficient distance to prevent them from overlapping...

...but what if that movement causes another collision,
whether with a static obstruction (like a wall) or with
some other dynamic entity?

In the former case, you have a big problem, because the wall certainly cannot move away in turn! Even in the latter case,
the possibility of crazy knock-on effects is very real.

Revert

A more sensible approach is to revert a
colliding object to its previous position.

But there is no guarantee that the previous position will
still be unoccupied, because some other dynamic object
might have moved into it!

In the overall scheme of things, such occurrences are relatively rare --- but they can happen and, in practice, they do happen... and when they do they are an enormous pain.

This is the trap that GTA fell into.

GTA Hell


It was possible to create a situation where the player
could put a bunch of vehicles in a physical loop
(nose-to-tail, in a loose circle as seen from above).

If, in this configuration, the vehicles all moved forward, and any one of them triggered a collision, the required "rollback" was essentially impossible to perform, and would result in
an infinite loop!

(The full details are a bit more complicated,
but that was the gist of it).

Purgatory?


The central problem was that, in the general case,
you couldn't always guarantee the existence of
a suitable "safe place" for an entity to return to.

However, there exists a very simple solution to this which,
as far as I know, is how most games have worked since (especially the "sandbox" ones)...

Non-Simultaneous


The easiest way to guarantee the existence of a suitable
"safe place" for an entity to return to, in the event
of a collision, is to use its previous location.

...If we can guarantee that the previous location
will not be occupied by anything else.

The way to do that, is to move and collision-resolve each
entity in turn i.e. one at a time, as part of their
individual update routines.

Wrong! (?)


Of course, strictly-speaking, this is "wrong"
insofar as it contradicts the idea that our entities
should be acting simultaneously.

In particular, the collision behaviour of two objects will
now depend on the order in which they are updated.

e.g. consider a race between equals...

The apparent winner will be the one who gets updated first,
which is technically arbitrary and "unfair".

..But..


...on the other hand, in practice "we get away with it",
and it makes collision response much easier: if all else fails,
we can always move an object back to its previous position, and be safe in the knowledge that this will work...

Right?

...erm, unless the environment itself is dynamic e.g. with moving platforms etc. (Such things are usually handled "specially", and I won't go into the details of those here).

Detection in Detail


As discussed at the start, collision detection is essentially a geometry problem: it's a matter of discovering the dynamic intersections within groups of geometric primitives
e.g. points, lines, circles, rectangles, spheres,
triangles, cuboids, cylinders and so on.

Each collidable entity is given an associated collision representation (sometimes called a "collision model" or "collision volume") which is used by the collision system.


...Approximately


These representations are almost always approximate,
because the handling of perfectly exact representations
is generally too slow and complex in real-time... and because the approximations are usually accurate
enough for this to be a "fair trade-off".

In simple cases, an entity might be adequately described by
a single primitive e.g. a box. However, more generally, an object's collision representation might include multiple primitives (potentially intersecting with each other!).

For Example


Bounding Volumes


As the number of primitives in a model increases, however, the time taken to compute the collisions increases too,
which can lead to performance problems.

To address this an entity will typically have, in addition
to any detailed collision model, a primitive outer model
which is used to provide a very simple shell to support
an "early rejection" optimisation.

Such outer models are often referred to as "bounding" models, typically "bounding boxes" or "bounding spheres".

For Example



2D Collision Detection


In 2D games, the collision primitives tend to be
things like rectangles and, quite often, circles.

BTW: Occasionally, a 2D game will also perform
"pixel perfect" collision using the actual sprite-data,
but this is less common (and uses somewhat different techniques, which I won't cover here).

Circles


Circles are a popular choice for collision primitives because...

 Well... they are easy to write collision-detection routines for!

This might seem like laziness (and, in a sense, it is), but an "easy" solution also tends to be a fast/concise/elegant one,
and there is much to be said for that.


Code


Two circles are in collision if the distance between
their centre points is less than the sum of their radii.
var distance = distanceBetween( c1.centre, c2.centre );
var limit = c1.radius + c2.radius;
if (distance < limit) { /* it's a collision! */ }
else { /* no collision */ }

Computing the distance between two points is easy, although it does involve taking a square-root which, historically, was a slow operation. There's a standard optimisation/work-around for this (although it's probably a less significant saving today than it used to be, but it's still widely used in practice)...

Squaring the Circle?


If we square both sides of the equation,
the inequality will still hold:
var distanceSq = distanceSqBetween( c1.centre, c2.centre );
var limitSq = square(c1.radius + c2.radius);
if (distanceSq < limitSq) { /* it's a collision! */ }
else { /* no collision */ }

That is, we save ourselves the square-root operation,
at the cost of performing an extra squaring operation on
the "limit" value. That's generally going to be a "win" overall.

Rectangles


In 2D games, we are generally not too concerned with rotations (or, if we are, we use circles instead!), so we tend to treat rectangles in an "axis-aligned" form i.e. with perfectly horizontal and vertical edges, running parallel to
the co-ordinate axes.

I would call these "axis-aligned rectangles", but you'll often hear the term "axis-aligned bounding-box" (commonly abbreviated to AABB) used for the same purpose,
and for its 3D equivalent.

Code?


Anyway, axis-aligned 2D rectangle collision is a little bit
more complex than circle collision, but not terribly so...

Let's start by thinking about it, and see if we can come up
with an "algorithm" to solve this problem...

And, here's a nice implementation:

Mixing It Up


The collision between a circle and a rectangle is
a bit trickier, but it can certainly be done
(or, where acceptable, approximated).

Indeed, we've been doing variants of that since PONG!

BTW: In some situations, contrary to what I claimed earlier, we might actually want to have rotatable rectangle collision...

...I won't go into the details of that here,
but these are called "oriented bounding boxes" (OBBs)

Intermission

(This is roughly the half-way point)

Sufficient?


So, in principle, it might be enough to define box and/or
circle models for each of your entities and then use
those to detect any collisions. Right?

...well, not necessarily.

Thus far, we've just been thinking about "static" overlaps i.e. taking the desired position of an entity and checking it for collision against some other bunch of primitives.

Technically speaking, that isn't always sufficient...

Dynamic Collision


Unfortunately, if an object is moving fast enough it can apparently "warp" or "tunnel" through another object
without our "static" collision detection spotting it!

This is generally known as the "Bullet Through Paper" problem, for hopefully obvious reasons...

Bullet Through Paper


The problem is that, in a dynamic system, we should really
be testing against the "swept volume (or area) over time"
of our entities.

Geometrically, these swept forms can get quite complicated, even for originally simple primitives. The linear sweep of a circle is a kind of mutant circle/rectangle hybrid, which is sometimes referred to as a "sausage" --- others call it a "capsule" or, generalising slightly, a "lozenge"

Sweeping Generalisations


The sweep of a rectangle is similar, until you start thinking about rotations, at which point it becomes utterly evil.

In some cases, these "swept volumes" can be used in a
collision detector but, in general, they are quite impractical
(especially when arbitrary rotations are involved).

As ever, the solution in the gaming world is to take some short-cuts and make some approximations...

Multi-Step Motion


Rather than computing a true swept volume, it is often sufficient to simply test against multiple instances of the original primitives, stepped over time in a way that compromises between reducing the "gaps" while
keeping the number of steps reasonably modest.

The number of "steps" can be determined either by directly geometrical considerations (e.g. don't step by more than your own radius), or by temporal ones (e.g. don't step by more than 0.01 seconds, regardless of the overall "update rate").

Limits


Sometimes, objects are simply given maximum velocities which relate to their size and allow us to control the number
of steps that way (often arranging things so that the number
of steps per update can be "one").

In practice, for typical combinations of object size, velocity
and update-rate, the problem is (as with so many things in
this field!) essentially "ignored", albeit knowingly (and
with some checks-and-balances to keep things sane).

Bullets Again


However, the motivating example of a bullet is often handled specially: bullets are an important feature in many games but they are unusually small and fast-moving... in a way that breaks many of the typical in-game assumptions.

Luckily, the solution here is quite easy --- the swept volume
of a bullet is, to a very good approximation, simply a line!

The intersection of a line against most other primitives is easy to compute and, in addition to bullet collision, these facilities are used to help with visibility detection & object "picking".

3D Collision Detection


In 3D, the primitives are cuboids, spheres, convex hulls
of various kinds and, sometimes, cylinders and triangles.

Cuboids and spheres are handled as natural extensions
of their 2D equivalents (rectangles and circles).

And, although few objects in a typical game will seem obviously "spherical", the technique of using multiple
spheres to approximate an arbitrary volume often
works well, and can be very efficient (and simple).

Some Examples


We used this extensively in "Wild Metal Country", where
almost all dynamic objects (including all of the "tanks")
were represented as groups of spheres, packaged
together inside a single overall bounding sphere.

In fact, the collision in "EVE Online" is also
 to this day, entirely sphere-based.

Sshhhh!!! Don't tell anyone.

It's embarrassing.

Triangles


Despite being the fundamental primitive of almost all 3D graphics, the direct use of triangles in collision detection
isn't as common as you might think, because that level
of fidelity tends to be overkill for most things (and a bit
of a hassle complexity and efficiency-wise), but they are sometimes used to represent the static environment,
especially terrains.

Convex Hulls


Convex hulls are often useful in 3D, and have numerous collision-friendly properties. The key fact about a convex hull (and this includes simpler things such as plain cuboids), is
that a point is only "inside" the hull if (and only if) it is on
the "inner" side of all of the hull's bounding planes (i.e.
the planes which extend through the faces of its surface).

This turns out to be very quick and simple to calculate...
so much so, in fact, that non-convex volumes in a game are usually converted into groups of convex volumes instead
(this conversion is always possible).

Representing Humanoids


An important special case is humanoid characters.
Several approaches are possible here and, indeed, a set of spheres would actually be OK for many things. However,
in practice, it is common to represent characters as upright cylinders which, if you think about it, are just a simple extension (well, extrusion) of a circle into 3D space.

The fact that the cylinders remain vertically upright is
an important simplification, which is generally applied, regardless of the angle of slope that a character may be standing on. (The Unreal Engine works this way).

Hierarchies


3D models are often represented hierarchically, with movable joints between the parts. This adds some complexity to the collision detection system, because the collision model itself may have to change when the entity's joints are modified.

When the collision primitives correspond directly to the segments of the hierarchy, this works fairly "naturally".

But, when a collision primitive covers multiple segments of the hierarchy (as the overall bounding volume surely does), there can be problems with maintaining its correctness.

Problems of Parenthood


It's possible for a "parent" volume to be recalculated so that it always fits the current position of the child nodes, but this is potentially expensive and, in my experience, is not often done.

Instead, the "solution" is to ensure that the bounding volumes are generous enough to contain all of their child volumes
in any legitimate pose.

3D Environment Collision


Collision with the overall game environment (e.g. the terrain or corridors or buildings or whatever) is another important special case in many games...

For one thing, collisions involving non-environment entities are, in the broad scheme of things, "rare" (perhaps only occurring every couple of seconds => on less than 1% of all computed updates). But environment collisions are usually happening all the time, for almost every dynamic object.

Performance Matters...


Environment collision can be very performance-sensitive --- especially in vehicle-based games where, depending on how you handle it, each wheel is in a state of essentially constant (and complex) collision with the environment.

Furthermore, the essential geometry of an environment tends to be a bit different from that of a non-environment entity. Environments are much larger and usually have much more complicated collision geometry than other entities, and are more likely to be represented as "triangles" than as the
simple spheres, boxes and cylinders used elsewhere.

Difficult


These factors make environment collision generally
harder to implement, more computationally expensive,
and more critical to overall performance.

So, naturally, we take shortcuts...

Height Maps


The way a "Height Map" works is to simply store a series
of regularly-spaced height samples across a regular grid
(i.e. an array)

This tends to make for a simple implementation, which is fast, memory-efficient, and quite suitable for many situations.

My own "Wild Metal Country" worked this manner (in 1999).

And it's what "Skyrim" does too.

Height Map Creation


You can create a height map by "any means necessary", including generating it as a fractal.

Or you can let the artists draw it directly as a grey-scale texture, or you can provide them with an actual editing tool which lets them loft and sculpt the environment in real-time.

We did all three.

Height Map Texturing


You then texture the terrain using a set of pre-rendered tiles which represent the various surface types available to you.

In a system with texture-blending, you can perform arbitrary overlapping blends to create smooth transitions between
these surface types.

In WMC, we didn't have that option, so we had to use a palette of pre-blended textures and pick the "best fit" for
each tile on the map, based on its supposed composition.

Wild Metal Country

I don't care what anyone says, I'm still proud of it.


How Skyrim Does It



Terrain Texture Examples


2D Environment Collision


Analogous techniques (and simplifications) are often
applied to handling the environment in 2D games also.

In particular, the environment is often (though not always) built on a fixed grid, which can be conveniently represented
as a 2D array, rather than as an arbitrary set of free-form rectangular blocks (or whatever it might be).

...Consider the background tiling of an old Mario game,
for example.

In Conclusion

This concludes our introduction to the exciting world of collision detection... but there will be more next time.