[유니티] 승리 조건 체크

이현경·2026년 2월 19일

5주차에는 게임 룰 파트를 최종 마무리하기 위한 승리 조건 체크와 부가적으로 살인마의 네임택을 빨간색으로 바꾸는 것을 맡았다.

승리 조건 체크

승리 조건 체크 함수에서 누가 승리했는지를 편하게 구분하기 위해서 WhoWin이라는 enum을 추가하였다.

public enum WhoWin {None, SurvivorWin, KillerWin};

승리 조건 체크 함수

public WhoWin CheckWinCondition()
{
    // 생존자 승리: 게임 시작 다 지나면 or 살인마 검거
    // 살인마 승리: 생존자 전멸

    int survivorCount = 0;
    int killerCount = 0;

    foreach (Player p in PhotonNetwork.PlayerList)
    {
        object isDeadValue;
        if (p.CustomProperties.TryGetValue("IsDead", out isDeadValue))
        {
            if ((bool)isDeadValue == true) continue; // 죽었으면 카운트x
        }

        if (p.CustomProperties.TryGetValue("Job", out object jobObject))
        {
            string job = (string)jobObject;
            if (job == "Survivor") survivorCount++;
            else if (job == "Killer") killerCount++;
        }
    }

    if (survivorCount == 0) return WhoWin.KillerWin;
    if (killerCount == 0) return WhoWin.SurvivorWin;
    if (currentGameTime <= 0) return WhoWin.SurvivorWin;

    return WhoWin.None;
}

승리 조건 체크 후 게임 종료 결정

public void UpdatePlayLogic()
{
    if (PhotonNetwork.IsMasterClient)
    {
        currentGameTime -= Time.deltaTime;

        float timeElapsed = gameTime - currentGameTime;
        if (currentState == GameState.Playing_OnLight && timeElapsed >= blackoutDelay)
        {
            photonView.RPC("RPC_SetGameState", RpcTarget.All, GameState.Playing_OffLight, 0.0);
        }

        if (currentGameTime <= 0) currentGameTime = 0;

        WhoWin result = CheckWinCondition();
        if (result != WhoWin.None) // 게임 종료되었다면
        {
            Debug.Log($"[게임 종료] 승리: {result}");
            photonView.RPC("RPC_EndGame", RpcTarget.All, result);
        }
    }

    // 3. 투표 시작 요청(우선은 M키 누르면 시작되게)
    if (Input.GetKeyDown(KeyCode.M))
    {
        if (PhotonNetwork.IsMasterClient) StartMeeting();
        else photonView.RPC("RPC_RequestMeeting", RpcTarget.MasterClient);
    }
}

[PunRPC]
public void RPC_EndGame(WhoWin winner)
{
    currentState = GameState.Result;
    isGameStart = false; // 플레이어 움직임 봉쇄

    // 결과 텍스트 띄우기
    if (resultText != null)
    {
        resultText.gameObject.SetActive(true);
        if (winner == WhoWin.SurvivorWin) resultText.text = "SURVIVOR WIN!";
        else resultText.text = "KILLER WIN!";
    }        
}

위와 같이 코드 작성 후 테스트하니 게임이 시작하자마자 종료되는 현상이 발생했다. 아무래도 커스텀 프로퍼티로 직업을 체크하여 승리조건을 체크하는데, 직업이 커스텀 프로퍼티에 다 로딩되기 전 CheckWinCondition()을 바로 실행해버려서, 직업 로딩이 안된 플레이어들이 제대로 카운트가 안 된 것 같다.

그래서 아직 직업 로딩이 안 된 플레이어들을 따로 세주고 한 명이라도 로딩이 덜 되었다면 승리 체크를 하지 않도록 수정하였다.

public WhoWin CheckWinCondition()
{
    // 생존자 승리: 게임 시작 다 지나면 or 살인마 검거
    // 살인마 승리: 생존자 전멸

    int survivorCount = 0;
    int killerCount = 0;
    int notYetCnt = 0; // 직업 로딩 전 승리 조건 체크 시

    foreach (Player p in PhotonNetwork.PlayerList)
    {
        object isDeadValue;
        if (p.CustomProperties.TryGetValue("IsDead", out isDeadValue))
        {
            if ((bool)isDeadValue == true) continue; // 죽었으면 카운트x
        }

        if (p.CustomProperties.TryGetValue("Job", out object jobObject))
        {
            string job = (string)jobObject;
            if (job == "Survivor") survivorCount++;
            else if (job == "Killer") killerCount++;
        }
        else notYetCnt++;
    }

    if(notYetCnt>0) return WhoWin.None; // 아직 로딩 다 안 됐으면 승리 조건 체크x
    if (survivorCount == 0) return WhoWin.KillerWin;
    if (killerCount == 0) return WhoWin.SurvivorWin;
    if (currentGameTime <= 0) return WhoWin.SurvivorWin;

    return WhoWin.None;
}

살인마 빨간 네임택

킬러인 플레이어에겐 본인 네임택이 빨간색으로 보이도록 하였다.

void Start()
{
    // ...
    ApplyKillerNameRed(); // 시작할 때 직업이 있을 수 있으니 여기서도 체크
}

public override void OnPlayerPropertiesUpdate(Player targetPlayer, Hashtable changedProps)
{
    if (targetPlayer.ActorNumber == photonView.Owner.ActorNumber)
    {
        if (changedProps.ContainsKey("IsDead"))
        {
            CheckLifeStatus();
        }

        if (changedProps.ContainsKey("Job"))
        {
            ApplyKillerNameRed();
        }
    }
}

void ApplyKillerNameRed()
{
    object jobValue;
    if (photonView.Owner.CustomProperties.TryGetValue("Job", out jobValue))
    {
        string job = (string)jobValue;

        if (job == "Killer" && photonView.IsMine)
        {
            playerNameText.color = Color.red; // 킬러면 빨간색
        }
        else
        {
            playerNameText.color = Color.black; // 생존자면 검정색
        }
    }
}

photonView.IsMine 조건을 넣어서 다른 플레이어 화면에서는 내 닉네임이 여전히 검정색으로 보이도록 처리했다.

profile
커피 한 잔의 여유를 아는 품격있는 여자

0개의 댓글