호스트와 비 호스트 1:1 게임에서의 싱크 문제

저는 현재 자동으로 좌/우 움직이면서 벽에 닿으면 반대 방향으로 이동하고, 점프만 할 수 있는 게임을 개발 중입니다. 뒤끝매치 예제 게임 코드를 보고 학습 중입니다.

    public void SendDataToInGame<T>(T msg)
    {
        var byteArray = DataParser.DataToJsonData(msg);
        Backend.Match.SendDataToInGameRoom(byteArray);
    }

호스트와 비 호스트 모두 이 함수를 통해서 점프 패킷을 보냅니다.

public void OnReceive(MatchRelayEventArgs args)
   {
       if (args.BinaryUserData == null)
       {
           Debug.LogWarning(string.Format("빈 데이터가 브로드캐스팅 되었습니다.\n{0} - {1}", args.From, args.ErrInfo));
           // 데이터가 없으면 그냥 리턴
           return;
       }

       var msg = DataParser.ReadJsonData<Message>(args.BinaryUserData);
       if (msg == null) return;
       if (BackendMatchManager.Instance.IsHost() != true && args.From.SessionId == myPlayerIndex) return;
       if (players == null)
       {
           Debug.LogError("Players 정보가 존재하지 않습니다.");
           return;
       }

       switch (msg.type)
       {
           case Type.StartCount:
               var startCount = DataParser.ReadJsonData<StartCountMessage>(args.BinaryUserData);
               Debug.Log("wait second : " + startCount.time);
               //UIManager.Instance.SetStartCount(startCount.time);
               if (GameManager.Instance.CurrentGameState != GameState.MatchInGamePreLoad)
                   GameManager.Instance.ChangeState(GameState.MatchInGamePreLoad);
               break;
           case Type.RandomSeed:
               var seedMessage = DataParser.ReadJsonData<RandomSeedMessage>(args.BinaryUserData);
               //debug all
               Debug.Log("Random Seed Receive : " + seedMessage.seed);
               GameManager.Instance.MainRandomSeed = seedMessage.seed;
               break;
           case Type.GameStart:
               //UIManager.Instance.SetStartCount(0, false);
               GameManager.Instance.ChangeState(GameState.MatchInGame);
               break;
           case Type.GameEnd:
               var endMessage = DataParser.ReadJsonData<GameEndMessage>(args.BinaryUserData);
               SetGameRecord(endMessage.count, endMessage.sessionList);
               GameManager.Instance.ChangeState(GameState.MatchOver);
               break;

           case Type.Key:
               var keyMessage = DataParser.ReadJsonData<KeyMessage>(args.BinaryUserData);
               ProcessKeyEvent(args.From.SessionId, keyMessage);
               break;
           case Type.PlayerRocket:
               var rocketMessage = DataParser.ReadJsonData<PlayerRocketMessage>(args.BinaryUserData);
               ProcessPlayerData(rocketMessage);
               break;
           case Type.PlayerBreakBlock:
               var breakBlockMessage = DataParser.ReadJsonData<PlayerBreakBlockMessage>(args.BinaryUserData);
               ProcessPlayerData(breakBlockMessage);
               break;
           case Type.GameSync:
               var syncMessage = DataParser.ReadJsonData<GameSyncMessage>(args.BinaryUserData);
               ProcessSyncData(syncMessage);
               break;
           default:
               Debug.Log($"Unknown protocol type: {msg.type}");
               return;
       }
   }

   private void ProcessKeyEvent(SessionId index, KeyMessage keyMessage)
   {
       if (BackendMatchManager.Instance.IsHost() == false)
           //호스트만 수행
           return;
       
       var isJump = false;
       var isSpecialSkill = false;
       Vector3 playerPos = players[index].GetPosition();

       var keyData = keyMessage.keyData;

       if ((keyData & KeyEventCode.JUMP) == KeyEventCode.JUMP) isJump = true;

       if ((keyData & KeyEventCode.SPECIAL_SKILL) == KeyEventCode.SPECIAL_SKILL) isSpecialSkill = true;

       if (isJump) players[index].Jump();

       if (isSpecialSkill) players[index].SpecialSkill();
   }

현재 이 코드를 이용해서 통신 중입니다.
그리고 플레이어가 버튼을 눌러 점프하는 순간에

KeyMessage msg;
msg = new KeyMessage(KeyEventCode.JUMP, transform.position, 1f);

이 키 메시지를 보내게 됩니다.

그런데 문제는, 싱크가 살짝씩 안 맞는다는 점입니다.

이 영상을 보시면 이해가 쉬울 것 같습니다.
계속 점프하다 보면 서로 다른 곳에 가 있습니다.
점프를 했다는 정보만 보내기 때문에 rigidbody의 velocity나 기타 위치 값은 보내지 않는 것이 원인으로 보입니다.
이를 해결하기 위해서 무엇을 해야 할지 쉽게 알려주시면 감사하겠습니다.

안녕하세요, 개발자님.
뒤끝 매치는 메시지를 중계하는 릴레이 서버로서의 기능을 수행하며, 게임 로직에는 관여하지 않습니다.
이에, 게임 로직과 관련된 추가 처리는 지원하지 않는 점 양해 부탁드립니다.
네트워크 플레이 시, 메시지 전송에 따른 딜레이로 인해 실시간 게임의 경우 sync가 조금씩 어긋날 수 있습니다.
이 부분에 대한 보정은 개발사 측에서 직접 처리해 주셔야 하는 점 이용에 참고 부탁드리며,
원활한 게임 동기화를 위해 아래와 같은 방식을 구현하시길 권장드립니다.

  1. 특정 액션 발생 시뿐만 아니라, 주기적으로 상태를 전송하여 전체 상태를 동기화
  2. 이벤트 전송 시에도 발생 위치나 시간 등 동기화 관련 값을 함께 첨부하여 동일한 시점에 이벤트가 발생하도록 보정

감사합니다.