Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CmdTeleport causes desync when called after a scene is loaded and when called in Start methods #3894

Open
rdmullett opened this issue Aug 25, 2024 · 0 comments
Assignees

Comments

@rdmullett
Copy link

rdmullett commented Aug 25, 2024

Describe the bug
When teleporting using CmdTeleport() characters can end up out of sync between client/server in a scenario where the player is moving while the server/host is loading a scene. What appears to happen is that in the time between the server trying to change the scene and the client receiving that message the player is still able to move, and that can cause a desync if the player is set to DDOL, and then gets CmdTeleport() called on it right after scene change.

Initially, I was also teleporting characters on character selection, and was seeing behavior similar to that which is described previously in #3588.

For the Start() behavior the character is moved to a location that is exactly double what it is supposed to be.

  • Version 89.8.0
  • Character is supposed to be teleporting to 1.00/1.00, and instead on Server side is shown at 2.00/2.00.
  • This happens when a CmdTeleport() is called in OnStartAuthority()
  • Once the character is desynced it remains throughout the session
  • Not always reproducible. Sometimes the teleport goes to the correct location. Other times it goes to the "doubled" location

For the OnSceneLoaded behavior the character can end up desynced based on how much they were able to move in the time that the server was loading the scene. This is always reproducible for me.

How can we reproduce the issue, step by step:
For Start:

  • Calling the MoveToSpawnLocation() (below) within the OnStartAuthority() method sometimes caused the player to end up at "doubled" coordinates. (2, 2 instead of 1, 1)

For the desync when loading scenes:

  • Have a subscriber for the SceneManager.sceneLoaded trigger, that calls the MoveToSpawnLocation() (below) SceneManager.sceneLoaded += OnSceneLoaded;
  • Have a PlayerObjectController which is DDOL with DontDestroyOnLoad(this.gameObject);
  • With the code below in place on a PlayerObjectController, have a client move while the server loads a scene using ServerChangeScene(SceneName);
  • With the above steps this was always reproducible for me.
    private void OnEnable()
    {
        SceneManager.sceneLoaded += OnSceneLoaded;
    }

    private void OnSceneLoaded()
    {
        MoveToSpawnLocation()
    }

     public void MoveToSpawnLocation()
    {
        StartCoroutine(DelayedTeleport());
    }

    private IEnumerator DelayedTeleport()
    {
        while (!NetworkClient.ready)
        {
            inputManager.DisablePlayerInput();
            yield return null;
        }
        if (isOwned)
        {
            // Removed initial code I use to find the spawnpoint to make repro easier
            Vector3 pos = new Vector3(1, 1, 1);

            Debug.Log($"Teleporting to: {pos}");
            inputManager.EnablePlayerInput();
            networkTransform.CmdTeleport(pos);
        }
    }

Expected behavior
When calling a CmdTeleport() after a scene change when a character was able to move there should not be a resulting desync between the location that the player teleports to, and the location that the player ends up at.

Screenshots

These pictures are from when these two characters were desynced with some debug text showing their location (client/server). This was a more mild case, but in extreme examples characters were able to get desynced up to 10+ units away.

image
Screenshot 2024-08-24 223341

Desktop (please complete the following information):

  • OS: Windows
  • Build target: Standalone
  • Unity version: 2022.3.43f1
  • Mirror branch: 89.8.0

Additional context
The previous bug #3588 had me looking in what I believe is the correct place, and I did actually workaround it for now. Commenting out all of the code in ResetState() except for base.ResetState() in NetworkReliableTransform fixed the issue and it was no longer reproducible.

The note at the top says the following. This, along with the previous bug is what prompted me to try commenting it out.

    // reset state for next session.
    // do not ever call this during a session (i.e. after teleport).
    // calling this will break delta compression.

Indeed, once ResetState() in NetworkReliableTransform was only calling the base method I no longer saw the desync behavior on any scene changes when teleporting. I did not test whether this also resolved the desync when called from OnStartAuthority() because instead I simply Instantiated my player at the right location and stopped teleporting them.

For completeness, here is exactly what my ResetState() method looks like in NetworkReliableTransform, and I cannot reproduce it with this:

        public override void ResetState()
        {
            base.ResetState();

            // reset delta
            //lastSerializedPosition = Vector3Long.zero;
            //lastDeserializedPosition = Vector3Long.zero;

            //lastSerializedScale = Vector3Long.zero;
            //lastDeserializedScale = Vector3Long.zero;

            // reset 'last' for delta too
            //last = new TransformSnapshot(0, 0, Vector3.zero, Quaternion.identity, Vector3.zero);
        }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants
@rdmullett @MrGadget1024 @miwarnec and others