Game Development Community

Creating a simple, networked, moving object that doesn't jitter

by Aloshi · in Torque 3D Professional · 06/05/2011 (6:41 pm) · 2 replies

So, I've been trying to create a relatively simple class based on StaticShape, except that it has a velocity. It's not affected by gravity, nor does it collide with anything. I've gotten it almost working; the object spawns correctly and moves smoothly most of the time, but not all of the time; occasionally, the object will "jitter." I think I'm also may be networking it incorrectly.

I've been having trouble tracking down exactly what the problem is; it seems partially latency dependent and partially framerate dependent. I've been using client.setSimulatedNetParams(0, 300) to test latency. I get no jitter at 60fps (vsync turned on), both with and without simulated net params. At lower framerates (30, 45), I get jitter, again both with and without simulated net params. At framerates over 60 (200 to 500), I get no jitter without simulated net params, but jitter with simulated net params at what seems like certain framerates (it'll jitter, I'll look away from the terrain to get a higher framerate, then it'll stop for a bit, then continue).

I pieced together what I could from Player.cpp and some other resources, and it's very possible that I implemented the calculation of the new position (in my processTick), interpolation, and/or networking, wrong...hopefully someone who knows what they're doing can help me out here? If there's another thread or resource on this topic, could someone link me to it?

My packUpdate:
U32 ShipObject::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
{
	U32 retMask = ShapeBase::packUpdate(con, mask, stream);
	
	//Transform
	if (stream->writeFlag(mask & PositionMask))
	{
		mathWrite(*stream,mObjToWorld); 
	}

	//Scale
	if(stream->writeFlag(mask & ExtendedInfoMask))
	{
		mathWrite(*stream, mObjScale);
	}

	//Velocity
	if(stream->writeFlag(mask & VelocityMask))
	{
		mathWrite(*stream, mVelocity);
	}
	
	return retMask;
}

My unpackUpdate:
void ShipObject::unpackUpdate(NetConnection *con, BitStream *stream)
{
	ShapeBase::unpackUpdate(con, stream);

	//Transform
	if (stream->readFlag())
	{
		MatrixF mat;
		mathRead(*stream,&mat);
		setTransform(mat);
	}

	//Scale
	if(stream->readFlag())
	{
		VectorF scale;
		mathRead(*stream, &scale);
		setScale(scale);
	}
	
	//Velocity
	if(stream->readFlag())
	{
		mathRead(*stream, &mVelocity);
	}
	
}

My processTick:

void ShipObject::processTick(const Move* move)
{
	Parent::processTick(move);
	
	MatrixF mat = Parent::getTransform();

	mat.setPosition(mat.getPosition() + (mVelocity * TickSec)); //Velocity * (32 / 1000)
	
	//Delta is just a struct used to store some variables for interpolation
	delta.DeltaBase = mat.getPosition();
	delta.BackDelta = mat.getPosition() - Parent::getPosition();

	setTransform(mat);
}

And my interpolateTick:
void ShipObject::interpolateTick(F32 dt)
{
	Parent::interpolateTick(dt);

	MatrixF startmat = Parent::getTransform();
	MatrixF endmat = Parent::getTransform();
	
	endmat.setPosition(delta.DeltaBase - (delta.BackDelta * dt));

	Parent::setRenderTransform(endmat);
}

(oh, and ShipObject::setTransform just calls Parent::setTransform and does setMaskBits(PositionMask), and Parent is just StaticShape; I probably used Parent more than I needed to, as I'm not experienced with C++)

And here's a video of what I mean by jitter (taken at 45fps, no simulated latency): http://youtu.be/U_PE2HAldVM

#1
06/08/2011 (1:23 pm)
I hate to bump this, but I really don't know what else to try.
#2
06/08/2011 (8:28 pm)
This sounds like a warping problem. Warping (I believe) is a way that torque does networked movement where the client extrapolates from what position and velocity information it has, and updates this information when it gets a new server packet. You can see this in action in, for example, item.cpp around line 1035.