Game Development Community

Client-side item not properly updated

by Markus Nuebel · in Torque Game Engine · 02/14/2005 (11:46 pm) · 6 replies

Recently I wanted to do a standard item, with very less gravity (e.g. between -0.1 and 0.1) that is kind of floating in the air and ran into two problems with the item code.

1. pack/unpack only allows for positive gravityMod values
The networking functions are sending the member ItemData::gravityMod over the wire using:
stream->writeFloat(gravityMod, 10);
...  // and
gravityMod = stream->readFloat(10);

This does not allow to have objects move upwards. So I changes this to:
stream->writeSignedFloat(gravityMod, 10);
...  // and
gravityMod = stream->readSignedFloat(10);

I really don't know, if gravity can be negative (in physical terms) so I wouldn't consider this as a bug, just as a nice to have for gaming worlds.

2. If the server side object changes it's flag from atRest to not at rest, no network update is issues and so the client side item is not starting to move.

The default value of Item::mAtRest is true which get's replicated to the client, shortly after an item adds the simulation.
When the server side item starts to move because of gravity (regardless of it's direction) the Item::mAtRest flag will be switched to false:

void Item::processTick(const Move* move)
{
...
      if (isServerObject() && mAtRest && (mStatic == false && mDataBlock->sticky == false))
      {
         if (++mAtRestCounter > csmAtRestTimer)
         {
            [b]mAtRest = false;[/b]
            mAtRestCounter = 0;
         }
      }

...
}

Since this happens, without an explicit call to setTransform() or setVelocity() no network flags are set and no client update is issued. This leads to a situation, where the server side item is in heavy movement (according to gravity) but the client side item stands still.

Switching the PositionMask in this situation resolves the problem, since a position update will also update the mAtRestFlag
void Item::processTick(const Move* move)
{
...
      if (isServerObject() && mAtRest && (mStatic == false && mDataBlock->sticky == false))
      {
         if (++mAtRestCounter > csmAtRestTimer)
         {
            mAtRest = false;
            mAtRestCounter = 0;

            [b]setMaskBits(PositionMask);[/b]
         }
      }

...
}

Because issue #2 can also be observed for positive (normal) gravity, I think this could be problem in other projects, too.

-- Markus

#1
02/19/2005 (4:44 pm)
This is a pretty interesting writeup. I've added it to my list of things to review for 1.4. Thanks, Markus.
#2
08/09/2005 (12:37 am)
And committed some fixes into trunk based on it - thanks!
#3
08/09/2005 (12:07 pm)
Thanks for letting us know, Ben.
#4
08/02/2007 (8:30 am)
Sorry for bumping an old topic but I seem to be having the same issue using a clean copy of TGE 1.4.2 + TLK. Using applyImpulse() on an item results in it warping from the 'resting' position to the new position on the client. In the editor, you can see the worldbox move smoothly to the new location. It seems as though the client isn't properly interpolating between the two positions.

Here's a few pics to illustrate the problem:

applyImpulse() called on item

Item returning to "rest" state - position finally updated
#5
08/02/2007 (10:43 am)
Oh, thanks for bumping this. It seems to be very much related to a problem im having right now :)
#6
08/03/2007 (10:46 am)
Glad I'm not the only one having this problem. I've done a comparison of both item.cc and item.h from TGE 1.4.2 and TGE 1.3 and there's only minor differences (some spelling error fixes, syntactical changes and, of course, the fix mentioned above). I'll keep digging. :]