312
In p
r
of accel
e
the mos
frame ra
ProveI
So it so
u
b
y drivi
n
location
es in Fi
g
velocity
zier spli
n
If you
w
tations
o
Figure 1
8
accelerat
i
r
actice, this
w
e
ration signi
f
t
forgiving
o
t
es.
t!
u
nds good in
t
n
g a vehicle i
from the de
a
g
ure 18.4 and
blending is
r
n
es. That rati
w
ant to test it
y
o
f both projec
t
8
.4. Cubic Bé
z
i
on (top) and
w
1
w
orks out m
a
f
icantly reduc
o
f both inco
n
t
heory, but le
n a repeatabl
e
a
d-reckoned l
o
statistics in
T
r
oughly five
t
o improves
a
y
ourself, the
d
t
ive velocity
b
z
ier splines (l
e
w
ithout acceler
a
8.Believabl
e
a
gnificently!
e the oscillat
n
sistent net
w
t
’s get some
p
e
pattern (e.
g
o
cation, we
c
T
able 18.1 sh
t
o seven per
c
a
bit more w
h
d
emo applica
b
lending and
e
ft) versus pro
j
a
tion (bottom)
e
DeadReck
o
The blende
d
t
ions. In addi
t
w
ork update
r
p
roof. We ca
n
g
., a circle).
B
c
an determin
e
h
ow the clear
c
en
t
more ac
c
h
en you can’t
a
tion on the
w
d
cubic Bézie
r
j
ective velocit
y
.
o
ningforNet
w
d
velocity an
d
t
ion, this tec
h
r
ates and ch
a
n
perform a
b
B
y subtractin
g
e
the error. T
h
result. The p
r
c
urate than c
u
t
publish acc
e
w
ebsite has i
m
r
splines.
y
blending (ri
g
w
orkedGam
e
d
change
h
nique is
a
nges in
b
asic test
g
the real
h
e imag-
r
ojective
u
bic Bé-
e
leration.
m
plemen-
g
ht), with
e
s
18.4TimeforT 313
Update Rate Cubic Bézier
(DR Error)
Projective Velocity
(DR Error)
Improvement
1 update/sec 1.5723 m 1.4584 m 7.24% closer
3 updates/sec 0.1041 m 0.1112 m 6.38% closer
5 updates/sec 0.0574 m 0.0542 m 5.57% closer
Table 18.1. Improvement using projective velocity blending. Deck-reckoning (DR) error
is measured in meters.
As a final note, if you decide to implement a spline behavior instead of pro-
jective velocity blending, you might consider the cubic Bézier splines [Van Verth
and Bishop 2008]. They are slightly easier to implement because the control
points can simply be derived from the velocities
0
V
and
0
V
. The source code on
the website includes a full implementation.
18.4TimeforT
So far, we’ve glossed over time. That’s okay for an introduction, but, once you
begin coding, the concept of time gets twisted up in knots. So, let’s talk about T.
WhatTimeIsIt?
The goal is to construct a smooth path that an actor can follow between two mo-
ments in time
0
T
and
1
T
. These two times mark the exact beginning and end of the
curve and are defined by locations
0
P
and
1
P
, respectively. The third time
t
T
is
how much time has elapsed since
0
T
. The final time
ˆ
T
represents how far the ac-
tor has traveled along the path as a normalized value, with
ˆ
0.0 1.0T
.
0
T
is easy. It’s the time stamp when the last known values were updated. Ba-
sically, it’s “now” at the time of the update. If you’ve seen the movie Spaceballs,
then
0
T
is “now, now.” When we process a new network update, we mark
0
T
as
now and set
t
T
back to zero. The slate is wiped clean, and we start a whole new
curve, regardless of where we were.
If
0
T
is now, then
1
T
must be in the future. But how far into the future,
Δ
T
,
should the projection go? Well, if we knew that the actor updates were coming at
regular intervals, then we could just use the inverse update rate. So, for three up-
dates per second,
Δ
0.333 s
T
. Even though network updates won’t always be
perfectly spaced out, it still gives a stable and consistent behavior. Naturally, the
314 18.BelievableDeadReckoningforNetworkedGames
update rate varies significantly depending on the type of game, the network con-
ditions, and the expected actor behavior. As a general rule of thumb, an update
rate of three per second looks decent and five or more per second looks great.
TimetoPutItTogether
From an implementation perspective, normalized time values from zero to one
aren’t terribly useful. In many engines, you typically get a time
f
T
since the last
frame. We can easily add this up each frame to give the total time since the last
update
t
T
. Once we know
t
T
, we can compute our normalized time
ˆ
T
as follows:
ttf
T
TT
Δ
ˆ
t
T
T
T
.
Now we have all the times we need to compute the projective velocity blend-
ing equations. That leaves just one final wrinkle in time. It happens when we go
past
Δ
T
(i.e.,
Δt
T
T
). This is a very common case that can happen if we miss an
update, have any bit of latency, or even have minor changes in frame rate. From
earlier,
ˆ
tt tt
T

