1 minute read

포톤 서버 적용 (Pun2)

이번 팀 프로젝트는 혈압 마라톤 모작의 멀티게임을 구현하는 것이었습니다. 제가 맡은 부분은 플레이어 간의 네트워크 통신으로, Photon 서버를 이용해 Pun2를 사용하여 제작했습니다.
Photon 서버의 Pun은 P2P 방식으로, 서버는 플레이어를 룸까지 매칭만 시켜주고, 그 이후로는 룸의 첫 생성자인 마스터와 나머지 클라이언트로 이루어진 네트워크 방식입니다.

1. 연결 설정

룸에 연결하는 메서드

public void ConnectToRoom()
{
    if (PhotonNetwork.IsConnected)
    {
        // 랜덤한 룸에 연결
        if (isConnecting)
        {
            PhotonNetwork.JoinRandomRoom();
        }
    }
    else
    {
        // 현재 포톤 연결 세팅에 맞춰서 연결
        PhotonNetwork.ConnectUsingSettings();
        PhotonNetwork.GameVersion = gameVersion;
    }
}

위 메서드는 룸에 빠르게 연결하는 방법입니다. 비슷한 방식으로, 연결되어 있으면 룸이나 로비로 들어가게 됩니다.

2. 룸 및 로비 관리

룸 리스트 업데이트

룸 리스트를 화면에 표시하기 위한 코드입니다:

public override void OnRoomListUpdate(List<RoomInfo> roomList)
{
    base.OnRoomListUpdate(roomList);
    foreach (RoomInfo roomInfo in roomList)
    {
        if (roomDict.ContainsKey(roomInfo.Name))
        {
            Destroy(roomDict[roomInfo.Name]);
            roomDict.Remove(roomInfo.Name);
        }
        else
        {
            if (!roomDict.ContainsKey(roomInfo.Name))
            {
                GameObject roomEntry = Instantiate(roomListPrefab, roomListParent);
                roomEntry.GetComponentInChildren<TextMeshProUGUI>().text = $"방 이름 : {roomInfo.Name.Substring(0, 4)}\n현재 인원 : {roomInfo.PlayerCount}";
                Button button = roomEntry.GetComponent<Button>();
                button.onClick.AddListener(() =>
                {
                    JoinRoom(roomInfo.Name);
                });
                roomDict.Add(roomInfo.Name, roomEntry);
            }
        }
    }
}

Photon은 룸 목록 업데이트 기능을 자체적으로 제공하여 매우 편리했습니다.

3. 룸 참여 및 플레이어 목록

플레이어 목록 표시 및 게임 시작

룸에 참여하면 플레이어 목록을 보여주고, 인원이 최대치가 되면 게임을 자동으로 시작합니다:

[PunRPC]
private void MakePlayerListContent(int id)
{
    GameObject newListContent = Instantiate(playerListContentPrefab, playerListParent);
    TextMeshProUGUI tmp = newListContent.GetComponentInChildren<TextMeshProUGUI>();
    tmp.SetText($"유저 Id : {id}");
    if (PhotonNetwork.IsMasterClient)
    {
        playerObjectList.add(id, newListContent);
    }
}

RPC를 사용하면 특정 메서드를 한 명이 실행할 때 나머지 모두가 함께 실행됩니다:

photonView.RPC("MakePlayerListContent", RpcTarget.AllBuffered, playerInGameId);

게임이 시작되기 전, 최대 인원이 모두 찼을 때 10초 카운트 다운을 하며, 도중에 플레이어가 나가면 게임 시작을 취소하고 해당 플레이어를 목록에서 제외합니다:

public override void OnPlayerLeftRoom(Photon.Realtime.Player otherPlayer)
{
    if (!PhotonNetwork.IsMasterClient) { return; }
    base.OnPlayerLeftRoom(otherPlayer);
    RemovePlayerFromData(otherPlayer);
}

Photon은 다양한 콜백 메서드를 제공하여 이런 특수 상황에 편리하게 대응할 수 있었습니다.


이제 뒤에는 플레이어와 같은 네트워크 데이터에서 정보가 필요한 객체의 생성, 각 개인의 조작으로 변화한 내용의 동기화가 남았습니다.