Page 1 of 1

Freezing a character controller/body for individual updates

Posted: Sun Mar 31, 2013 3:06 pm
by Gregc91
Hi,

So I am implementing a client server networked fps and my solution for client side prediction involves freezing all other players while processing the current input on the server. I have it working so that players will not move during an update if I take these steps:

1. make entity kinematic
2. set entity velocities to 0
3. space update
4. make entity dynamic (uses saved local inverse inertia)
5. set velocities back to pre-freeze

However, I now need to implement objects on the server which can move the players during updates when there is no input, so simply freezing the player to update the space will no longer work. Using an elevator as an example, when the elevator updates but the characters body is kinematic, it will not be pushed up by the elevator but will instead begin to fall through it.

I thought a solution that would be simple given my current implementation would be to eliminate the kinematic and dynamic part, so that elevators can still move the object but the controller input should not be applied until required. If I do this however, the entity still moves

1. set entity linear velocity, rotational velocity to 0
2. space update
3. set velocity back to pre-freeze velocity

As well as this, I check in my CharacterController's IBeforeSolverUpdateable.Update(float dt) method whether or not the character should be frozen and this method does not get updated when it shouldn't. So my question is what could be causing an entity with a character controller attached to be moving, when I set the velocity to 0? Are there other updateables in the character controller code which need to be disabled for these updates? When the character is on normal ground I would like the update to happen as if the character was kinematic, but it still needs to be pushed by certain dynamic objects such as elevators.

PS. Is there a neater way to implement client side prediction and similar networked physics using BEPU? It essentially requires movement code for players to be processed independently of the world space with custom time deltas, so that the server can update each player the same way the client would have done. I am currently doing this by freezing the world and performing multiple space updates per frame, but this may cause efficiency problems as the number of players scales.

Thanks,

Greg

Re: Freezing a character controller/body for individual upda

Posted: Sun Mar 31, 2013 4:41 pm
by Norbo
So my question is what could be causing an entity with a character controller attached to be moving, when I set the velocity to 0? Are there other updateables in the character controller code which need to be disabled for these updates? When the character is on normal ground I would like the update to happen as if the character was kinematic, but it still needs to be pushed by certain dynamic objects such as elevators.
It depends on the kind of movement you're seeing.

One likely source is gravity. Even for objects which are not in the air at the time of the freeze, it may still have an effect. Anything on slopes could receive tiny contributions from gravity. Entities on truly flat ground should not change much, but there may still be extremely small epsilon-sized shifting. Disabling gravity would stop this, though care would be required to avoid inappropriate floating.

Another possibility is that the entity is in penetrating collision. For example, if a character just ran into the wall, the character may be penetrating 0.05 units into it. That's sufficient to cause a penetration correction impulse that will move the character a little.

You can temporarily disable this effect by setting CollisionResponseSettings.PenetrationRecoveryStiffness = 0. It defaults to 0.2f.

I don't have any ideas off the top of my head which would explain large movements other than floating objects affected by gravity. If the character's updateable and constraints are stopped from running completely, there is no other character-related system that would make it move.
PS. Is there a neater way to implement client side prediction and similar networked physics using BEPU? It essentially requires movement code for players to be processed independently of the world space with custom time deltas, so that the server can update each player the same way the client would have done. I am currently doing this by freezing the world and performing multiple space updates per frame, but this may cause efficiency problems as the number of players scales.
This sort of networking model necessarily introduces some grossness. The physical simulation is designed around one unified 'world,' while the networking model seeks to simulate individuals in isolation. Those two goals don't mesh cleanly; implementing such a networking model on a physical simulation comes down to mitigating the discontinuity. It cannot be totally eliminated.

In these situations, I usually recommend giving the client a bit more authority. Loosening server authority opens a lot of doors at the cost of 'trusting the enemy', but the tradeoff is often worth it for simplicity and elegance. This becomes more and more important as the simulation complexity (player count, physical object count) increases.

For example, in one prototype implementation, I gave the clients full authority over their own position and allowed them to take control over other objects that they interacted with, such as vehicles, supporting objects, or objects being held. There still existed a main server which did the heavy lifting for the whole simulation, though- it had the ability to sanity check client input by checking the state of its own simulation. If something was too incorrect, the server would not believe it. The result was a very smooth-feeling experience for the players thanks to the client authority, and the simulation scaled to many thousands of dynamic objects without difficulty.