Q
PPP
.
Because
ˆ
T
is clamped at one, the
t
P
drops out, leaving the original equation
2
00 0
1
2
ttt
TT


Q
PV A
.
The math simplifies quite nicely and continues to work for any value of
ˆ
1.0
T
.
JustinTimeNotes
Here are a few tips to consider:
Due to the nature of networking, you can receive updates at any time, early
or late. In order to maintain
1
C
continuity, you need to calculate the instanta-
neous velocity between this frame’s and the last frame’s dead-reckoned posi-
tion,
1tt f
T
PP
. When you get the next update and start the new curve,
use this instantaneous velocity for
0
V
. Without this, you will see noticeable
changes in velocity at each update.
18.5PublishorPerish 315
Actors send updates at different times based on many factors, including crea-
tion time, behavior, server throttling, latency, and whether they are moving.
Therefore, track the various times separately for each actor (local and re-
mote).
If deciding your publish rate in advance is problematic, you could calculate a
run-time average of how often you have been receiving network updates and
use that for
Δ
T
. This works okay but is less stable than a predetermined rate.
In general, the location and orientation get updated at the same time. Howev-
er, if they are published separately, you’ll need separate time variables for
each.
It is possible to receive multiple updates in a single frame. In practice, let the
last update win. For performance reasons, perform the dead reckoning calcu-
lations later in the game loop, after the network messages are processed. Ide-
ally, you will run all the dead reckoning in a single component that can split
the work across multiple worker threads.
For most games, it is not necessary to use time stamps to sync the clocks be-
tween clients/servers in order to achieve believable dead reckoning.
18.5PublishorPerish
So far, the focus has been on handling network updates for remote actors. How-
ever, as with most things, garbage in means garbage out. Therefore, we need to
take a look at the publishing side of things. In this section, forget about the actors
coming in over the network and instead focus on the locally controlled actors.
WhentoPublish?
Let’s go back and consider the original tank scenario from the opponent’s per-
spective. The tank is now a local actor and is responsible for publishing updates
on the network. Since network bandwidth is a precious resource, we should re-
duce traffic if possible. So the first optimization is to decide when we need to
publish. Naturally, there are times when players are making frequent changes in
direction and speed and five or more updates per second are necessary. However,
there are many more times when the player’s path is stable and easy to predict.
For instance, the tank might be lazily patrolling, might be heading back from a
respawn, or even sitting still (e.g., the player is chatting).
The first optimization is to only publish when necessary. Earlier, we learned
that it is better to have a constant publish rate (e.g., three per second) because it
keeps the remote dead reckoning smooth. However, before blindly publishing
every time it’s allowed (e.g., every 0.333 s), we first check to see if it’s neces-
316 18.BelievableDeadReckoningforNetworkedGames
bool ShouldForceUpdate(const Vec3& pos, const Vec3& rot)
{
bool forceUpdateResult = false;
if (enoughTimeHasPassed)
{
Vec3 posMoved = pos – mCurDeadReckoned_Pos;
Vec3 rotTurned = rot – mCurDeadReckoned_Rot;
if ((posMoved.length2() > mPosThreshold2) ||
(rotTurned.length2() > mRotThreshold2))
{
// Rot.length2 is a fast approx (i.e., not a quaternion).
forceUpdateResult = true;
}
// ... Can use other checks such as velocity and accel.
}
return (forceUpdateResult);
}
Listing 18.1. Publish—is an update necessary?
sary. To figure that out, we perform the dead reckoning as if the vehicle was re-
mote. Then, we compare the real and the dead-reckoned states. If they differ by a
set threshold, then we go ahead and publish. If the real position is still really
close to the dead-reckoned position, then we hold off. Since the dead reckoning
algorithm on the remote side already handles
Δt
T
T
, it’ll be fine if we don’t up-
date right away. This simple check, shown in Listing 18.1, can significantly re-
duce network traffic.
WhattoPublish
Clearly, we need to publish each actor’s kinematic state, which includes the posi-
tion, velocity, acceleration, orientation, and angular velocity. But there are a few
things to consider. The first, and least obvious, is the need to separate the actor’s
real location and orientation from its last known location and orientation. Hope-
fully, your engine has an actor property system [Campbell 2006] that enables you
to control which properties get published. If so, you need to be absolutely sure
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.17.176.72