Notice
Recent Posts
Recent Comments
Link
«   2025/06   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
Archives
Today
Total
관리 메뉴

행복한 개구리

Unity 팀프로젝트 21.05.14. Pun2 - 방목록 출력 본문

Unity/Project : Cursed Treasure

Unity 팀프로젝트 21.05.14. Pun2 - 방목록 출력

HappyFrog 2021. 5. 14. 14:30

* GetRoomList대신 ILobbyCallbacks의 OnRoomListUpdate사용 권장 - 11:58 해결
https://doc.photonengine.com/en-us/pun/v2/getting-started/migration-notes

 

Migration Notes | Photon Engine

Photon Quantum Join the revolution in multiplayer games development: create MOBAs, brawler, RTS, fighting and sports games with our blazing fast deterministic networking engine.

doc.photonengine.com

ㄴ Pun2에선 GetRoomList()를 사용할 수 없다.

 

ㄴ OnRoomListUpdate를 상속받아 사용하면 매개변수를 할당하지 않아도 JoinLobby를 통해 콜백됨. 따라서 상속받아 오버라이드만 시켜서 사용한다면 문제없이 방목록과 해당 방의 정보들 출력가능

* RoomList를 출력시, RoomOptions가 제대로 설정되지 않는 이슈 - 12:21 해결
ㄴRoomOptions를 메서드 내에서 생성하여 옵션의 속성들을 설정한 뒤 JoinOrCreateRoom의 매개변수로 할당하니까 해결됨.
ㄴ사진 RoomOptions 참고.

* UIRoomItem 출력시 Grid에 의해 부자연스러운 연출이 되는 이슈 - 12:26
ㄴVertical Layout의 Child Force Expand의 Height설정을 풀어주면 해결.
ㄴ사진 Grid 참고.

* RoomList 갱신되지 않는 이슈 발견 - 14:58
ㄴ 해결위해 OnRoomListUpdate, OnPlayerLeftRoom, OnLeftRoom R&D시작

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Photon.Pun;
using Photon.Realtime;

public partial class Launcher : MonoBehaviourPunCallbacks
{
    public Button masterJoin;
    public Button masterLeave;
    public Button create;
    public Button roomJoin;
    public Button roomLeave;
    public Text masterCount;
    public Text roomtext;
    public InputField roomName;
    public UIRoomItem room;
    public Transform grid;	//방 목록에서 슬롯들을 생성시킬 위치

    Dictionary<string, RoomInfo> cachedRoomList;	//방정보를 담는 딕셔너리
    Dictionary<string, GameObject> roomListEntries;	//방목록에 할당될 UI게임오브젝트들의 딕셔너리

    
    #region Private Serializable Fields
    #endregion

    #region Private Fields
    string gameVersion = "1";
    byte maxPlayer = 4;
    
    #endregion

    private void Awake()
    {
        PhotonNetwork.AutomaticallySyncScene = true;
        cachedRoomList = new Dictionary<string, RoomInfo>();
        roomListEntries = new Dictionary<string, GameObject>();
    }
    void Start()
    {
        Init();
    }

    void Update()
    {
        if (PhotonNetwork.IsConnected)
        {
            this.masterCount.text = PhotonNetwork.CountOfPlayersOnMaster.ToString();
            if (PhotonNetwork.CurrentRoom != null)
            {
                this.roomtext.text = PhotonNetwork.CurrentRoom.Name + " / " + PhotonNetwork.PlayerList.Length.ToString();
            }
            else
            {
                this.roomtext.text = "Not Connected";
            }
        }
        else
        {
            this.masterCount.text = "0";
            this.roomtext.text = "Not Connected";
        }
    }

    public void Init()
    {
        Connect();
        LeaveServer();
        Create();
        RoomLeave();
    }

    [PunRPC]
    public void Connect()
    {
        this.masterJoin.onClick.AddListener(() =>
        {
            PhotonNetwork.GameVersion = gameVersion;
            PhotonNetwork.ConnectUsingSettings();
            this.masterJoin.gameObject.SetActive(false);
            this.masterLeave.gameObject.SetActive(true);
            this.masterCount.gameObject.SetActive(true);
        });
    }

    void LeaveServer()
    {
        this.masterLeave.onClick.AddListener(() =>
        {
            PhotonNetwork.Disconnect();
            this.masterJoin.gameObject.SetActive(true);
            this.masterLeave.gameObject.SetActive(false);
            this.masterCount.gameObject.SetActive(false);
        });
    }

    void RoomLeave()
    {
        this.roomLeave.onClick.AddListener(() =>
        {
            PhotonNetwork.LeaveRoom();
        });
    }

    public override void OnRoomListUpdate(List<RoomInfo> roomList)
    {       
        Debug.Log("OnRoomListUpdate" + roomList.Count);

        ClearRoomListView();
        UpdateCachedRoomList(roomList);
        UpdateRoomListView();
    }

