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 조건을 넣어서 다른 플레이어 화면에서는 내 닉네임이 여전히 검정색으로 보이도록 처리했다.