ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Photon - Demo 탐색
    Unity 2023. 10. 25. 23:58

    I. 유니티 내 구성

     

     1. TopPanel

     

       A. LobbyTopPanel.cs

     

    namespace Photon.Pun.Demo.Asteroids
    {
        public class LobbyTopPanel : MonoBehaviour
        {
            private readonly string connectionStatusMessage = "    Connection Status: ";
    
            [Header("UI References")]
            public Text ConnectionStatusText;
    
            #region UNITY
    
            public void Update()
            {
                ConnectionStatusText.text = connectionStatusMessage + PhotonNetwork.NetworkClientState;
            }
    
            #endregion
        }
    }

     

    ConnectionStatusText 

     

     : ConnectionStatus 오브젝트의 컴포넌트 중 Text 컴포넌트

     

    PhotonNetWork.NetworkClientState

     

     : 현재 클라이언트의 네트워크 상태를 반환함.

     

        public static ClientState NetworkClientState
        {
            get
            {
                if (OfflineMode)
                {
                    return (offlineModeRoom != null) ? ClientState.Joined : ClientState.ConnectedToMasterServer;
                }
    
                if (NetworkingClient == null)
                {
                    return ClientState.Disconnected;
                }
    
                return NetworkingClient.State;
            }
        }

     

     

    2. MainPanel

     

     A. LobbyMainPanel.cs

     

     

         a. Awake()

     

    public void Awake()
    {
        PhotonNetwork.AutomaticallySyncScene = true;
    
        cachedRoomList = new Dictionary<string, RoomInfo>();
        roomListEntries = new Dictionary<string, GameObject>();
    
        PlayerNameInput.text = "Player " + Random.Range(1000, 10000);
    }

     

    PhotonNetWork.AutomaticallySyncScene

     

     : 방 안의 클라이언트가 마스터 클라이언트와 동일한 씬을 자동으로 로드해야하는 지 여부를 결정

     : 해당 bool을 true로 한다면, 이후에도 모든 클라이언트들은 마스터 클라이언트와 같은 씬을 로드하게 됨.

     

    딕셔너리 사용 이유

     

     : 각 방의 이름을 키로 사용하여 해당 방의 정보를 효율적으로 관리할 수 있기 때문에, 리스트보다 딕셔너리로 관리하는 것이 유리함.

     

    cachedRoomList

     

     : 게임 내에서 방의 상태를 추적하고 유지하기 위한 데이터를 담은 딕셔너리.

     

     * 캐싱 : 데이터나 계산 결과를 이후에 더 빠르게 액세스할 수 있도록 메모리에 보관하는 것.

     

    roomListEntries

     

      : UI에 표시되는 방 목록을 관리하는 데 사용하는 딕셔너리

     

     

         b. OnConnectedToMaster()

       

    public override void OnConnectedToMaster() // 마스터 접속을 했을 때.
    {
        this.SetActivePanel(SelectionPanel.name);
    }

     

    PunClasses.OnConnectedToMaster()

     

    public virtual void OnConnectedToMaster()
    {
    }

     

     : OnConnectedToMaster() 은 PunClasses의 OnConnectedToMaster()을 오버라이드함.

     

    SetActivePanel()

     

      : 파라미터로 받은 activePanel 이 각 패널(여기서는 게임오브젝트로 연결함)의 이름과 같다면, 해당 패널을 활성화시킴.

     

    private void SetActivePanel(string activePanel)
    {
        LoginPanel.SetActive(activePanel.Equals(LoginPanel.name));
        SelectionPanel.SetActive(activePanel.Equals(SelectionPanel.name));
        CreateRoomPanel.SetActive(activePanel.Equals(CreateRoomPanel.name));
        JoinRandomRoomPanel.SetActive(activePanel.Equals(JoinRandomRoomPanel.name));
        RoomListPanel.SetActive(activePanel.Equals(RoomListPanel.name));    // UI should call OnRoomListButtonClicked() to activate this
        InsideRoomPanel.SetActive(activePanel.Equals(InsideRoomPanel.name));
    }

     

         c. OnRoomListUpdate()

     

        : 현재 Peer에 존재하는 방을 관리하여 보여줌.

        => 플레이가 진행중인 방은 삭제

    public override void OnRoomListUpdate(List<RoomInfo> roomList)
    {
        ClearRoomListView();
    
        UpdateCachedRoomList(roomList);
        UpdateRoomListView();
    }

     

     

    ClearRoomListView()

     

      : UI에 표시된 ( = roomListEntries 에 있는) 모든 오브젝트를 다 파괴한다.

       => 방 정보를 가진 프리팹들을 모두 파괴

     

    private void ClearRoomListView()
    {
        foreach (GameObject entry in roomListEntries.Values)
        {
            Destroy(entry.gameObject);
        }
    
        roomListEntries.Clear();
    }

     

     => RoomListEntry.cs

     

     : roomListPanel 에서 존재하고 있는 room의 정보를 보여줌.

     : 각각의 room에 대한 정보를 roomListEntries에서 획득하여, Initailize()로 RoomListEntry 프리팹을 instantiate 함.

     

     : 해당 방의 JoinRoomButton을 클릭하는 이벤트가 발생할 시, 해당 방으로 이동하는 JoinRoom 메서드를 연결시킴.

     

    public class RoomListEntry : MonoBehaviour
    {
        public Text RoomNameText;
        public Text RoomPlayersText;
        public Button JoinRoomButton;
    
        private string roomName;
    
        public void Start()
        {
            JoinRoomButton.onClick.AddListener(() =>
            {
                if (PhotonNetwork.InLobby)
                {
                    PhotonNetwork.LeaveLobby();
                }
    
                PhotonNetwork.JoinRoom(roomName);
            });
        }
    
        public void Initialize(string name, byte currentPlayers, byte maxPlayers)
        {
            roomName = name;
    
            RoomNameText.text = name;
            RoomPlayersText.text = currentPlayers + " / " + maxPlayers;
        }
    }

     

    UpdateCachedRoomList()

     

     : 캐싱한 데이터를 통해 ( = chachedRoomList 에 있는 키값을 기준으로), roomSelectPanel 에서 현재 선택 가능한 룸의 정보를 관리함.

     : RoomInfo 클래스를 만들어, 룸의 정보를 관리하기 위한 필드의 상태에 따라 관리.

     

    private void UpdateCachedRoomList(List<RoomInfo> roomList)
    {
        foreach (RoomInfo info in roomList)
        {
            // Remove room from cached room list if it got closed, became invisible or was marked as removed
            if (!info.IsOpen || !info.IsVisible || info.RemovedFromList)
            {
                if (cachedRoomList.ContainsKey(info.Name))
                {
                    cachedRoomList.Remove(info.Name);
                }
    
                continue;
            }
    
            // Update cached room info
            if (cachedRoomList.ContainsKey(info.Name))
            {
                cachedRoomList[info.Name] = info;
            }
            // Add new room info to cache
            else
            {
                cachedRoomList.Add(info.Name, info);
            }
        }
    }

     

    UpdateRoomListView()

     

        : 현재 Peer에 존재하는 모든 방을 보여줌.

        : RoomListEntryPrefab을 인스턴스화 하고, RoomListPanel의 content에 추가함.

    private void UpdateRoomListView()
    {
        foreach (RoomInfo info in cachedRoomList.Values)
        {
            GameObject entry = Instantiate(RoomListEntryPrefab);
            entry.transform.SetParent(RoomListContent.transform);
            entry.transform.localScale = Vector3.one;
            entry.GetComponent<RoomListEntry>().Initialize(info.Name, (byte)info.PlayerCount, (byte)info.MaxPlayers);
    
            roomListEntries.Add(info.Name, entry);
        }
    }

     

     => RoomListContent

     

         : RoomListPanel에서 Vertical Layout Group 컴포넌트의 요소 중, Content 오브젝트.

            => Room 에 대한 정보가 존재할 시에, RoomListEntry 프리팹이 자식 오브젝트로써 추가된다.

     

     

         d. OnJoinedLobby()

     

         : 플레이어가 로비에 참여할 때, 이전에 캐시된 룸 데이터 (chacedRoomList)를 삭제하고, UI에서 보이는 룸의 오브젝트를 삭제하는 콜백 함수.

     

    public override void OnJoinedLobby()
    {
        // whenever this joins a new lobby, clear any previous room lists
        cachedRoomList.Clear();
        ClearRoomListView();
    }

     

    MonoBehaviorPunCallBacks.OnJoinedLobby()

     

       : 마스터 서버의 로비에 들어갈 때 호출

     

    public virtual void OnJoinedLobby()
    {
    }

     

         e. OnLeftLobby()

     

         : 플레이어가 로비에서 나갈 때, 이전에 캐시된 룸 데이터를 삭제하고, UI에서 보이는 룸의 오브젝트를 삭제하는 콜백 함수

     

    public override void OnLeftLobby()
    {
        cachedRoomList.Clear();
        ClearRoomListView();
    }

     

    MonoBehaviorPunCallBacks.OnLeftLobby()

     

          : 마스터 서버의 로비에서 나갈 때 호출

     

    public virtual void OnLeftLobby()
    {
    }

     

         f. OnCreatedRoomFailed()

     

         : 방 만들기에 실패했을 때,  SelectionPanel을 활성화하는 콜백 함수

     

    public override void OnCreateRoomFailed(short returnCode, string message)
    {
        SetActivePanel(SelectionPanel.name);
    }

     

    MonoBehaviorPunCallBacks.OnCreatedRoomFailed()

     

         : 방 만들기에 실패했을 때 호출

     

    public virtual void OnCreateRoomFailed(short returnCode, string message)
    {
    }

     

     

         g. OnJoinedRoomFailed()

     

         : 방 참가에 실패했을 때, SelectionPanel을 활성화하는 콜백 함수

     

    public override void OnJoinRoomFailed(short returnCode, string message)
    {
        SetActivePanel(SelectionPanel.name);
    }

     

    MonoBehaviorPunCallBacks.OnJoinedRoomFailed()

     

         : 방 참가에 실패했을 때 호출

     

    public virtual void OnJoinRoomFailed(short returnCode, string message)
    {
    }

     

         h. OnJoinRandomFailed()

     

         : 랜덤 방 참가에 실패했을 경우, 새로운 방을 만들어 입장하는 콜백 함수

     

    public override void OnJoinRandomFailed(short returnCode, string message)
    {
        string roomName = "Room " + Random.Range(1000, 10000);
    
        RoomOptions options = new RoomOptions {MaxPlayers = 2};
    
        PhotonNetwork.CreateRoom(roomName, options, null);
    }

     

    RoomOptions

     

    public class RoomOptions
    {
        public bool IsVisible { get { return this.isVisible; } set { this.isVisible = value; } }
        private bool isVisible = true;
        public bool IsOpen { get { return this.isOpen; } set { this.isOpen = value; } }
        private bool isOpen = true;
        public int MaxPlayers;
        public int PlayerTtl;
        public int EmptyRoomTtl;
        public bool CleanupCacheOnLeave { get { return this.cleanupCacheOnLeave; } set { this.cleanupCacheOnLeave = value; } }
        private bool cleanupCacheOnLeave = true;
        public Hashtable CustomRoomProperties;
        public string[] CustomRoomPropertiesForLobby = new string[0];
        public string[] Plugins;
        public bool SuppressRoomEvents { get; set; }
        public bool SuppressPlayerInfo { get; set; }
        public bool PublishUserId { get; set; }
        public bool DeleteNullProperties { get; set; }
        public bool BroadcastPropsChangeToAll { get { return this.broadcastPropsChangeToAll; } set { this.broadcastPropsChangeToAll = value; } }
        private bool broadcastPropsChangeToAll = true;
    }

     

      - IsVisible

        : 방이 노출되는가?

        : 로비의 리스트에 방이 포함되어 있는가?

      - IsOpen

         : 방에 인원이 참가가 가능한가?

      - MaxPlayers

         : 방 참가 가능 최대 인원 수

      - PlayerTtl

         : 플레이어가 방에서 나간 후, 액터(플레이어의 정보)가 방에서 체류할 수 있는 시간

         : TTL 시간 동안, 플레이어가 다시 들어온다면, 재연결 혹은 재참여가 가능하다.

         : 단위는 밀리초

      - EmptyRoomTtl

         : 마지막 플레이어가 방에서 나간 후, 방의 정보가 로비에서 체류할 수 있는 시간

         : 단위는 밀리초

       - CleanUpCacheOnLeave

         : 유저가 방에서 떠날 때, 유저의 이벤트와 프로퍼티를 방에서 삭제하는가에 대한 여부

       - CustomProperties

         : 추가적으로 HashTable 형식의 "key", "value" 형식의 데이터를 방이나 플레이어에 붙여서 사용할 수 있는 기능.

         

    public override void OnConnectedToMaster()
    {
        var roomOption = new RoomOptions()
        roomOption.CustomRoomProperties = new HashTable() { { "Type", "대장전" } };
        
        PhotonNetWork.JoinOrCreateRoom("Room", roomOption, null);
     }
     
     public override void OnJoinedRoom()
     {
     	HashTable CP = PhotonNetwork.CurrentRoom.CustomProperties;
        
        switch (CP["Type"])
        {
        	case "섬멸전":
            	Debug.Log("섬멸전을 선택하셨습니다.");
                break;
            case "대장전":
            	Debug.Log("대장전을 선택하셨습니다.");
                break;
        }
        
        // 마스터 클라이언트일 시, 방장임을 알리는 커스텀 프로퍼티 설정
        if (PhotonNetwork.IsMasterClient) 
        {
        	PhotonNetwork.LocalPlayer.SetCustomProperties(new Hashtable { {"IsAdmin", "Admin"} };
        }
     }
        
     public void OnTypeEleminationSelected()
     {
     	if (PhotonNetwork.LocalPlayer.CustomProperties["IsAdmin"] == "Admin")
        {
            HashTable CP = PhotonNetwork.CurrentRoom.CustomProperties;
            CP["Type"] = "섬멸전";
        }
     }
     
    public void OnTypeClassicSelected()
    {
        if (PhotonNetwork.LocalPlayer.CustomProperties["IsAdmin"] == "Admin")
        {
            HashTable CP = PhotonNetwork.CurrentRoom.CustomProperties;
        	CP["Type"] = "대장전";
        }
    }

     

       -  SuppressRoomEvents

        : 방에 참여하거나 떠나는 플레이어들의 룸 이벤트 스킵 여부

        : 활성화시, 클라이언트는 룸에 있는 다른 플레이어를 알 수 없음.

       - SuppressPlayerInfo

        : 가입 프로세스 중에 가입된 사용자에 대한 모든 정보를 가져오는 것을 금지함.

        : GetProperties 작업을 사용하여 이 정보를 가져올 수 있음.

       - PublishUserId

        : 룸에 있는 "published" 된 플레이어의 UserId를 정의 함.

        : 친구와 게임 같이하기 기능을 구현하고 싶을 때 사용함.

     

    PhotonNetwork.CreateRoom

     

       : PhotonNetwork의 연결 상태 혹은 설정에 따라 방을 만들고, 만들었는 지 여부를 bool 값으로 반환함.

     

       : 오프라인 일 경우, 오프라인 방을 만듦.

       : 마스터 서버에 연결되어 있지 않은 경우, 방 생성에 실패함.

       : 방을 생성하면서 방 생성을 위한 매개변수(EnterRoomParams)를 설정함.

    public static bool CreateRoom(string roomName, RoomOptions roomOptions = null, TypedLobby typedLobby = null, string[] expectedUsers = null)
    {
        if (OfflineMode)
        {
            if (offlineModeRoom != null)
            {
                Debug.LogError("CreateRoom failed. In offline mode you still have to leave a room to enter another.");
                return false;
            }
            EnterOfflineRoom(roomName, roomOptions, true);
            return true;
        }
        if (NetworkingClient.Server != ServerConnection.MasterServer || !IsConnectedAndReady)
        {
            Debug.LogError("CreateRoom failed. Client is on " + NetworkingClient.Server + " (must be Master Server for matchmaking)" + (IsConnectedAndReady ? " and ready" : "but not ready for operations (State: " + NetworkingClient.State + ")") + ". Wait for callback: OnJoinedLobby or OnConnectedToMaster.");
            return false;
        }
    
        typedLobby = typedLobby ?? ((NetworkingClient.InLobby) ? NetworkingClient.CurrentLobby : null);  // use given lobby, or active lobby (if any active) or none
    
        EnterRoomParams opParams = new EnterRoomParams();
        opParams.RoomName = roomName;
        opParams.RoomOptions = roomOptions;
        opParams.Lobby = typedLobby;
        opParams.ExpectedUsers = expectedUsers;
    
        return NetworkingClient.OpCreateRoom(opParams);
    }

     

     

    LoadbalancingPeer.EnterRoomParams

     

    public class EnterRoomParams
    {
        public string RoomName;
        public RoomOptions RoomOptions;
        public TypedLobby Lobby;
        public Hashtable PlayerProperties;
        protected internal bool OnGameServer = true; 
        protected internal JoinMode JoinMode;
        public string[] ExpectedUsers;
    }

     

    'Unity' 카테고리의 다른 글

    Photon - Demo 탐색 (2)  (1) 2023.10.29
    photon - 채팅 기능 구현 기획  (0) 2023.10.26
    네트워크 게임의 이해  (0) 2023.10.24
    readme 작성  (0) 2023.10.19
    코루틴 (in Unity)  (1) 2023.10.06
Designed by Tistory.