    void UpdateCachedRoomList(List<RoomInfo> roomList)
    {
        foreach (var room in roomList)
        {
            if (room.RemovedFromList)   //없어졌는데
            {
                if (cachedRoomList.ContainsKey(room.Name))  //리스트에 방제목이 존재하거나
                {
                    cachedRoomList.Remove(room.Name);
                }
                continue;
            }
            else if (cachedRoomList.ContainsKey(room.Name)) //존재하고 방제목이 이미 리스트에 존재하거나
            {
                cachedRoomList[room.Name] = room;
            }
            else
            {
                cachedRoomList.Add(room.Name, room);    //둘 다 아니라면 리스트에 추가
            }
        }
    }

    void ClearRoomListView()
    {
        foreach(var entry in roomListEntries.Values)    //foreach roomListEntries의 게임오브젝트들을 부순다.
        {
            Destroy(entry.gameObject);
        }
        roomListEntries.Clear();    //그리고 roomListEntries를 비운다.
    }

    void UpdateRoomListView()
    {
        foreach(RoomInfo room in cachedRoomList.Values) //리스트칸에 UI방목록 생성
        {
            GameObject entry = Instantiate(this.room.gameObject);
            entry.transform.SetParent(this.grid);
            entry.transform.localScale = Vector3.one;
            entry.GetComponent<UIRoomItem>().Init(room.Name, room.PlayerCount, room.MaxPlayers);

            roomListEntries.Add(room.Name, entry);
        }
    }


    void Create()
    {
        Debug.Log("CreateRoom!@!@!@");
        this.create.onClick.AddListener(() =>
        {
            var roomName = this.roomName.text;
            RoomOptions roomOption = new RoomOptions();
            roomOption.MaxPlayers = maxPlayer;
            roomOption.CleanupCacheOnLeave = true;
            var room = PhotonNetwork.JoinOrCreateRoom(roomName, roomOption, null);
            Debug.Log("CreateRoom!");
        });
    }

    public override void OnConnectedToMaster()
    {
        Debug.Log("OnConnectedToMaster()");
        PhotonNetwork.JoinLobby();
    }

    public override void OnJoinedLobby()    //로비참가시 방목록 초기화 및 방목록캐시 초기화
    {
        cachedRoomList.Clear();
        ClearRoomListView();

        Debug.Log("Joined Lobby");
    }

    public override void OnLeftLobby()  //로비를 떠날 때 방목록 초기화 및 방목록캐시 초기화
    {
        cachedRoomList.Clear();
        ClearRoomListView();

        Debug.Log("Left Lobby");
    }

    public override void OnJoinedRoom() //방참가시 방목록캐시 초기화
    {
        cachedRoomList.Clear();
        Debug.LogFormat("OnJoinedRoom()");
    }

    public override void OnDisconnected(DisconnectCause cause)
    {
        Debug.LogFormat("OnDisconnected");
    }

    public override void OnLeftRoom()   //방을 떠날 때 방목록 초기화
    {
        ClearRoomListView();
        Debug.LogFormat("OnLeftRoom!!!!!!!");
    }

    public override void OnPlayerLeftRoom(Player otherPlayer)
    {
        Debug.Log("OnPlayerLeftRoom: " + otherPlayer.NickName);
    }
}

OnRoomListUpdate()에 대한 이슈를 해결했다. 데모버전의 힘을 빌려 해결하긴 했지만 구조를 이해하고 내용을 조금씩 수정하며 적용하느라 꽤나 오래걸렸다.

 

OnLeftRoom과 OnPlayerLeftRoom의 차이점은 OnPlayerLeftRoom은 내가 아닌 다른 플레이어가 방에서 떠났을 때를 알려주는 콜백메서드이다. 따라서 LeaveRoom을 한다면 OnLeftRoom이 콜백된다. 그렇기 때문에 OnLeftRoom에서 ClearRoomListView로 방에서 나올 때 RoomList를 초기화해주었다.

 

또한 OnRoomListUpdate()가 Update과 마찬가지로 'Lobby'에 있을 때 Update기능을 해주는 콜백메서드였다. - 따라서 따로 Update에 코딩할 필요가 없었다.

 

그리고 OnRoomListUpdate에서 3가지 메서드를 사용하는데, 순서가 중요하다.

1.RoomList를 먼저 초기화하고 (ClearRoomListView)

2.갱신된 방들의 정보를 가져오고 (UpdateCachedRoomList)

3.그 정보를 바탕으로 UI를 생성한다. (UpdateRoomListView)

 

만약 초기화 처리나 OnRoomListUpdate에서의 순서가 잘못되었다면, 방에서 나와도 방 목록이 제대로 초기화되질 않을 것이다.

 

그리고 플레이어가 방안에 있다면 방목록은 출력되지 않는다.(갱신이 되지않고, 방에 들어가며 방목록을 초기화하며 들어가기 때문.)