Search Unity

Third Party [PUN] Physics based car game

Discussion in 'Multiplayer' started by Ibzy, Jan 15, 2015.

  1. Ibzy

    Ibzy

    Joined:
    Sep 15, 2013
    Posts:
    112
    I'm having trouble with the syncronisation with PUN on my latest project. I have the connections sorted and have 2 players join a specified room no problem.

    When i play the game on one instance and watch from another, the car I am driving moves choppy and laggy in the observed screen. Not only this, but the position is very inaccurate - I drove and "near-missed" player 2, but according to player 2's screen, I crashed right into them!

    Is this a known issue, or am I maybe using the wrong solution for what I'm trying to accomplish?

    Cheers
     
  2. BFGames

    BFGames

    Joined:
    Oct 2, 2012
    Posts:
    1,543
    How do you interpolate/extrapolate positions and rotation? Always a good idea to post your code.
     
  3. Ibzy

    Ibzy

    Joined:
    Sep 15, 2013
    Posts:
    112
    Wasn't sure if it was simply a known issue or not - not that it's been requested though:

    I have a PlayerControl script as below:
    Code (CSharp):
    1.     void Start () {
    2.         if(photonView.isMine){
    3.             GetComponentInChildren<Camera> ().enabled = true;
    4.             GetComponentInChildren<AudioListener> ().enabled = true;
    5.             GetComponent<GunControl> ().enabled = true;
    6.             GetComponent<PlayerHUD> ().enabled = true;
    7.             GetComponent<CarControl> ().enabled = true;
    8.         }
    9.     }
    10.  
    11.     void Update(){
    12.         if(!photonView.isMine){
    13.             transform.position = Vector3.Lerp (transform.position, position, Time.deltaTime);
    14.             transform.localRotation = Quaternion.Lerp (transform.rotation, rotation, Time.deltaTime);
    15.         }
    16.     }
    17.  
    18.     void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info){
    19.         if(stream.isWriting){
    20.             stream.SendNext (transform.position);
    21.             stream.SendNext (transform.rotation);
    22.         } else {
    23.             position = (Vector3) stream.ReceiveNext ();
    24.             rotation = (Quaternion) stream.ReceiveNext ();
    25.         }
    26.     }
    And the CarControl script (only one of the above activated required for the movement):
    Code (CSharp):
    1.     void Start () {
    2.         car = GetComponent<Car> ();
    3.     }
    4.    
    5.     void Update () {
    6.         GetInput();
    7.     }
    8.  
    9.     void GetInput()
    10.     {
    11.         car.throttle = Input.GetAxis("Vertical");
    12.         car.steer = Input.GetAxis("Horizontal");
    13.     }
    But having just looked a little further, I have added the velocity to the stream and everything looks a lot more accurate.

    If there's anything else you can see that I'm doing wrong I would be grateful to hear it, but will run with this for now.

    Thanks!
     
  4. BFGames

    BFGames

    Joined:
    Oct 2, 2012
    Posts:
    1,543
    Yeah it is as i expected. This has nothing to do with PUN but networking in general.

    You are doing the most simple form of linear interpolation updating position and rotation at a constant speed (delta time). This will in most games always give chunky movement.

    Lets say you update it 20 times per second. If you always received all messages AND all messages came within the exact same interval AND you drive identical distances within sending messages then it would all be good. However that's sadly not how it works. In fast paced games you you most often use UDP, but UDP is not reliable so you will lose messages quite often.

    So lets say you get message A and moves the car there, but then message B is lost. Then you dont move (stand still) until you get C or D, but they are pretty far away so you jump "fast forward" but then E is lost and you stand still again waiting for F or G. This will give you chunky movement and look like a person driving a car for the first time :D Also you will often be out of sync a lot (you are always out of sync in networked games by the way).

    This is why you will try and predict positions as well as possible! This is NOT easy at all and it's where people new to networking games often gets stuck.

    For interpolation you can buffer a few messages before moving the car. Send position AND time-stamp. Because there might be lost messages in between, but when you got time between two buffer packages then you can correct speed and stuff like that. Also when you send time-stamp you know if its long time since you last received a message (caused by lag e.g), and what do you do then?

    With your current code you simply stand still waiting for new messages. Here you should look into extrapolation. With extrapolation you 'guess' into the future to predict where you might be. So if you send velocity as an example then you can move the car in that direction and then correct it when the next message comes if you guessed wrong! (hint: don't extrapolate forever, if you did not receive messages for a "very" long time then don't do anything)

    Hope this helped you into some of the mindset of how to deal with these problems. Sadly there is no easy solution to this problem no matter what networking you work with (as such).