public void NetworkSpawnPlayer(MyPlayerController spawnedPlayer, int spawnedPlayerId, int playerConnectionId)
        {
            // Player spawn msg
            SpawnPlayerMsg spm = new SpawnPlayerMsg();

            spm.PlayerId = spawnedPlayerId;
            if (playerConnectionId >= 0)
            {
                // For that player's connection, spawn as local player
                spm.IsLocalPlayer = true;
                spm.Serialize(GameStatics.OnlineSession.NetBuffer);
                GameStatics.OnlineSession.SendBufferToConnection(playerConnectionId, OnlineSession.ReliableSequencedChannelId);

                // Otherwise, spawn as not local
                spm.IsLocalPlayer = false;
                spm.Serialize(GameStatics.OnlineSession.NetBuffer);
                GameStatics.OnlineSession.SendBufferToAllClientsExcept(playerConnectionId, OnlineSession.ReliableSequencedChannelId);
            }
            else
            {
                // Server's player
                spm.IsLocalPlayer = false;
                spm.Serialize(GameStatics.OnlineSession.NetBuffer);
                GameStatics.OnlineSession.SendBufferToAllClients(OnlineSession.ReliableSequencedChannelId);
            }
        }
        public void OnDisconnect(int connectionId)
        {
            if (GameStatics.OnlineSession.Mode == OnlineSessionMode.Server)
            {
                for (int i = ConnectionInfos.Count - 1; i >= 0; i--)
                {
                    if (ConnectionInfos[i].ConnectionId == connectionId)
                    {
                        // Unregister and Destroy associated players and characters
                        foreach (int playerId in ConnectionInfos[i].PlayerControllerIds)
                        {
                            MyPlayerController p = SimulationSystem.GetPlayerControllerWithId(playerId);
                            if (p != null)
                            {
                                KinematicCharacterSubsystem.UnregisterCharacter(p.Character.GetId());
                                Destroy(p.Character.gameObject);

                                SimulationSystem.UnregisterPlayerController(p.GetId());
                                Destroy(p.gameObject);
                            }
                        }

                        // Remove connection info
                        ConnectionInfos.RemoveAt(i);
                        break;
                    }
                }
            }
            else if (GameStatics.OnlineSession.Mode == OnlineSessionMode.Client)
            {
                SceneManager.LoadScene(GameStatics.GameData.LobbySceneName);
            }
        }
        public void HandleSpawnPlayerMsg(ref SpawnPlayerMsg msg, int connectionId)
        {
            if (GameStatics.OnlineSession.Mode == OnlineSessionMode.Client)
            {
                MyPlayerController spawnedPlayer = Instantiate(GameStatics.GameData.PlayerPrefab);
                SimulationSystem.RegisterPlayerControllerAtId(spawnedPlayer, msg.PlayerId, msg.IsLocalPlayer ? -1 : connectionId);

                // Handle local player camera
                if (msg.IsLocalPlayer)
                {
                    spawnedPlayer.OrbitCamera = Instantiate <OrbitCamera>(GameStatics.GameData.CameraPrefab);
                    spawnedPlayer.OrbitCamera.gameObject.tag = "MainCamera";
                }
            }
        }
        private void OnReadyToInitiateGame()
        {
            int characterCounter = 0;

            // Create and spawn local players & characters
            {
                // Player controller
                MyPlayerController newPlayer = Instantiate(GameStatics.GameData.PlayerPrefab);
                newPlayer.OrbitCamera = Instantiate <OrbitCamera>(GameStatics.GameData.CameraPrefab);
                SimulationSystem.RegisterPlayerController(newPlayer, -1);
                if (GameStatics.OnlineSession.IsOnline())
                {
                    NetworkSpawnPlayer(newPlayer, newPlayer.GetId(), -1);
                }

                // Character
                MyCharacterController newCharacter = Instantiate(GameStatics.GameData.CharacterPrefab);
                newPlayer.OrbitCamera.SetFollowTransform(newCharacter.CameraFollowPoint);
                newPlayer.OrbitCamera.IgnoredColliders = newCharacter.GetComponentsInChildren <Collider>();
                PlaceCharacterAtSpawnPointIndex(newCharacter, characterCounter);
                KinematicCharacterSubsystem.RegisterCharacter(newCharacter, true);
                if (GameStatics.OnlineSession.IsOnline())
                {
                    NetworkSpawnCharacter(newCharacter, newCharacter.GetId(), newPlayer.GetId());
                }

                // Assign character to player
                newPlayer.Character       = newCharacter;
                newCharacter.OwningPlayer = newPlayer;

                characterCounter++;
            }

            // Create and spawn client players & characters
            foreach (ConnectionInfo ci in ConnectionInfos)
            {
                // Player controller
                MyPlayerController newPlayer = Instantiate(GameStatics.GameData.PlayerPrefab);
                SimulationSystem.RegisterPlayerController(newPlayer, ci.ConnectionId);
                if (GameStatics.OnlineSession.IsOnline())
                {
                    NetworkSpawnPlayer(newPlayer, newPlayer.GetId(), ci.ConnectionId);
                }

                // Register as player for that connection
                ci.PlayerControllerIds.Add(newPlayer.GetId());

                // Character
                MyCharacterController newCharacter = Instantiate(GameStatics.GameData.CharacterPrefab);
                PlaceCharacterAtSpawnPointIndex(newCharacter, characterCounter);
                KinematicCharacterSubsystem.RegisterCharacter(newCharacter, false);
                if (GameStatics.OnlineSession.IsOnline())
                {
                    NetworkSpawnCharacter(newCharacter, newCharacter.GetId(), newPlayer.GetId());
                }

                // Assign character to player
                newPlayer.Character       = newCharacter;
                newCharacter.OwningPlayer = newPlayer;

                characterCounter++;
            }

            // Tell clients to initiate game
            if (GameStatics.OnlineSession.IsOnline())
            {
                SimpleEventMsg sem = new SimpleEventMsg();
                sem.Event = SimpleEventMsg.EventType.InitiateGame;
                sem.Serialize(GameStatics.OnlineSession.NetBuffer);
                GameStatics.OnlineSession.SendBufferToAllClients(OnlineSession.ReliableSequencedChannelId);
            }
        }