내일배움캠프/프로젝트

팀 프로젝트 - 게임 오버 메커니즘

서보훈 2024. 12. 24. 20:54

게임 플레이가 종료되어 멀티플레이를 끝내는 메커니즘을 제작중에 있습니다.

 

GameManager에서 게임오버 메서드가 호출되면 게임을 종료할 수 있도록 제작중에 있으며 게임 결과를 보여주는 UI를 활성화 시켜줄 계획입니다.

public bool IsGameover { get; private set; } = false;

public void Gameover(ResultType resultType)
{
    Debug.Log("게임 종료 요청");
    IsGameover = true;
    NetworkConnectController.Instance.ExitVivoxChennel();
    NetworkSceneChanger.Instance.ChangeScene("LobbyScene");

    resultUi = UIManager.Instance.CreateUI<GameResultUI>();
    resultUi.SetResultText(resultType);
    resultUi.Show();

    Cursor.lockState = CursorLockMode.None;
    Cursor.visible = true;
}

//연결이 끊겼을때 작동되는 결과 UI
public void DisconnectError()
{
    NetworkConnectController.Instance.ExitVivoxChennel();

    resultUi.SetResultText(ResultType.Error);
    resultUi.Show();

    Cursor.lockState = CursorLockMode.None;
    Cursor.visible = true;
}

또한, 게임매니저에 IsGameover 속성을 사용하여 만약 게임이 정상적으로 종료되지 않는 상황일경우, 멀티플레이 연결이 끊긴것으로 간주하여 처리할 수 있도록 별도로 메서드를 만들어주었습니다.

 

 

게임 결과를 보여주는 UI 에 사용되는 스크립트 입니다.

열거형을 사용하여 게임의 결과를 선택하고, 해당 열거형에 맞는 내용을 보여줄 예정입니다.

public enum ResultType
{
    Escape,
    Dead,
    Error
}

public class GameResultUI : UIPopup
{
    public TextMeshProUGUI resultText;
    public TextMeshProUGUI descriptionText;
    public Button exitButton;

    private string escape = "Escape";
    private string dead = "Missing";
    private string disconnected = "Error";

    private string escapeDescription = "Escaped form a cursed place";
    private string deadDescription = "Couldn't come back to Lab";
    private string disconnectDescription = "Connection is lost";

    private void Awake()
    {
        exitButton.interactable = false;
    }

    private void Start()
    {
        canvas.sortingOrder = 1;
    }

    public void SetResultText(ResultType type)
    {
        switch(type)
        {
            case ResultType.Escape:
                resultText.text = escape;
                descriptionText.text = escapeDescription;
                break;

            case ResultType.Dead:
                resultText.text = dead;
                descriptionText.text = deadDescription;
                break;

            case ResultType.Error:
                resultText.text = disconnected;
                descriptionText.text = disconnectDescription;
                break;
        }
    }

    public void ExitButton()
    {
        Hide();
    }

    public void EnableExitButton()
    {
        exitButton.interactable = true;
    }
}

 

실제 게임을 종료할 때 호출될 Rpc 메서드 입니다.

ServerRpc를 통해 게임이 끝났다는것을 서버에 알리고, 서버는 해당 Rpc를 다시 ClientRpc 로 전달하여 실제 게임을 종료시키는 Gameover 메서드를 호출합니다.

[ServerRpc(RequireOwnership = false)]
private void SendGameResultServerRpc(int enumIndex)
{
    ReciveGameResultClientRpc(enumIndex);
}

[ClientRpc]
private void ReciveGameResultClientRpc(int enumIndex)
{
    ResultType type = (ResultType)enumIndex;
    GameManager.Instance.Gameover(type);
}

 


문제 상황

  • 게임을 종료한 뒤 다시 게임을 시작하면 이전 게임에 사용된 NetworkObject들이 남아있는 현상

→ 게임 종료 매커니즘을 만들면서 NetworkSceneManager 를 사용하지 않고, 플레이 씬에서 네트워크 연결을 종료한 뒤 개별적으로 씬을 넘어가도록 만들어준 결과 이러한 문제가 발생하였습니다.

NetworkSceneManager를 통하지 않고 씬을 변경할경우 NetworkObject 에 관한 처리가 진행되지 않아서 문제가 발생하게 된다고 합니다.

현재 게임 종료시 먼저 NetworkSceneManager를 통해 씬을 이동한 뒤, 결과 UI를 보여주며 연결을 끊을수 있도록 수정하고 있습니다.

 

  • 클라이언트측에서 로비씬을 불러오지 못하는 현상

→ NetworkSceneManager를 통해 씬 이동을 진행한 뒤, 씬이 로드되자 마자 연결 종료를 시도해서 이러한 문제가 발생하였습니다.

클라이언트 측에서 NetworkSceneManager 를 통해 다음 씬을 불러와야하는데, 씬을 불러오기 전에 연결이 끊기며 불러올 씬을 찾지 못하고 멈춰버리는 상태가 되었습니다.

 

  • 호스트 연결이 종료되지 않는 현상 - 진행중

→ 이전처럼 OnSynchronizeComplete 를 사용하여 씬 로드가 끝나면 연결을 끊도록 만들어 주려고 했으나, NetworkObject 관련 오류가 발생하며 해결하지 못하고 있는 상황입니다.

현재 해당 내용의 해결을 시도하는중입니다.

 

※ NetworkSceneManager 관련 : 일반 SceneManager를 통해서 로드한 씬이 있을경우, 해당 씬은 NetworkSceneManager를 통해서 언로드 할 수 없습니다.

이전 씬 로드시 이 문제로 NetworkSceneManager 를 통해 클라이언트의 씬을 언로드 할 수 없는 문제가 있는 부분을 SceneManager로 언로드 하는 방식으로 해결했습니다.

public void ChangeScene(string sceneName)
{
    //이전의 Active씬 언로드
    SceneManager.UnloadSceneAsync(currentScene);

    if (NetworkManager.Singleton.IsHost)
    {
        //호스트가 씬 변경후, 클라이언트와 씬을 동기화
        //NetworkManager.Singleton.SceneManager.ActiveSceneSynchronizationEnabled = true;
        NetworkManager.Singleton.SceneManager.SetClientSynchronizationMode(LoadSceneMode.Additive);
        NetworkManager.Singleton.SceneManager.LoadScene(sceneName, LoadSceneMode.Additive);
    }
}

이 부분이 문제가 되는것으로 추정됩니다.

게임 시작시 플레이 씬을 네트워크를 통해 로드한 뒤, 다시 개별적으로 언로드 하면서 발생한 문제로 생각됩니다.

 

현재로써는 결과를 보여주기위한 씬을 만들어준 뒤, 해당씬에서 연결을 끊고 개별 씬 매니저를 통해 로비로 돌아가는 방식시도해봐야할 듯 합니다.


게임 종료 매커니즘을 완성한 뒤, 연속 플레이에 문제가 없음을 확인하면 이후 퍼즐 성공, 실패에 관련된 Rpc 내용을 작업하고, 로비 UI를 새롭게 만들어줄 예정입니다.