Game Development Community

Performance problems when objects are moving

by Tobias B. · in Torque 3D Professional · 11/26/2009 (10:09 am) · 12 replies

Hi,

I have a strange effect in my simulation application: I derived a class called SimulationObject from ShapeBase. This class uses a non-blocking communication to receive position data from an external simulation during every processTick() and interpolateTick().

When the simulation does not run, the objects remain at their position. In this case, I can move smoothly through my world.

When I start the simulation and the objects are moved by the simulation position data (in my example 6 objects), I get massive performance problems and heavily reduced frame rates. This ist not caused by the external simulation, since it produces CPU load around 1% on my dual-core machine. It is not caused by the communication since it is non-blocking.

Does it make a difference for the engine, if ShapeBaseData-derived objects were moved between two render calls? Does the engine check if an object was moved in between and does this cause CPU oder GPU load? To make it clear: Not only the objects move very rough, also the camera becomes unsmooth (both free and player camera). In case it is important: It happens both in Advanced and Basic Lightning.

I have no explanation for that. Do you?

Thanks a lot,

Tobias

#1
11/27/2009 (12:54 am)
Did you mean that it derives from ShapeBase? ShapeBaseData is a datablock and does not receive ticks.

I don't know if this is the direct cause of your slowdown, but it sounds like you probably do not need to modify interpolateTick. The torque simulation occurs in processTick which is where the object should do whatever processing to determine where is has moved in the last TickMS.

InterpolateTick is called prior to each frame render and just for interpolating smoothly between the prev / next tick position ( of the object ).
#2
11/27/2009 (4:32 am)
Yeah, you're right: I mixed it up, sorry. It was derived from ShapeBase. I corrected that in my original post, thanks!

Concerning interpolateTick(): I generate new positions for the object in a very high rate (100 times per second), so I have fresh position data also when interpolateTick() is called by the engine. Thus, I found it more elegant to use the updated simulation data instead of interpolation... is this the wrong way?

My primary question is if moving ShapeBase objects require more computation power than fix ones...?
#3
11/27/2009 (3:17 pm)
In that situation I suppose you might as well make use of the higher resolution data. What type of objects are you simulating, out of curiosity?

A setTransform call on a ShapeBase object does pretty much the same thing it does for a SceneObject so that call is not directly the problem.

Some ShapeBase derived classes like Player and Vehicle actually do a lot of work when they move in updatePos, like sweep tests, but that is called from processTick not setTransform. And as you said you are overriding the functionality in processTick while your simulation is in control so I assume that is not happening ( also you would have had to copy code from Player or Vehicle for this to even be relevant ).

One thing to keep in mind is that the client tick happens first, then when the server performs that tick it should be in the same position as the client object. If they do not match the server will send a correction to the client object and it will do "warp ticks" to the serverside position.

It sounds quite likely that the position you are setting based on your simulation is causing Torque to server-client fight / constantly send correction.
#4
11/30/2009 (5:39 am)
I'm simulating cars and their dynamic behaviour. Presently, I'm using 5-10 cars which are low-poly.

The point is: If I don't move them, the performance is quite good. The trouble starts as soon as their position is changed. Your idea about client/server troubles sounds good. So how do I manage to solve that?

In fact, the simulation objects should be comparable to normal players in a network game. Instead of keyboad/mouse inputs, the simulation determines their movements.
#5
12/01/2009 (8:53 am)
Hi,

