|
Resource
Guide

Outsourcing
Reality: Integrating a Commercial Physics Engine
Player Control
Strategies
Player control of the avatar is, for many games, where you're going to
spend the most time fine-tuning your physics integration. Every design
trade-off you've made regarding physics resolution, applying forces, keyframe
data, and the like will all come together to affect how your character
navigates and how realistic it feels. The avatar is so central to the
player's perceptions that any glitch becomes extremely visible. I'm going
to talk about the strategy we're using for our application, a multiplayer,
networked, third-person exploration game with a mix of indoor and outdoor
environments and an emphasis on photorealism. Naturally, your approach
will vary depending on the design of your game, but you'll probably recognize
issues that apply to your own situation.
A key decision for player control is the shape of the proxy you'll use
to do collision for your character. A popular choice is a simple capsule
(Figure 5). This shape has several advantages: It's smooth on the bottom,
so it can glide over uneven terrain; it's radially symmetric from above,
so your avatar can turn in place without being pushed away from the wall;
and it has no sharp corners, which can get caught on narrow doorways.
A subtler advantage is that since it presents no sharp corners to the
ground, it won't jump or stick as it hits polygon joins in an otherwise
flat terrain.
Notice that
the character's arm sticks out through the capsule. He's illustrating
a point, which is that this capsule is used only for his gross movement
in the environment, and it does not handle detail interactions between,
say, his hand and a lever. We use a completely different mechanism for
such detail interactions; the problems of detail interaction are beyond
the scope of this article, but suffice it to say that they're different
enough to justify separate mechanisms from those used for movement. As
for the realism of the simplistic shape, it's instructive to note that
a large percentage of a human's motor control goes into maintaining the
illusion that we're not a bundle of flailing limbs all moving in different
directions. A real human body does an extremely good job of moving our
head along on a smooth path. As a result, a simplified physical body can
actually lead to more realistic results than a multi-limbed physics body.
That's how we're shaped, but how do we move? What translates button presses
into forward motion? There are three fundamental approaches. First you
can set the position and orientation of your character directly. Second
you can set the velocity (linear and angular) of your character. And finally,
you can apply forces to propel your character.
Setting position is attractive because it's so simple: You're standing
here and you want to move forward, so just add a vector. This approach
falls apart pretty quickly, unfortunately, and it is the least friendly
to using physics in a general fashion.
Assume we start each frame in a physically valid position. Our player
tells us to move forward, so we construct a vector representing typical
forward motion, orient it to our player's forward vector, and add it to
our position. Easy enough so far, and if all games were played on an infinite
flat plane, this would work great. But what happens when the position
we want to occupy overlaps with a wall, or even with a slight rise in
the ground?
Big deal, you say, we have a fancy physics package. We'll just ask it
to validate the position before we finalize it. So what do you do when
the position is not valid? You'll have to calculate the point of impact,
figure out where your character is deflected, and so on. This situation
only gets worse when you consider that there are other moving objects
in the environment. The problem is that by setting position directly,
you've shut your physics engine out of the loop and you now have to write
more code to take its place. How do we get physics to do this work for
us?
Forces are a natural way to move a physics body around. On the good side,
you'll find that a lot of unplanned situations tend to work when you use
forces: If your character hits some boxes, he'll knock them over. If he's
hit by a rolling boulder, the force imparted by the boulder will combine
with his walking force to move him in a new direction. He'll interact
realistically with slopes and walls. In general, it's a major improvement.
On the other hand, using forces to move the player somewhat decreases
your level of control over exactly how the player moves. Subtler issues
such as friction come into play, and it becomes hard simply to say, "Walk
to this spot." Forces tend to highlight the fact that we're using
a simplistic capsule shape for the player and not a 400-bone musculoskeletal
simulation. While a golf ball might fly 100 yards if you whack it with
a paddle, a human won't, and the reasons why are a complex to emulate.
Positioning the player by setting velocity is a reasonably happy medium
between the total physics-unfriendliness of setting position and the loose
control provided by forces. Rather than saying what position you want
to be in each frame, calculate how fast you need to be moving to reach
your target position and set the velocity on your physics body accordingly.
This has many of the same benefits as forces. If your character hits a
wall, he'll either stop or slide along it. If he steps off a cliff, he'll
start to fall, and if he hits a slope he'll climb up it. Little rises
and falls in the ground will be automatically incorporated into your character's
movement, and you still have pretty tight frame-to-frame control of your
character's movement; he won't go flying off down a hill if you're setting
his speed each frame, and you won't get an unfortunate confluence of external
influences causing him to fly through the air.
One drawback to this approach is that your motion is still based on movement
on a flat plane, so you're going to see some unrealistic movement when,
for example, the ground drops away rapidly. If you're just applying that
forward-walk vector, downward gravitational force will be applied every
frame, but it will be blown away by your preordained velocity. As a result,
the character will fall at a slow, constant rate and won't accelerate
toward the ground as he should; he'll only get one frame's worth of acceleration
each time before starting over at zero.
There are two solutions to this problem. The first is to leave vertical
velocity alone when you're walking, and the second is to stop walking
when you're in the air. In actuality, both are necessary; you don't want
a single-frame departure from the ground (common when hitting a bump)
to interrupt your forward progress, so your walk behavior should continue
for a short time after leaving the ground. Since this can cause a few
frames of floating when stepping off a cliff, not setting vertical velocity
is necessary to trim off any extra frames of floating when cresting a
peak. A rule of thumb is that each navigational state should have a sense
of what kind of velocity it can set: a walk can't set vertical velocity,
but a jump can.
Another drawback to the velocity-based approach is that it does not automatically
integrate external forces. If your avatar is walking forward and suddenly
slammed by a 10-ton rolling boulder moving left, he won't budge unless
you take extra measures to notice that the velocity you sent down last
frame has been modified somewhat. Resolving this correctly is somewhat
beyond our scope here, but it involves keeping track of the intended velocity
and combining it intelligently with the actual velocity, rather than just
setting it.
We've just touched on a few of the issues regarding player control in
a physical environment. While they can be extremely challenging, solving
these problems creatively will open up a lot of new possibilities.
Focus on Creativity
Now that
we've been freed of the burden of writing yet another BSP-versus-bouncing
spheres physics engine, we find that integrating a full-featured commercial
engine can be just as much work. The critical difference between the two
approaches is huge, though: a robust implementation of fully generalized
physics is capable of forms of gameplay we haven't even dreamed of yet.
I think that physics engines are going to do for gameplay what rendering
engines have done for visuals: provide a rich base of stable features,
freeing implementers to focus on creative new functionality rather than
being chained to an endless wheel of reinvention. We've already seen our
play-testers using the laws of physics to invent new gameplay for which
we hadn't even planned. Managed carefully, this combination of planning
and discovery holds great promise for the future of games and gameplay.
For More Information
Havok
www.havok.com
Mathengine's
Karma
www.mathengine.com
Source
code for calculating a tight-fitting spherical
primitive from a polytope:
http://vision.ucsd.edu/~dwhite/ball.html
Generating
convex hulls from arbitrary geometry:
www.geom.umn.edu/software/qhull
Using
BSPs to break a level into convex shapes:
www.faqs.org/faqs/graphics/bsptree-faq
UNC's
excellent pages on collision, with several academic
implementations:
www.cs.unc.edu/~geom/collide/packages.shtml
Russell
Smith's excellent open-source physics engine, ODE:
www.q12.org/ode/ode.html
|