The hacking issues can usually be mostly mitigated through serverside heuristics. Hackers will tend to take the route of least resistance anyway. A little effort spent on keeping players from simply teleporting themselves and issuing kill commands for the entire server is generally enough to make them focus on other vulnerabilities common to both a pure serverside authority game and a partial clientside authority game (e.g. the client).

Re: Freezing a character controller/body for individual upda

Posted: Sun Mar 31, 2013 5:51 pm
by Gregc91
Wow thanks for the detailed reply.

The character update happens on the server every few frames or so, and it occurs before the rest of the dynamic objects get updated, so I would have thought the initial character update would resolve all collisions and stop any further movement on the updates when it should be frozen, even on successive frames after this, until the next input comes in. So because of this, I don't think the entity is in penetrating collision, though I will investigate tonight. I am testing on a completely flat plane, so I also don't think gravity will be the problem. I can easily disable gravity since this would be no different to making the objects kinematic and will test results of this too.

The movement I am getting is non negligible even on a per frame basis, and it amounts to my character moving around 30% faster overall in the direction of travel. A simple example of what is going on over 3 frames on the server might look as follows:

Input received > process player for 100ms (by freezing the space and updating)
Freeze all players and update space for 33ms

No input received > ignore player movement
Freeze all players and update space for 33ms

No input received > ignore player movement
Freeze all players and update space for 33ms

If I make the players kinematic for the main space update in each frame, they will not move. What's happening now (without making kinematic) is that all of the main space updates are slightly moving the player in the direction of motion. Just to make sure, this is how I zero the velocity:
Body.LinearVelocity = Vector3.Zero;
There's no other forces or anything that I should be zeroing to stop movement? I have tried with and without buffered states just in case it used a buffered velocity but it seems to have no effect.
Norbo wrote: I don't have any ideas off the top of my head which would explain large movements other than floating objects affected by gravity. If the character's updateable and constraints are stopped from running completely, there is no other character-related system that would make it move.
The only method I stop running in the character controller is the IBeforeSolverUpdateable.Update(float dt) method. I thought this was the main movement method and I haven't really looked into the constraints and other support classes. Are there other updateables that would still run even if this update doesn't?

I have already began along the route to your suggested implementation by allowing all weapon firing and hit detection to be computed client side. It saves me having to predict it and means I don't need to perform lag compensation on the server hit tests, since client hit tests are already 100% accurate to what the client is seeing. When planning this project I did initially think of a model very similar to your suggested one where clients have authority over certain objects, but I couldn't see how clients would handle collision with each other, since old player locations would mean clients could walk to what they think is an empty space which may become occupied. A server model seemed to easily solve this since it is a singular simulation, but as you said the individual player simulations introduce discontinuity problems which I did not foresee. My simulation is quite simple, with few dynamic objects and so for now I will stick with a stronger authoritative server model, at least until I hit scaling limitations.

Re: Freezing a character controller/body for individual upda

Posted: Sun Mar 31, 2013 6:23 pm
by Norbo
Just to make sure, this is how I zero the velocity:
Body.LinearVelocity = Vector3.Zero;
There's no other forces or anything that I should be zeroing to stop movement? I have tried with and without buffered states just in case it used a buffered velocity but it seems to have no effect.
Setting that property is indeed sufficient to stop an entity's linear motion instantly. Entities with infinite inertia like the character body have no angular velocity, so halting the linear motion will stop the entity completely (until some other force is applied, of course).
The only method I stop running in the character controller is the IBeforeSolverUpdateable.Update(float dt) method. I thought this was the main movement method and I haven't really looked into the constraints and other support classes. Are there other updateables that would still run even if this update doesn't?
The IBeforeSolverUpdateable itself queries for support information and handles jumping, but it does not directly handle primary character movement. That's the job of the character's HorizontalMotionConstraint. If the CharacterController.HorizontalMotionConstraint is not told to stop trying to move, the character will keep scooting (and, because the CharacterController updateable is not updating, the HorizontalMotionConstraint is likely operating on out of date information).

You can set CharacterController.HorizontalMotionConstraint.IsActive = false to prevent it from solving.

There's also a VerticalMotionConstraint, though it is responsible for keeping characters stuck to the surface they're standing on. Keeping it enabled probably won't cause much a problem.

Re: Freezing a character controller/body for individual upda

Posted: Sun Mar 31, 2013 8:26 pm
by Gregc91
Thanks for the explanation, disabling the horizontal motion constraint fixes my problem. It obviously adds a small velocity to the already zeroed velocity to give me the slight movement I was seeing. I will need to keep the vertical constraint updating to allow the characters to be pushed up correctly during the update when an elevator moves, which is exactly what I was after!