Game Development Community

T3D 1.1 Beta2 (and all previous versions) - projectiles network their position and velocity twice when created - RESOLVED

by Guy Allard · in Torque 3D Professional · 08/10/2010 (6:12 pm) · 4 replies

I think this one has been present in the engine for a long long time, and is a very nice way of using up lots of bandwidth unnecessarily in a large firefight. The projectiles are sending their position and velocity to the client twice as part of their initial update.

The projectiles network their position and velocity to the client upon creation. If a projectile bounces on something, the position and velocity are re-sent to the client to ensure that things stay in sync. BounceMask is used to trigger the update of a bounce.

in packUpdate, initially the pos and vel are sent as compressed point and normal after
if ( stream->writeFlag( isInitalUpdate ) )

then, further down, they are re-sent in uncompressed form as part of the same update after
if ( stream->writeFlag(( mask & BounceMask ))
because BounceMask is 1 for the first network update

This line should read
if ( stream->writeFlag(( mask & BounceMask ) && !isInitalUpdate ) )

Now the initial packet will only contain one version of the projectiles position and velocity.

However, we now potentially have another problem - the use of compressed vectors for the position and velocity may lead to inaccurate projectile trajectories on the client. This was not a problem before, as it was being accidentally corrected by the second transmission of these values in their uncompressed form.

You can check that this is really happening by putting
Con::printf("Projectile - initial update");
after
if ( stream->writeFlag( isInitalUpdate ) )
{

and
Con::printf("Projectile - bounce update");
after
if ( stream->writeFlag( mask & BounceMask ))
{

then shoot a projectile at the sky - you'll see that both the initialUpdate and BounceMask sections are being called.

I've reported this as a bug, as this is clearly not the intended functionality.

#1
08/10/2010 (7:45 pm)
Nice catch. Doubling up this data doesn't sound like a lot, but in multiplayer with tons of projectiles being created it could add up.

I was trying to think of a scenario where a bounce could have occurred before the initial update packet went out, ie if a projectile bounced in tick 0 and the initial update was delayed until tick 1 (certainly can happen), but it still shouldn't matter since in that case the initial update would be sending the post-bounce velocity anyway.

The compression accuracy loss is probably minimal, but since we're talking about a net gain in networking traffic either way it seems like it could be reasonable to just send the initial update vectors uncompressed. I might run some tests on long-range projectiles, see how much of an impact point offset between client and server actually result from the compression over various distances.

*Edit:
Started messing with this, first thing I noticed was that if you disable sending the bounce update during initial update, the projectile doesn't appear at all. That's because it's using the sceneGraph position instead of mCurrPosition. So you'll either need to change it to use mCurrPosition or add my fix to onAdd() from the other thread, which is basically just to call:

MatrixF xform( true );
xform.setColumn( 3, mCurrPosition );
setTransform( xform );

At some point during onAdd(), doesn't seem to really matter where. Near the end seems best. You could also just use mCurrPosition in packUpdate instead of getTransform, but I recommend fixing this for the other reason (late ghosts) anyway.

(note: If you were seeing some projectiles but not others, that's probably b/c you're using a <32 packet to client rate, but if you keep firing until a projectile ghosts on tick 0 by chance it will fail to appear.)

Anyway, collecting some test data on compression-induced offsets now.

First a high-speed projectile, near bullet velocity:
sending initial pos: 348.480011 182.796005 252.735001
sending initial vel: -544.786987 -250.292007 23.681900
read pos: 348.485840 182.797012 252.728607
getting initial vel: -232.278870 -107.098228 9.823461
Explode Pos (Srv): 33.116974 37.908497 266.443756
Explode Pos (Clnt): 207.260315 117.681335 258.701324


Now a slower projectile (the rocket):
sending initial pos: 348.157013 182.975006 252.459000
sending initial vel: -91.933800 -39.125099 -4.171460
read pos: 348.165833 182.977005 252.458618
getting initial vel: -91.813972 -39.295574 -4.450031
Explode Pos (Clnt): 39.395344 50.825737 237.493790
Explode Pos (Srv): 38.206390 51.066639 238.395416


That's kind of confusing maybe, but the first thing I noticed is that the compression system it's using for velocity does not seem to work with higher velocities, it's actually cutting them in half. For the slower projectile, the difference between pack and unpack is minimal compression noise, but for the bullet projectile, it's massively slowed down.

That aside, even the rocket was off by ~1.5m (1.511481) when it exploded. The explosion update corrects the position, but if you were standing near the impact point you'd see a rocket trail come in and an explosion go off almost 2 meters from where the trail was pointing, which would be kind of strange.
#2
08/12/2010 (12:07 am)
Logged as TQA-772
#3
08/19/2010 (8:31 pm)
Bug confirmed.
#4
09/01/2010 (9:36 pm)
Fixed in 1.1 Beta 3.