Unity Network with Photon

장현태입니다·2025년 7월 24일

※ 틀린 사항이 포함되어 있을수도 있습니다. 후기 남겨주시면 제대로 수정하고 학습하겠습니다

1. UI Binding을 이용한 Network와 UI연결

Network에서 로비나 룸을 만들 때 ui는 빠지지않고 들어간다. 이점을 생각해봤을 때 많은 ui요소를 인스펙터에 넣고 실수하지 않게 설정하는것은 어려울 수 있어서 ui바인딩을 이용해서 Network 연결, 로비, 룸을 구성할것이다(일부분은 직렬화 필요)

다음과같이 BaseUI를 통해 상속한 ui들을 Manager와 큰 틀인 Canvas에서 작은 단위인 ui들을 생성하고 로비와 룸을 구성해서 Network를 구성할것이다.

2. 기본적인 사용방법

private GameObject roomPanelItem => GetUI("RoomPanelItemParent");
private GameObject createRoomPanel => GetUI("CreateRoomPanel");
private Button leaveLobbyButton => GetUI<Button>("LeaveLobbyButton");
private Button createRoomButton => GetUI<Button>("CreateRoomButton");
  
private void Start()
{
    GetEvent("CreateLobbyButton").Click += data =>
    {
        createRoomPanel.SetActive(true);
        roomPanelItem.SetActive(false);
        createLobbyButton.interactable = false;
        leaveLobbyButton.interactable = false;
    };
}

빈 오브젝트나 해당 오브젝트를 컨트롤 할 수 있도록 GameObject, UI요소를 사용해야하는 Button은 GetUI<ㅁㅁㅁ> 와 같은 형식으로 작성해서 사용해준다.

GetEvent(string)에서 string형식의 사용할 인스펙터의 ui요소를 string으로 만들어서 해당 오브젝트의 이벤트를 사용해주면 이전에 기입해두었던 이벤트로 사용이 가능하다.

NetworkManager

 void Start()
 {
     currentRoomDic = new();
     PhotonNetwork.ConnectUsingSettings();
 }

 #region ConnectNetwork & Lobby
 public override void OnConnectedToMaster()
 {
     if (loadingPanel.activeSelf)
     {
         loadingPanel.SetActive(false);
     }
     PhotonNetwork.JoinLobby();
 }

 public override void OnDisconnected(DisconnectCause cause)
 {
     PhotonNetwork.ConnectUsingSettings();
 }

 public override void OnJoinedLobby()
 {
     lobbyPanel.SetActive(true);
     StateCustomProperty(CurrentState.Lobby);
 }

 public override void OnCreatedRoom()
 {
     StateCustomProperty(CurrentState.InRoom);
 }

 public override void OnJoinedRoom()
 {
     lobbyPanel.SetActive(false);
     roomPanel.SetActive(true);
     roomManager.PlayerPanelSpawn();
 }

시작 호출로 오브젝트를 켰다 꺼줬다를 실행하며 로비, 그리고 룸으로 이동할 수 있도록 구성하였다.

public override void OnRoomListUpdate(List<RoomInfo> roomList)
{
    foreach (RoomInfo roomInfo in roomList)
    {
        //방이 사라질 때
        if (roomInfo.RemovedFromList)
        {
            if (currentRoomDic.TryGetValue(roomInfo.Name, out GameObject obj))
            {
                Destroy(obj);
                currentRoomDic.Remove(roomInfo.Name);
            }

            continue;
        }
        
        //방이 생길 때
        if (currentRoomDic.ContainsKey(roomInfo.Name))
        {
            currentRoomDic[roomInfo.Name].GetComponent<JHT_RoomItem>().Init(roomInfo);
        }
        else
        {
            GameObject prefab = Instantiate(roomPanelPrefab);
            prefab.transform.SetParent(roomListParent);
            prefab.GetComponent<JHT_RoomItem>().Init(roomInfo);
            currentRoomDic.Add(roomInfo.Name, prefab);
        }
    }
}

네트워크에서 제일 큰 학습중 하나였던 OnRoomListUpdate인데 이 함수를 호출하게되면 Roominfo의 List를 가져오게 되는데 룸의 정보를 담은 RoomInfo에서 방의 정보를 토대로 방 형식의 패널을 생성해주도록 하였다. (OnRoomListUpdate - 룸리스트가 변경될 때 호출됨)

플레이어의 친구목록에서 현재 내 친구의 게임 상태를 위해 생성한 커스텀 프러퍼티이다


방이 생성이 됐을 때 다음과 같이 커스텀프로퍼티를 설정해서 현재 플레이어의 상태를 해시테이블에서 플레이어의 Enum을 설정하도록 구성하였고 아직 완성하지는 못했다.

팀 나누기

아직 구현되지 못한 상태이지만 브리핑을 하자면 현재 만들고있는 게임은 2:2형식으로 두개의 팀으로 나눌 필요가 있다.

먼저 커스텀프로퍼티로 Team을 만들고 "BlueTeam", "RedTeam"을 string 형식의 변수에 할당하는데 룸을 만드는 플레이어(마스터)가 Count를 가지고 있도록하고 해당 방을 구성했을 때 Dictionary<int,string>을 사용해서 플레이어가 어디팀의 위치에 있는지, 그리고 플레이어가 나갔을 때 해당 키를 가지고있는 플레이어의 count를 줄일 수 있게 설정할 필요가 있을거 같다.

public void SeparateTeam()
{
    int blueCount = 0;
    int redCount = 0;

    foreach (Player player in PhotonNetwork.PlayerList)
    {
        string team = blueCount <= redCount ? "Blue" : "Red";
        ExitGames.Client.Photon.Hashtable teamProperty = new();
        teamProperty["Team"] = team;
        PhotonNetwork.LocalPlayer.SetCustomProperties(teamProperty);

        if (team == "Blue") 
        	blueCount++;
        else 
        	redCount++;
    }
}

이슈사항

플레이어가 룸에 들어왔을 때 PhotonNetwork.LocalPlayer.ActorNumber 자신의 고유 번호를 가지도록 이름을 설정 해놨다(추후에 Firebase.Auth.CurrentUser.DisplayNamed으로 수정예정) 하지만 다른 플레이어가 들어와도 자신의 ActorNumber로 표기되는 이슈가 있었다. 동기화에 대해 더 고민해보고 해결할 수 있도록 해야할거같다. (아직 해결 안됨)


시연 영상

0개의 댓글