Odd behavior with Advance Tutorial Sample

I'm new to Bolt and using Unity 2018.3f2.

I imported the Bolt Free asset and built the advanced tutorial scenes. The game window running as the server behaves as expected, but in all of the client windows, the input commands appear to get processed multiple times causing the local player in the client to run at ~3x speed and jump higher than it should be able to. In the server instance (and for proxied players in other clients), the second player moves as expected. This causes the client instances to get way out of sync where they believe they have moved a great distance, but the server sees them as only moving a small amount.

Here's an example of the problem. Client 1 moved forward towards the server player. In Client 1's game, he moved rapidly towards the server all the way up to the server player. Client 2 and Server see him in the correct position, having only moved 20 feet forward.



Has anyone else seen this? How do I fix it?

Also, is there anything in Bolt that corrects out of sync locally controlled objects? i.e. Will the object get moved back towards it's "correct" position? ("Source Engine Multiplayer Networking" discusses correcting prediction errors)

Thanks for your time.

Comments

  • chrisrbs
    chrisrbs
    edited January 2019
    Edit: Ignore this comment.

    I did some digging and it's because ExecuteCommand is being called multiple times on the clients for the same BoltNetwork.Frame value.

    E.g. At frame 100, the player is at (0,0,0) and a forward command is queued. ExecuteCommand is called 5 times for frame 100 and the player moves to position (5,0,0). But on the server since it is the owner it is only moved to (1,0,0).

    I don't see anything in the Advanced Tutorial about verifying movements and ensuring a frame is only predicted once. Is this something we have to do manually?

    Thanks!
  • Executecommand is called multiple times every fixed update to reset to the nearest correction from the server then play the commands that aren't confirmed by the server yet. We can take a look and see if there's a new issue related to clients moving faster.
  • I encountered this problem in Unity 2018.3 too, but it is working fine in Unity 2018.2.
  • We are able to reproduce this issue, fix for 2018.3 will be released as soon as possible.
  • I didn't fully understand ExecuteCommand when I wrote the second comment, so what I said was incorrect. I've identified the issue, however.

    The issue is that, on a new frame, the CharacterController isn't respecting the updated position of the transform after it is set by PlayerMotor.SetState() on line 98.

    `transform.localPosition = _state.position;`

    Instead, it appears to be using the position it had, which was the position of the last client predicted command.

    Here is the flow:
    Player is not moving
    Player is 5 commands ahead of server
    Suppose the last command from server is #100
    On the client, the player moves forward for one command (#105) from x=0 to x=1
    When the client replays server frame #101, it's suppose to move back to x=0 in PlayerMotor.SetState(); however the character controller doesn't respect the change by line 98, so when the client replays command #101 that has no movement input, it's starting at x=1, applying the gravity vector to move down and ending at x=1 even though the correct position is x=0.
    Then, when command #105 is replayed, the player is moved to x=2.

    This snowballs, so when the server supplies #102 with x=0, the character controller still thinks it's at x=2, so #105 moves the player to x=3 and so on.

    I modified PlayerController.cs by adding logging statements to illustrate the problem here: https://gist.github.com/chrisrbs/21b75824acd678ac93342c6157c87862 If you replace PlayerController in the advanced tutorial with that code, and debug as the client you'll see the logs.

    A work around that I found for the tutorial code is the following:

    Replace line 98 in PlayerMotor with this: `_cc.Move(position - transform.localPosition);`

    Instead of moving the transform back to the correct starting position, use the Move command with the position delta so the CharacterController puts the transform back to the starting position.

    Am I adequately explaining the situation? My guess is that the implementation for CharacterController must have changed in the updates since the tutorial was written causing this issue.
  • Tykev said:

    We are able to reproduce this issue, fix for 2018.3 will be released as soon as possible.

    Appreciate it. Any idea what the ETA might be? Less than a week? Less than a month?
  • chrisrbs said:

    Tykev said:

    We are able to reproduce this issue, fix for 2018.3 will be released as soon as possible.

    Appreciate it. Any idea what the ETA might be? Less than a week? Less than a month?
    Your explanations was good, thanks. We stick with this solution in next release.