Hello, I’ve been working with the GGPO prediction and rollback model with coherence. I’ve followed the example posted here: https://docs.coherence.io/v/0.8/authority/input-prediction-and-rollback
I’ve noticed some desync and set up the debugger. It looks like the first frame on each client is not the same. I believe this is what causing my issues.
Here is an example from the debug: The first Client detects the other player and starts the simulation at 86278258334
The second client gets both client joined messages, and logs its first frame as
86278258343
This is bad right? If clients don’t agree with what is happening on specific frames, I’d be rolling back to the wrong frame.
I posted a snippet of my input simulation script. I have more if need be
// called by BOTH clients when a client joins, creates a controller on each side for the new player
protected override void OnClientJoined(CoherenceClientConnection client)
{
SimulationEnabled = AllClients.Count == 2;
NetworkedController newController = client.GameObject.GetComponent<NetworkedController>();
newController.Initalized += BeginSimulation;
newController.PlayerID = AllClients.Count-1;
ServiceLocator.ControllerService.AddController(newController);
// if both clients have joined, the last joining client sends a random seed to both sides to use
/*if (AllClients.Count == 2 && coherenceBridge.ClientConnections.GetMine() == client)
{
Debug.Log("I'm player setting seed for both clients");
client.SendClientMessage<NetworkedController>("SetRandomSeed", Coherence.MessageTarget.All, Random.Range(0,1000));
}
*/
if(SimulationEnabled)
{
Random.InitState(0);
BeginSimulation();
}
}
// starts simulation, but only called after the local client has signaled that they have been initalized
// currently initalization is only used for sharing a seed. But for future reference this can be used to wait for character choice/stage choice etc.
public void BeginSimulation()
{
# if COHERENCE_INPUT_DEBUG
Debugger.FramesToKeep = 1000;
#endif
// Lets us rejoin the same simulation without restarting the app.
SimulationEnabled = true;
manager.StartRoundMultiplayer();
StateStore.Clear();
}
protected override void OnPauseChange(bool isPaused)
{
Debug.Log($"paused {isPaused}");
//PauseScreen.SetActive(isPaused);
}
I’ve been looking through the forums and documentation but have to get a clear answer. I hope this isn’t off-topic or has been answered already. Thank you!