호스트와의 연결이 끊길경우, 호스트가 서버를 종료했을경우 클라이언트 플레이어가 로비로 돌아오도록 수정해주었습니다.
public class NetworkConnectController : MonoBehaviour
{
public NetworkObject networkGameManager;
private void Awake()
{
if (NetworkManager.Singleton.IsHost)
{
NetworkObject netGameManager = Instantiate(networkGameManager);
netGameManager.Spawn(true);
}
}
//게스트 플레이어의 경우, 서버와 연결이 끊어졌을때 이벤트를 받아서 연결 종료
private void Start()
{
if (NetworkManager.Singleton.IsHost) return;
NetworkManager.Singleton.OnClientDisconnectCallback += ClientDisconnetCallback;
}
//서버를 종료시 해야하는 작업들
public void DisconnetServer()
{
Destroy(NetworkManager.Singleton.gameObject);
VivoxController.Instance.LeaveVoiceChannel();
NetworkSceneChanger.Instance.ChangeScene("TestScene_SBH");
}
//호스트가 서버를 종료하는 메서드
public void ShutDownButton()
{
if (!NetworkManager.Singleton.IsHost) return;
ClientDisconneted();
NetworkManager.Singleton.Shutdown(true);
DisconnetServer();
}
//클라이언트 연결 해제
public void ClientDisconneted()
{
for(int i = 0; i < NetworkManager.Singleton.ConnectedClientsList.Count; i++)
{
ulong id = NetworkManager.Singleton.ConnectedClientsIds[i];
if (id == NetworkManager.Singleton.GetComponent<UnityTransport>().ServerClientId) continue;
NetworkManager.Singleton.GetComponent<UnityTransport>().DisconnectRemoteClient(id);
}
}
//연결이 끊겼을때 호출되는 메서드
public void ClientDisconnetCallback(ulong id)
{
DisconnetServer();
}
}
클라이언트 플레이어는 OnClientDisconnectCallback 이벤트가 발생하면 의도적이든 의도적이지 않든 호스트로부터 연결이 끊어졌다고 처리하여 서버에서 나가게 됩니다
※ Vivox 관련 내용은 현재 수정이 더 필요한 상태입니다.
호스트 플레이어의 경우, 연결 종료를 시도하는 메서드를 임시로 만들어주었으며, 연결종료를 시도하면 모든 클라이언트와의 연결을 끊은 뒤 서버를 종료하게 됩니다.
추가적으로, 게임이 시작되면 무작위로 역할을 부여하도록 만들어주었습니다.
public class NetworkGameManager : NetworkBehaviour
{
private NetworkManager networkManager;
private UnityTransport transport;
private int isHostProfessor = -1;
public ulong ProfessorId { get; private set; }
public ulong StudentId { get; private set; }
private void Start()
{
networkManager = NetworkManager.Singleton;
transport = networkManager.GetComponent<UnityTransport>();
RoleDicider();
//SetPlayerRole();
Debug.Log(isHostProfessor);
}
private void RoleDicider()
{
if (!IsHost) return;
ulong clientId = 0;
for(int i = 0; i < networkManager.ConnectedClientsList.Count; i++)
{
if (networkManager.ConnectedClientsIds[i] == transport.ServerClientId) continue;
clientId = networkManager.ConnectedClientsIds[i];
}
int random = Random.Range(0, 2);
if(random == 0)
{
isHostProfessor = 0;
ProfessorId = transport.ServerClientId;
StudentId = clientId;
}
else
{
isHostProfessor = 1;
ProfessorId = clientId;
StudentId = transport.ServerClientId;
}
SetPlayerClientRpc(isHostProfessor);
}
[ClientRpc]
private void SetPlayerClientRpc(int index)
{
isHostProfessor = index;
SetPlayerRole();
}
private void SetPlayerRole()
{
if (networkManager.IsHost) return;
if(isHostProfessor == 0)
{
ProfessorId = transport.ServerClientId;
StudentId = networkManager.LocalClientId;
}
else if (isHostProfessor == 1)
{
ProfessorId = networkManager.LocalClientId;
StudentId = transport.ServerClientId;
}
else
{
Debug.Log("실패");
}
}
}
트러블슈팅
- 로비씬으로 돌아온 후, 다시 로비를 만들고 게임을 시작할경우 게임이 시작되지 않는 문제
로비를 관리하는 LobbyManager는 씬을 넘어가지 않고, Vivox 를 관리하는 VivoxController는 씬을 넘어가는 상태였습니다.
이때, VivoxController에서 LobbyManager 의 이벤트인 OnGameStartEvent 에 구독해둔것이 사라지게되었고, 이벤트에 등록된 메서드가 작동하지 않으면서 게임 시작이 되지 않는 문제가 발생하였습니다.
//LobbyManager
//싱글톤, 해당 오브젝트가 씬을 넘어가지 않도록 재정의
protected async override void Awake()
{
Create();
if (Instance != this)
{
Destroy(gameObject);
}
await UnityServices.InitializeAsync();
}
private void Start()
{
VivoxController.Instance.OnVivoxLoginEvent += ChangeGameScene;
VivoxController.Instance.SetupGameStartEvent();
if(AuthenticationService.Instance.IsSignedIn)
{
playerName = AuthenticationService.Instance.Profile;
}
}
LobbyManager의 Start에서 VivoxController에서 이벤트를 구독하는 메서드를 만들어 호출하는 방식으로 문제를 해결하였습니다.
//VivoxController
private async void Start()
{
await VivoxService.Instance.InitializeAsync();
}
public async void SetupVivox()
{
if (!VivoxService.Instance.IsLoggedIn)
{
await LoginVivoxAsync();
}
OnVivoxLoginEvent?.Invoke();
}
public void SetupGameStartEvent()
{
LobbyManager.Instance.OnGameStartEvent += SetupVivox;
}
또한, 게임을 재시작할때, 이미 Vivox에 로그인되있는상태이므로, 로그인되있는상태면 로그인 과정을 건너뛰도록 수정해주었습니다.
※ 유니티 서비스에 익명 인증을 하는 시점에 Vivox에 로그인하는것이 좋을수도 있다고 생각하고 있습니다.
또한 이러한 오류가 발생하였는데
Cannot start Host while an instance is already running
로비씬으로 돌아오면서 NetworkManager가 복사되었고, 이 NetworkManager에서 호스팅을 끝내지 않은 상태여서 발생하는 문제였습니다.
일단 게임 종료시 네트워크매니저가 붙은 게임오브젝트를 삭제함으로써 해결해주었습니다.
//서버를 종료시 해야하는 작업들
public void DisconnetServer()
{
Destroy(NetworkManager.Singleton.gameObject);
VivoxController.Instance.LeaveVoiceChannel();
NetworkSceneChanger.Instance.ChangeScene("TestScene_SBH");
}
이 외에도 NetworkObject 와 Rpc 관련 내용이 있습니다. 이 내용은 따로 정리해두었습니다.
수정하지 못한 내용
재입장시, 이전 게임에서 사용한 vivox 관련 UI들이 남아있는 현상이 발견되었습니다.
아직 해결책을 못찾았으며, 일단 플레이가 멈추지는 않기 때문에 먼저 멀티플레이 진행 내용을 제작한 뒤 수정할 예정입니다.
'내일배움캠프 > 프로젝트' 카테고리의 다른 글
팀 프로젝트 - 리팩토링 대상 정리 (0) | 2024.12.05 |
---|---|
팀 프로젝트 진행 - 멀티플레이 구현 (0) | 2024.12.04 |
팀 프로젝트 - Vivox 조작 UI 제작 (0) | 2024.12.02 |
팀프로젝트 - 프로토타입 로비 완성, Vivox 연동 시작 (0) | 2024.11.29 |
팀 프로젝트 진행 - 프로토타입 로비 제작 (3) | 2024.11.28 |