the implementation of processTick() and interpolateTick() is similar and principally as follows (in fact, it is composed by several functions - I hope I don't mix it up):

void SimulationObject::processTick(const Move* move)
{
Parent::processTick( move );
MatrixF mat;
updateSignals( mat );
Parent::setTransform( mat );
}

void SimulationObject::interpolateTick( F32 delta )
{
Parent::interpolateTick( delta );
MatrixF mat;
updateSignals( mat );
Parent::setRenderTransform( mat );
}

void SimulationObject::updateSignals( MatrixF &_mat )
{
Point3F pos;
QuatF   rot;
MatrixF tmat;
MatrixF mat;

getRenderEyeTransform(&tmat);
pos = tmat.getPosition();
rot.set(tmat);
pos = getPositionFromSimulation(); //This copies the position data
rot = getOrientationFromSimulation(); //This copies the orientation data
rot.setMatrix(&mat);
mat.setPosition(pos);
_mat = mat;
}

Is there anything that has to be changed with respect to the client/server data exchange?
#6
12/01/2009 (2:51 pm)
I apologize for the long stream of questions that follow, but I cannot really tell what architecture would be appropriate for what you are trying to do without more information.

When is the simulation advanced?
Is there a seperate simulation for the client and server?
Can one of these cars be a control object (Client controlled)?
What is the functional purpose of the car simulation and SimulationObject within the game?
Does SimulationObject have collision ( with each other with the player etc ) and how is that handled?
#7
12/01/2009 (3:34 pm)
Here is a collection of game networking papers Tom posted just the other day.
#8
12/02/2009 (6:41 am)
Thanks a lot. Please allow some time for me to understand Torque's internal networking model. I will respond as soon as possible.
#9
12/02/2009 (8:41 am)
Hi,

hey - I asked for help and I'm glad to have someone like you being interested :-)

So here my answers:
Quote:When is the simulation advanced?
The simulation runs independently from Torque, using own integrators and time steps, and it runs close to the real time. The simulation provides an interface to report the position and orientation of any simulation object at every time step. The interface functions are non-blocking.
Quote:Is there a seperate simulation for the client and server?
I think I don't understand this clearly since I'm presently still trying to get Torque's client/server architecture. Well, the client is connected to the simulation. It should be just like a player in a multiplayer game - every client has its own simulation object, handles its movement (in our case, not by keyboard/mouse control but by reading out the simulation data) and should report this to the server. The server collects and distributes all simulation object data, so all clients can display all simulation objects. Imagine our simulation like a racing game where all players are controlled by an own simulation running on a separate player PC each.
Quote:Can one of these cars be a control object (Client controlled)?
Yes. At the moment, the client controls always one ego-car, i.e. a car which is controlled by the simulation and at which we sit in. Additional cars may appear and are also controlled by the simulation. In a future version, additional cars should be actively controlled by other clients with an own simulation.
Quote:What is the functional purpose of the car simulation and SimulationObject within the game?
I try to visualize a traffic simulation. The SimulationObject is the representation of the simulated cars. This gives us the possibility to couple the simulation (running on a special simulation environment) with the Torque engine as the graphical output.
Quote:Does SimulationObject has collision ( with each other with the player etc ) and how is that handled?
I did no implementation in that direction. For the time being, we could switch off collision checking since I handle all events in the simulation program. But I did not implement anything. In fact, my hope was that I inherit collision handling in a sufficient way. If it saves time, I do not need collision checking!

I hope my answers are sufficient - as I already said - I'm presently trying to learn about Torque networking. I didn't know that my performance problem is coupled to a client/server problem. Since I use only one client at this time, my hope was that I can neglect this for the moment...
#10
12/02/2009 (2:39 pm)
These three papers linked on Tom's page are the must reads:

The TRIBES Engine Networking Model ( Mark Frohnmayer and Tim Gift )
Robust, Efficient Networking ( Ben Garney )
Networked Physics ( Glenn Fiedler )

I do not actually know if the problem you are having really is networking related; this is just a hypothesis of mine. But this is very relevant information for anyone doing a multiplayer game, and especially in Torque.

Quote:It should be just like a player in a multiplayer game - every client has its own simulation object, handles its movement (in our case, not by keyboard/mouse control but by reading out the simulation data) and should report this to the server. The server collects and distributes all simulation object data, so all clients can display all simulation objects.

Torque does not work this way. The server object is authoritative not the client. The only limited control the client has is over its control object, for which it sends a Move to the server, but this is not an absolute position it is only inputs to the simulation. When the server objects are ticked they will process the Move transmitted from the client ( if they have one ) to drive the simulation.

However some simulation is done on the client. In order to reduce latency the client's control object is simulated with the current Move 'before' sending the Move to the server. This is essentially client side prediction. But the result of this simulation is not authoritative. When that Move arrives at the server it will also simulate that object using that input Move ( and all others for that time-step ) and should the server come to a different result than the client it will send a correction.

Actually this is described much more thoroughly in the links above.

Honestly this sounds like a very tricky problem. A few random ideas...

Move the external simulation completely into Torque. Everything is a Vehicle, AI controlled cars are driven with Moves instead of directly set to positions ( this is what Torque is designed for ).

Client controlled cars are Vehicles, AI controlled cars are directly set to a position based on an external simulation. But that simulation must be deterministic and independent of a client's actions or client side prediction breaks. Or, remove client side prediction entirely, run the simulation only on the server, and send corrections to clients for all objects.
#11
12/04/2009 (6:44 am)
Hi,

that sounds like a lot of work ;-)

I will read the papers over the weekend - thanks again!

The external simulation runs on a special external simulation system - it cannot be integrated into Torque.

I can calculate both positions and velocities (=moving directions) on the simulation system with a high rate.

So would you suggest to handle this like vehicles or AI cars? Note, that the movements are completely determined on the simulation system; Torque just acts as a "display". And I need to be able to place a camera on any car with a high frame rate and smooth movements.

When I only report moves (velocities), I need to be sure that the cars don't drift away over time, i.e. from time to time the positions should be corrected!

My preferred concept: Is there a possibility to send positions for all cars to the server, and to perform interpolations locally on the clients? That means that positions, not moves are sent from the server to the clients. Would this be an elegant solution?
#12
12/04/2009 (8:34 pm)
Ok if Torque is just acting as a renderer and the client is only a camera but not driving, then this should be much much easier.

The simulation only occurs on the server, all client-side cars are simple ghosts. That is, they just warp/interpolate over time to the last position reported by the server.