09/30 Photon PUN2 - 매치메이킹

댓글 0
댓글을 작성하려면 로그인이 필요합니다.
아직 댓글이 없습니다. 첫 번째 댓글을 작성해보세요.

댓글을 작성하려면 로그인이 필요합니다.
아직 댓글이 없습니다. 첫 번째 댓글을 작성해보세요.
PhotonLobbyManager는 MonoBehaviourPunCallbacks를 상속해 Photon의 결과와 상태 변경을 콜백으로 받는다. 이 코드의 기본 흐름은 마스터 서버 접속 → 로비 입장 → 방 목록 확인 또는 방 생성 → 방 입장 → 플레이어 상태 관리 → 방 퇴장이다. 방을 만드는 함수나 들어가는 함수를 호출한 순간에 작업이 완료되는 것은 아니다. 성공·실패 콜백에서 결과를 확인하고 화면을 갱신한다.
OnConnectedToMaster()는 접속 후 PhotonNetwork.JoinLobby()를 호출하고, OnJoinedLobby()는 로비 입장을 표시한다. 방 목록을 보기 위해 로비에 들어가는 것이며, 방 입장 자체가 항상 로비 입장을 요구하는 것은 아니다.
| 코드에서 호출하는 함수 | 역할과 이어지는 콜백 |
|---|---|
PhotonNetwork.CreateRoom("ComeOn", options) | MaxPlayers = 4인 ComeOn 방 생성을 요청한다. 성공하면 방에 입장하며 OnJoinedRoom()이 호출된다. 실패하면 OnCreateRoomFailed()가 호출된다. |
PhotonNetwork.JoinRoom("Come") | 이름이 Come인 방 입장을 요청한다. 성공하면 OnJoinedRoom(), 실패하면 OnJoinRoomFailed()가 호출된다. |
PhotonNetwork.JoinRoom(roomName) | 방 목록 버튼에서 선택한 방의 이름으로 입장을 요청한다. |
PhotonNetwork.LeaveRoom() | 현재 방에서 나가도록 요청한다. 완료되면 OnLeftRoom()이 호출된다. |
현재 직접 생성 버튼의 방 이름은 ComeOn이고 직접 입장 버튼의 이름은 Come이다. 따라서 생성 버튼으로 만든 방에 직접 입장 버튼으로 들어가려 하면 이름이 맞지 않아 실패할 수 있다. 반면 방 목록 버튼은 해당 RoomInfo.Name을 넘긴다. JoinRandomRoom(), JoinOrCreateRoom() 등의 호출은 이 스크립트에서 주석 처리되어 실행되지 않는다. OnJoinRandomFailed() 콜백은 구현되어 있지만 현재 실행 경로에서 무작위 입장을 요청하지 않는다.
OnCreateRoomFailed(short returnCode, string message)와 OnJoinRoomFailed(short returnCode, string message)는 실패 코드와 메시지를 로그로 남긴다. 방 이름 중복, 없는 방, 닫힌 방, 정원 초과처럼 요청이 거절될 수 있는 경우를 이해할 때 이 로그가 단서가 된다.
RoomButton로비에 있을 때 OnRoomListUpdate(List<RoomInfo> roomList)가 방 목록의 변경 사항을 전달한다. 전달된 목록을 매번 전체 목록으로 취급하지 않고, roomDic에 이름을 기준으로 추가·갱신한다. info.RemovedFromList가 참이면 해당 방을 사전에서 제거한다. 이후 RefreshRoomButtons()가 버튼들을 다시 만든다.
각 RoomButton은 RoomInfo의 방 이름, 현재 인원, 최대 인원, 열림 상태를 표시한다. info.IsOpen이 거짓이거나 방이 가득 차면 버튼을 누를 수 없게 한다. 버튼 클릭은 RoomButton.OnClick() → PhotonLobbyManager.JoinRoomByName(roomName) → PhotonNetwork.JoinRoom(roomName)으로 이어진다. RoomButton 자체는 Photon 콜백을 상속하지 않고 화면 표시와 클릭 전달만 맡는다.
로비를 나가거나 방에 입장하면 코드에서 ClearRoomList()로 저장한 목록과 버튼을 지운다. 방 안에 있는 동안에는 로비의 방 목록을 보여주지 않는다.
PhotonNetwork.InRoom은 현재 방에 있는지 확인하는 값이다. PhotonNetwork.CurrentRoom에서는 방 이름(Name), 현재 인원(PlayerCount), 최대 인원(MaxPlayers)을 읽어 방 정보를 표시한다. PhotonNetwork.PlayerList를 순회하면 각 플레이어의 번호(ActorNumber), 닉네임(NickName), 방장 여부(IsMasterClient)를 표시할 수 있다.
OnJoinedRoom()은 내가 방에 들어갔을 때 호출된다. 방을 직접 만든 경우에도 호출되며, 이 코드에서는 상태·플레이어 목록·방 정보를 갱신한다.OnPlayerEnteredRoom(Player newPlayer)와 OnPlayerLeftRoom(Player otherPlayer)는 다른 플레이어가 들어오거나 나갔을 때 호출된다. 이 코드에서는 방 인원과 플레이어 목록을 다시 표시한다.OnLeftRoom()은 내가 방을 나왔을 때 호출된다. 방 정보와 플레이어 목록을 No Room 상태로 갱신한다.준비 버튼을 누르면 OnClickReady()가 먼저 방에 있는지 확인한다. IsReady(PhotonNetwork.LocalPlayer)는 내 CustomProperties에서 "ready" 값을 읽는다. 아직 이 키가 없으면 false로 취급한다. 다음 코드는 현재 값을 반전해 저장한다.
HashTable props = new HashTable();
props["ready"] = !ready;
PhotonNetwork.LocalPlayer.SetCustomProperties(props);
여기서 HashTable은 ExitGames.Client.Photon.Hashtable의 별칭이다. props는 변경할 키와 값의 묶음이고, PhotonNetwork.LocalPlayer는 내 플레이어 객체다. SetCustomProperties()는 내 플레이어의 "ready" 속성 변경을 Photon에 요청한다. 준비 상태는 방 전체의 속성이 아니라 플레이어마다 가진 속성이다. 따라서 PhotonNetwork.CurrentRoom.SetCustomProperties()나 OnRoomPropertiesUpdate()가 아니라 플레이어 속성 변경 흐름을 사용한다.
변경 내용이 동기화되면 OnPlayerPropertiesUpdate(Player targetPlayer, HashTable changedProps)가 호출된다. 이 코드에서는 RefreshPlayerList()를 실행하고, 각 플레이어의 ready가 참이면 이름 옆에 [Ready]를 표시한다. 온라인 방에서는 속성 변경 요청 직후 로컬 값이 즉시 바뀌었다고 가정하지 않고 콜백을 통해 갱신된 값을 확인하는 편이 정확하다.
AllReady()는 PhotonNetwork.PlayerList의 모든 플레이어에 대해 IsReady()를 검사한다. 방장이 시작 버튼을 누르면 PhotonNetwork.IsMasterClient와 AllReady()를 확인하고, 조건이 맞을 때 PhotonNetwork.CurrentRoom.IsOpen = false로 새 플레이어의 입장을 막는다. 현재 코드의 Debug.Log("게임시작")은 로그만 출력하며 게임 씬을 실제로 시작시키는 코드는 아니다. 플레이어의 Custom Properties는 방을 바꿔도 로컬 플레이어에 남을 수 있으므로, 새 방에서 준비 상태를 초기화할지는 별도로 정해야 한다.
OnClickTransferMaster()는 내가 방장일 때 PhotonNetwork.SetMasterClient(p)로 다른 플레이어에게 방장을 넘긴다. OnMasterClientSwitched(Player newMasterClient)가 호출되면 새 방장을 기록하고 플레이어 목록의 방장 표시를 갱신한다. PhotonNetwork.IsMasterClient는 내가 현재 방장인지, 각 플레이어의 p.IsMasterClient는 그 플레이어가 방장인지 확인할 때 쓴다.
방에서 나가려면 PhotonNetwork.LeaveRoom()을 호출하고, 완료 후 OnLeftRoom()에서 화면을 갱신한다. 연결이 끊기는 OnDisconnected()는 단순한 방 퇴장과 구분해야 한다.
방 생성·입장 요청 → 성공 또는 실패 콜백 → 방 정보 갱신 → 플레이어별 ready 속성 변경 → OnPlayerPropertiesUpdate()로 준비 표시 갱신 → 방장이 전원 준비 확인 후 방 닫기 → 방 퇴장 콜백.
참고 스크립트: PhotonLobbyManager.cs, RoomButton.cs.
Develog는 단순히 글을 쓰는 공간이 아닙니다. 성장의 과정을 기록하고, 그 기록으로 나를 증명하며 원하는 기회를 얻는 곳이길 바랐습니다. 누군가의 꿈으로 향하는 중간다리가 되는 것, 그것이 Develog를 만든 이유입니다.

우리들의 게임 발매 이야기

안녕하세요. 플밍 4기 입니다. 게임 개발을 배우기 전 네트워크 엔지니어 도메인에서 익히고 배웠던 네트워크 이론에 대한 기초 입니다. 학습에 도움이 되길 바라며 공유 드립니다.
Develog는 단순히 글을 쓰는 공간이 아닙니다. 성장의 과정을 기록하고, 그 기록으로 나를 증명하며 원하는 기회를 얻는 곳이길 바랐습니다. 누군가의 꿈으로 향하는 중간다리가 되는 것, 그것이 Develog를 만든 이유입니다.



안녕하세요. 플밍 4기 입니다. 게임 개발을 배우기 전 네트워크 엔지니어 도메인에서 익히고 배웠던 네트워크 이론에 대한 기초 입니다. 학습에 도움이 되길 바라며 공유 드립니다.