Search Unity

Third Party Photon: Inaccurate && Jittery position Sync

Discussion in 'Multiplayer' started by CyberInteractiveLLC, Jun 15, 2018.

  1. CyberInteractiveLLC

    CyberInteractiveLLC

    Joined:
    May 23, 2017
    Posts:
    307
    Hi! First i'd like to say that i just started learning Photon and Multiplayer in general 2~3 days ago, and I ran across this problem, I will try to explain the best i can:

    Movement: Player Objects are always moving, they can slow down or Speed up but they will always be moving.

    Photon settings: Im using Photon Transform view with Photon view:


    Note that: when the player objects are not constantly moving (Moves forward only on player input, it's smooth and has accurate position)

    Video:
     
  2. LorisToia

    LorisToia

    Joined:
    Jan 21, 2021
    Posts:
    14
    Hi, I know it's a dead post, but I got this problem and I solved it myself.

    this script is to attach to the gameobject to move:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using Photon.Pun;
    4. using UnityEngine;
    5.  
    6. [RequireComponent(typeof(Rigidbody))]
    7. public class Car : MonoBehaviourPun, IPunObservable
    8. {
    9.     public float speed = 900f;
    10.     public float rotationSpeed = 100f;
    11.    
    12.     private Rigidbody _rigidbody;
    13.     private float _inputX;
    14.     private float _inputY;
    15.     private Vector3 _netPosition;
    16.     private Quaternion _netRotation;
    17.     private Vector3 _previousPos;
    18.    
    19.     private void Awake()
    20.     {
    21.         _rigidbody = gameObject.GetComponent<Rigidbody>();
    22.     }
    23.    
    24.     public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
    25.     {
    26.         if (stream.IsWriting)
    27.         {
    28.             stream.SendNext(_rigidbody.position);
    29.             stream.SendNext(_rigidbody.rotation);
    30.             stream.SendNext(_rigidbody.velocity);
    31.         }
    32.         else
    33.         {
    34.             _netPosition = (Vector3)stream.ReceiveNext();
    35.             _netRotation = (Quaternion)stream.ReceiveNext();
    36.             _rigidbody.velocity = (Vector3)stream.ReceiveNext();
    37.            
    38.             float lag = Mathf.Abs((float)(PhotonNetwork.Time - info.SentServerTime));
    39.             _netPosition += (_rigidbody.velocity * lag);
    40.             ShowInfo.Instance.text.text = lag.ToString();
    41.         }
    42.     }
    43.    
    44.     void FixedUpdate()
    45.     {
    46.         if (photonView.IsMine)
    47.         {
    48.             _inputY = Input.GetAxis("Vertical");
    49.             _inputX = Input.GetAxis("Horizontal");
    50.  
    51.             _rigidbody.AddForce(transform.forward * speed * _inputY * Time.deltaTime, ForceMode.Acceleration);
    52.             transform.Rotate(Vector3.up * rotationSpeed * _inputX * Time.deltaTime);
    53.         }
    54.         else
    55.         {
    56.             _rigidbody.position = Vector3.MoveTowards(_rigidbody.position, _netPosition, Time.fixedDeltaTime);
    57.             _rigidbody.rotation = Quaternion.RotateTowards(_rigidbody.rotation, _netRotation, Time.fixedDeltaTime * 100.0f);
    58.         }
    59.     }
    60. }
    61.  
    Remove from gameobject the Photon Transform View, because this script handles itself the sync
     
  3. Ziberian

    Ziberian

    Joined:
    Jan 9, 2018
    Posts:
    66
    Hello LorisToia, this solution looks perfect for me. My only question is, how do you decide the
    Code (CSharp):
    1. public float speed = 900f;
    2. public float rotationSpeed = 100f;
    because I added them and now my players are suddenly moving faster (which I assume it is from the high speed). For reference, this is how I calculate my movement and rotation:
    Code (CSharp):
    1. void Move()
    2. {
    3.     Vector2 moveInput = playerInput.actions["Move"].ReadValue<Vector2>();
    4.     Vector3 move = moveInput * movementSpeed;
    5.  
    6.     if(!groundCheck.isGrounded && !flightMode) move *= 0.1f;
    7.  
    8.     Vector3 forward = transform.forward;
    9.     Vector3 right = transform.right;
    10.  
    11.     rb.velocity += forward * move.y;
    12.     rb.velocity += right * move.x;
    13. }
    Code (CSharp):
    1. void MousePosition() // For the rotation of the player
    2. {
    3.     Vector2 mouseDelta = playerInput.actions["Mouse Delta"].ReadValue<Vector2>();
    4.     Vector2 rawFrameVelocity = Vector2.Scale(mouseDelta, Vector2.one * mouseSensitivity * 0.01f);
    5.     frameVelocity = Vector2.Lerp(frameVelocity, rawFrameVelocity, 1 / mouseSmoothing);
    6.     mouseVelocity += frameVelocity;
    7.     mouseVelocity.y = Mathf.Clamp(mouseVelocity.y, -90, 90);
    8.  
    9.     cameraTransform.localRotation = Quaternion.AngleAxis(-mouseVelocity.y, Vector3.right);
    10.     transform.localRotation = Quaternion.AngleAxis(mouseVelocity.x, Vector3.up);
    11. }
    Would my speed just be my
    movementSpeed
    variable since the
    moveInput
    is always 0 or 1. That sounds simple enough, but the movement felt jittery when I did that.

    What about the rotation? Would it be
    mouseSensitivity * 0.01f
    ?

    Also finally, when I "start" my game, I teleport all my players to a far position. I realized with this code players don't see each other once teleported. Should I add some sort of "teleport if distance is 3<" to this script?
     
    Last edited: Feb 20, 2022
  4. Ziberian

    Ziberian

    Joined:
    Jan 9, 2018
    Posts:
    66
    Okay I have been working on this for the past half hour and here are the things I have realized/changed:

    1. I don't care about the speed or the rotation part because it is just for moving your own character, I do that in another script anyways.

    2. The teleportation was fairly easy to implement:
    Code (CSharp):
    1. public bool teleportIfFar;
    2. public float teleportIfFarDistance;
    Code (CSharp):
    1. void FixedUpdate()
    2. {
    3.     if(photonView.IsMine) return; // Only for objects that are not yours
    4.  
    5.     _rigidbody.position = Vector3.MoveTowards(_rigidbody.position, _netPosition, Time.fixedDeltaTime);
    6.     _rigidbody.rotation = Quaternion.RotateTowards(_rigidbody.rotation, _netRotation, Time.fixedDeltaTime * 100.0f);
    7.  
    8.     if(Vector3.Distance(_rigidbody.position, _netPosition) > teleportIfFarDistance)
    9.     {
    10.         _rigidbody.position = _netPosition;
    11.     }
    12. }
    One thing to note is, when my rates are 30 for send, 10 for serialization it still feels a little laggy. So I use 30/30 but I know that is not very ideal, still looking for better "compensation" methods to make the movement smoother.

    EDIT: I actually fixed this issue syncing rigid bodies instead. The solution works perfectly for me, instead of writing a whole bunch I'll just link my video where I go over the changes.
     
    Last edited: Feb 21, 2022