Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Client prediction and Physics

Discussion in 'Multiplayer' started by teremy, Sep 8, 2015.

  1. teremy

    teremy

    Joined:
    May 2, 2015
    Posts:
    86
    Hello.

    For my online game I am using unity's physics engine for the character movement. Since it's not exactly a physics based game, I just instantly apply a constant velocity ( I may use more of the physics engine in the future and it is currently primarily used for collision detection ).
    My problem is, when the player sends a move command to the server, the server will eventually answer with a position, I want to predict this position, but I dont't know how todo that.
    I made games before and moved the player by "teleporting" him to a new position ( setting its position... ), then it's easy to also do this "teleporting" on the client as it sends the command, but with physics the problem is, that when I set velocity or addforce etc., then I have to wait for the next update for something to actually happen to the rigidbody.
    If I set the position, then the collision detection won't work correctly.
    I saw there is Rigidbody2D.MovePosition, but I don't know if this will do it ( will it teleport the player but also regard collision? how exactly is the collision solved? By comparing with the old position? ).

    It's a tile based game and maybe in the future I will have to write my own collision detection, but it would still be nice to know how the client can predict physics movement in online games. Also if the game is 3D, I'd rather use the physics collision detection ).

    Also I don't know how error correction ( which is essential ) is implemented for client prediction, but that's another topic.

    Thanks in advance for any ideas.
     
    noise256 likes this.
  2. noise256

    noise256

    Joined:
    Apr 7, 2013
    Posts:
    22
    Someone please correct me if I'm wrong but I think this will be very difficult to do using the Unity Rigidbody. It is however, possible to do using custom physics. The client side prediction methods that I know require replaying input/movements with respect to time. So for example, if your custom physics function does:

    position = position + velocity * deltaTime

    You would perform this on both the client and server, the server then sends back a position but because of latency the server will be behind the client. To reconcile the client with the server you need to set the client position to the position you get back from server (which will be in the past) and redo all movement that occurred on the client after the server update. If you're using Rigidbody then I'm not sure how you would go about replaying that movement.
     
    teremy likes this.
  3. teremy

    teremy

    Joined:
    May 2, 2015
    Posts:
    86
    What I've read this really is a very difficult topic. Since I am just using the physics engine for collision detection ( when I want to move my character, I just set his velocity, so he moves with a constant speed and stops instantly if I stop pressing any key).
    I think I will stop using the physics and move my player by setting a different transform.position. This is easy to predict.
    The only problem then is the collision, but since the game is tilebased I can manually check collision with the tiles that make sense ( if moving up for example I check with the top, the top left, and the top right tile, starting from the tile the player currently stands on ). In any case this is even more efficient, because there are many colliders on the map and this way collision is only checked with tiles that make sense. I can also check if a tile contains any gameobjects and then also check collision with them.
    Working with the overlap methods, boxcasts or using the isTouchin function will for sure do the trick.
    I could still use the physics for other objects, because I don't have to predict their movement, but for the player I think it is essential in multiplayer gaming to predict the movement to make things feel responsive, but I don't actually need that kind of physics for the player.

    The difficult part about client prediction is the error correction, but as I said, that's another topic, this time I just needed to know how I can predict the movement... and will use the approach described above.
     
  4. noise256

    noise256

    Joined:
    Apr 7, 2013
    Posts:
    22
    teremy likes this.
  5. teremy

    teremy

    Joined:
    May 2, 2015
    Posts:
    86
    Thanks, yep, I just deleted the Rigidbody but I can use the isTouching method etc. with the player's boxcollider and the boxcollider of the tiles.

    I downloaded the code by GenaSG and took a brief look into it. Looks great and I think I know now how to write the actual client prediction with error correction.
    It's basically keeping the input in a list and also sending a timestamp, so you know which command correlates with which answer of the server. Then you can use the answer of the server and redo the input that was done starting from the supplied timestamp (using the list of inputs). That's sort of how I would have done it anyway, though I was thinking of sequence numbers instead of timestamps, but I think timestamps are even better.
     
  6. Firoball

    Firoball

    Joined:
    Aug 6, 2015
    Posts:
    60
    Predicting physics movement which is not capable of rewinding and playback is very complicated (if possible at all) to do.

    I have heard of people breaking with the authoritative server concept, and have several physics stuff running on the clients - with a lot of cross checking for cheat protection on the server. It sounds ugly and complicated... ;)

    For my game in fact I kept a rigidbody with isKinematic checked attached to the player - only for still having trigger events. The movement itself I made very simple, purely speed based, because my acceleration calculations seemed to go wrong at some point and I don't really need it for a action game :)

    In case I'll have some physics objects later on, they will not have any client side prediction applied. The server will do the physics, the clients will get data for interpolation based on the server results. Not perfect, but good enough.
     
    teremy likes this.
  7. teremy

    teremy

    Joined:
    May 2, 2015
    Posts:
    86
    A problem I see now is that although my game is currently 2D, I think I want to make a 3D game in the future and using physics will help immensely with the movement, because if I want to move the player I can just add a force or set the velocity, but if the player moves over increasing ground then it's very difficult todo this with moving the player by setting a different position.
    Using the physics the player automatically moves along even if the floor is increasing or decreasing.
    Maybe predicting physics movement is hard, but the kind of movement I am doing shouldn't be that hard after all. I am not gradually increasing the players velocity or something, I set an instant velocity and stop instantly if I stop pressing the button. Take any online shooter for example, the only physics I need is the collision detection, because for example I want the user to move along slopes ( hope this is the right term ) and I can't really do that by just setting a new position. In Counter-Strike for example this sort of prediction is even done in CS 1.6 I think, but maybe the engine allows to "act out" physics without having to wait for another update.

    I also have some thoughts about error correction: One can of course store user input in a list with a timestamp and if the server sends a position ( also with a timestamp ) one can set the users position and redo all the input that's younger than the provided timestamp.
    I wonder if it's possible to just store a position ( the one you get after predicting a movement ) and a timestamp, then if you get a position by the server you can set the position provided by the server and translate the players position by the currently stored position ( newest timestamp/newest element in the list ) minus the position stored with the timestamp, that was also received with the position sent by the server. So basically correct the players position but adding the movement, the server hasn't said anything about yet. This of course may need some smoothing, but that's always needed.

    Btw. movement is the only thing I am predicting for my game, thankfully no lag compensation or anything is needed for my kind of game.
     
  8. Firoball

    Firoball

    Joined:
    Aug 6, 2015
    Posts:
    60
    My players are moved with CharacterController.Move(). It does the job well enough and can be used easily in conjunction with fixed delta time for several additive playbacks. Just what I need.

    About prediction concepts I tried several things with flexible framerate, dynamic this, dynamic that.... int he end I took a tutorial and did it as described there.
    - Fixed time steps
    - frame ids (or timestamps)
    - storing key input data for each prediction frame

    I'm not storing positions as it canlead to many errors if I just do some vector maths. All the playback of later snapshots then ignores any change in the world and any obstacles in the way due to a corrected position. It is better to have the actual movement code with slope detection, gliding, bouncing, blah running. Will deliver a much more reliable prediction than trying to simplfy this with some position vector math.
    Don't ask why I know this...
     
    teremy likes this.
  9. teremy

    teremy

    Joined:
    May 2, 2015
    Posts:
    86
    Thank you very much Firoball. The CharacterController was exactly what I need! Now I can move the player easily and still have collision detection etc., which is basically the description of the character controller:
    "A CharacterController allows you to easily do movement constrained by collisions without having to deal with a rigidbody."

    For predicting the movement I can now just use the Move method of the Character Controller.
    My game currently is 2D and the CharacterController can't be used with 2D Colliders, but I was already converting my game to 3D ( with topdown perspective ) and I just need to use 3D colliders instead.
    Also there is a CharacterController2D created by a user, that also works great ( I googled and found it ), though I will use the CharacterController provided by Unity now ( since I will make a 3D game now ).
    It's amazing, you can even set the slope limit ( the things I talked about in my previous post ).
    Makes me really happy now, since that's really exactly what I needed :).

    Now I will implement client prediction and everything will be awesome ^^.
    Thanks for your answers!