# Photon Sync issues

**URL:** https://discussions.unity.com/t/photon-sync-issues/1625198
**Category:** News & General Discussion
**Tags:** Game-Development, Question
**Created:** [April 3, 2025, 5:25pm UTC](https://discussions.unity.com/t/photon-sync-issues/1625198 "2025-04-03T17:25:35Z")
**Posts on this page:** 2
**Page:** 1

<div class="post-metadata">

### Author: ![mansikkajaakko13](https://avatars.discourse-cdn.com/v4/letter/m/ecb155/32.png) [@mansikkajaakko13](https://discussions.unity.com/u/mansikkajaakko13)
#### Post date: [April 3, 2025, 5:25pm UTC](https://discussions.unity.com/t/photon-sync-issues/1625198/1 "2025-04-03T17:25:35Z")

</div>

Im using photon for my multiplayer game and for some reason PlayerA’s movement is synced nicely on playerB’s screen but not the other way around. When playerB moves the updated position from playerA’s perspective is very slow(both are using the same player prefab).

 ![image](https://europe1.discourse-cdn.com/unity/original/4X/6/a/6/6a6931d957d32ddd417dbe1abe587adb0d661e2b.png)

```auto
using UnityEngine;
using Photon.Pun;

public class PlayerMovement : MonoBehaviourPun
{
    private Camera playerCamera;
    private Rigidbody playerRigidBody;

    private float mouseSensitivity = 2f;

    [Header("Camera")]
    public float cameraPitch = 0f;
    public const float maxCameraPitch = 45f;
    public const float minCameraPitch = -45f;
    public float cameraYaw = 0f;
    public const float maxCameraYaw = 90f;
    public const float minCameraYaw = -90f;
    private float initialYaw;

    [Header("Movement")]
    public float mouseX;
    public float mouseY;
    public float moveX;
    public float moveY;
    [Space]
    public float moveSpeed = 5f;
    public bool isMoving;

    [SerializeField] private Transform headTransform;
    [SerializeField] private Transform bodyTransform;

    [SerializeField] private Transform playerTransform;

    private Vector3 lastCameraRotation;

    private void Awake()
    {
        PhotonNetwork.SendRate = 30;
        PhotonNetwork.SerializationRate = 30;
    }

    private void Start()
    {
        if (photonView.IsMine) 
        {
            playerCamera = Camera.main;
        }        
        playerRigidBody = GetComponent<Rigidbody>();
        //lastCameraRotation = playerCamera.transform.rotation.eulerAngles;
    }

    float t = 0f;
    private void Update()
    {
        if (!photonView.IsMine) { return; }

            MouseInput();
            CameraMovement();
            RotateBody();
            MovePlayer();

        t += Time.deltaTime;

        if(t >= 0.1) 
        {
            photonView.RPC("SyncRotationAndPosition", RpcTarget.All, transform.position, headTransform.rotation, bodyTransform.rotation);
            t = 0;
        }        
    }
    private void LateUpdate()
    {

    }

    private void MouseInput()
    {
        mouseX = Input.GetAxisRaw("Mouse X") * mouseSensitivity;
        mouseY = Input.GetAxisRaw("Mouse Y") * mouseSensitivity;
    }

    private void CameraMovement()
    {
        //playerCamera.transform.position = headTransform.transform.position + new Vector3(0f, 0, 0.5f);
        playerCamera.transform.position = headTransform.GetComponent<Renderer>().bounds.center;

        cameraPitch -= mouseY;
        cameraPitch = Mathf.Clamp(cameraPitch, minCameraPitch, maxCameraPitch);
        cameraYaw += mouseX;

        //Debug.Log("Pitch: " + cameraPitch + " || " + "Yaw: " + cameraYaw);

        playerCamera.transform.localRotation = Quaternion.Euler(cameraPitch, cameraYaw, 0f);
        headTransform.transform.rotation = playerCamera.transform.localRotation;
    }
    
    private void RotateBody()
    {

        Debug.DrawLine(headTransform.position, headTransform.position + headTransform.forward * 2f, Color.red, 0.01f);
        Debug.DrawLine(bodyTransform.position, bodyTransform.position + bodyTransform.forward * 2f, Color.blue, 0.01f);

        Debug.Log(headTransform.rotation.y);

        Quaternion targetRotation = Quaternion.Euler(0, headTransform.eulerAngles.y, 0);
        bodyTransform.rotation = Quaternion.Lerp(bodyTransform.rotation, targetRotation, Time.deltaTime * 2f);

        if (isMoving) 
        {
            //bodyTransform.rotation = Quaternion.Euler(0, headTransform.eulerAngles.y, 0);
            bodyTransform.rotation = Quaternion.RotateTowards(bodyTransform.rotation, targetRotation, 1f);
        }
        /*
        Vector3 currentCameraRotation = playerCamera.transform.rotation.eulerAngles;

        if (isMoving)
        {

            if (initialYaw == 0f)
            {
                initialYaw = headTransform.rotation.eulerAngles.y;
            }            

            float targetYaw = headTransform.rotation.eulerAngles.y - initialYaw; // Reset yaw offset based on initialYaw
            Quaternion targetRotation = Quaternion.Euler(0f, targetYaw, 0f);

            // Rotate the body smoothly towards the target yaw
            bodyTransform.rotation = Quaternion.RotateTowards(bodyTransform.rotation, targetRotation, 2.5f);
        }
        if (currentCameraRotation != lastCameraRotation)
        {
            // Rotate the body (the player) to match the camera's yaw (horizontal rotation)+

            // Apply rotation to the body (player) based on yaw
            
            float deltaYaw = cameraYaw - lastCameraRotation.y; // Get the difference in yaw from last frame
            if (cameraYaw > 45 || cameraYaw < -45)
            {
                bodyTransform.transform.Rotate(0f, deltaYaw, 0f); // Rotate the body on the Y-axis based on the yaw difference
            }
            

            // Update the last rotation to the current one
            lastCameraRotation = currentCameraRotation;
        }
        */
    }

    private Vector3 moveDirection;
    private void MovePlayer()
    {
        moveX = Input.GetAxisRaw("Horizontal");
        moveY = Input.GetAxisRaw("Vertical");
        // Get input for horizontal and vertical movement

        // Calculate the movement direction based on the headTransform's forward and right vectors
        moveDirection = (headTransform.right * moveX + headTransform.forward * moveY).normalized;

        // Set the velocity of the Rigidbody based on the move direction
        playerRigidBody.linearVelocity = new Vector3(moveDirection.x * moveSpeed, playerRigidBody.linearVelocity.y, moveDirection.z * moveSpeed);

        if (playerRigidBody.linearVelocity.magnitude >= 0.1f)
        {
            isMoving = true;
        }
        else
        {
            isMoving = false;
            //lastCameraRotation = playerCamera.transform.rotation.eulerAngles;
            //initialYaw = headTransform.rotation.eulerAngles.y;
        }
        //Debug.Log("X: " + moveX + " || " + "Y: " + moveY);
        if (photonView.IsMine) 
        {
            photonView.RPC("SyncRotationAndPosition", RpcTarget.All, transform.position, headTransform.rotation, bodyTransform.rotation);
        }
    }

    private float lerpSpeed = 5f;

    [PunRPC]
    void SyncRotationAndPosition(Vector3 position, Quaternion headRot, Quaternion bodyRot) 
    {
        transform.position = Vector3.Lerp(transform.position, position, Time.deltaTime * lerpSpeed);
        headTransform.rotation = Quaternion.Slerp(headTransform.rotation, headRot, Time.deltaTime * lerpSpeed);
        bodyTransform.rotation = Quaternion.Slerp(bodyTransform.rotation, bodyRot, Time.deltaTime * lerpSpeed);

        Debug.Log("Sync update: " + position + " " + headRot + " " + bodyRot);
    }
}

```

---

<div class="post-metadata">

### Author: ![tobiass](https://dub1.discourse-cdn.com/unity/user_avatar/discussions.unity.com/tobiass/32/101811_2.png) [@tobiass](https://discussions.unity.com/u/tobiass)
#### Post date: [April 7, 2025, 9:21am UTC](https://discussions.unity.com/t/photon-sync-issues/1625198/2 "2025-04-07T09:21:11Z")

</div>

Do you get your log “Sync update”?

Why do you use an RPC for this? This is ineffective, even by PUN standards.  
You should implement IPunObservable.

Or rather, [have a look at the PUN Basics Tutorial](https://doc.photonengine.com/pun/current/demos-and-tutorials/pun-basics-tutorial). It covers this and more.
