773
frame, or next frame, that game object can pick up the results of its request and
make use of them.
Batching is another shift in thinking for game programmers. As we men-
tioned in Section 14.6.2, it is more effi cient to collect similar tasks into batches
and perform them en masse than it is to run each task independently. This
applies to the process of updating game object states as well. For example, if
a game object needs to cast 100 rays into the collision world for various pur-
poses, it is best if those ray cast requests can be queued up and executed as
one big batch. If an existing game engine is being retrofi tt ed for parallelism,
this oft en requires code to be rewritt en so that it batches requests rather than
doing them individually.
One particularly tricky aspect of converting synchronous, unbatched code
to use an asynchronous, batched approach is determining when during the
game loop (a) to kick off the request and (b) to wait for and utilize the results.
In doing this, it is oft en helpful to ask ourselves the following questions:
z How early can we kick off this request? The earlier we make the request, the
more likely it is to be done when we actually need the results—and this
maximizes CPU utilization by helping to ensure that the main thread
is never idle waiting for an asynchronous request to complete. So for
any given request, we should determine the earliest point during the
frame at which we have enough information to kick it off , and kick it
there.
z How long can we wait before we need the results of this request? Perhaps we
can wait until later in the update loop to do the second half of an opera-
tion. Perhaps we can tolerate a one-frame lag and use last frame’s results
to update the object’s state this frame. (Some subsystems like AI can
tolerate even longer lag times because they update only every few sec-
onds.) In many circumstances, code that uses the results of a request can
in fact be deferred until later in the frame, given a litt le thought, some
code re-factoring, and possibly some additional caching of intermediate
data.
14.7. Events and Message-Passing
Games are inherently event-driven. An event is anything of interest that hap-
pens during gameplay. An explosion going off , the player being sighted by an
enemy, a health pack gett ing picked up—these are all events. Games generally
need a way to (a) notify interested game objects when an event occurs and (b)
arrange for those objects to respond to interesting events in various ways—we
14.6. Updating Game Objects in Real Time