로비에 입장하면 포톤 클라우드 서버는 현재 생성된 모든 룸 목록을 전달해준다. 로비에 접속하지 않고 포톤 클라우드 서버에만 접속한 경우에는 룸 목록을 받을 수 없다. PhtonManager 스크립트에 OnRoomListUpdate콜백 함수를 추가해 룸 목록을 전달 받는지를 확인해보자.
public override void OnJoinedRoom()
//...중략
public override void OnRoomListUpdate(List<RoomInfo> roomList) {
foreach (var roomInfo in roomList) {
// 룸이 삭제된 경우
Debug.Log($"Room={roomInfo.Name} ({roomInfo.PlayerCount}/{roomInfo.MaxPlayers})");
}
}
//...중략
OnRoomListUpdate함수는 RoomInfo타입의 데이터를 리스트 자료형으로 넘겨준다. 다음 그림은 새로 빌드한 실행 파일로 세개의 룸을 생성하고 3번째 유저는 ROOM_034 룸에 입장했다. 마지막으로 유니티를 실행해 로비까지만 입장한 상태에서 콘솔뷰를 살펴보자 룸의 목록이 표시되고 ROOM_034 룸의PlayerCount와MaxPlayer가 2/20으로 표시된 것을 알 수 있다.
룸목록은 룸정보의 변화가 발생할 때마다 콜백 함수가 호출된다. 다만 삭제된 룸에 대한 정보도 넘어온다.
룸의 삭제여부는 RemovedFromList속성으로 알수 있다. 따라서 룸목록을 Dictionary타입의 자료형으로 관리한다. 앞서 작성했던 OnRoomListUpdate함수를 다음과 같이 수정한다.
룸 목록은 룸 이름과 해당 룸을 ScrollView하위에 생성할 RoomItem프리팹을 쌍으로 저장해야 관리하기 편리하기 때문에 dictionary자료형을 사용한다. c#에서 Dictionary를 사용하기 위해서 System.Collections.Generic 네임스페이스를 선언한다.
using System.Collections.Generic;
클래스 선언부에 룸목록에 대한 데이터를 저장할 rooms를 선언한다.
private Dictionary<string, GameObject> rooms = new Dictionary<string, GameObject>();
RoomItem프리팹을 로드할 변수를 Awake()에서 할당한다.
// RoomItem 프리팹 로드
roomItemPrefab = Resources.Load<GameObject>("RoomItem");
룸 목록이 갱신되면 호출되는 OnRoomListUpdate함수의 로직을 간단히 설명하면
public override void OnRoomListUpdate(List<RoomInfo> roomList) {
// 삭제된 RoomItem 프리팹을 저장할 임시변수
GameObject tempRoom = null;
foreach (var roomInfo in roomList) {
if (roomInfo.RemovedFromList == true) { // 룸이 삭제된 경우
// 딕셔너리에서 룸 이름으로 검색해 저장된 RoomItem 프리팹를 추출
rooms.TryGetValue(roomInfo.Name, out tempRoom);
Destroy(tempRoom); // RoomItem 프리팹 삭제
rooms.Remove(roomInfo.Name); // 딕셔너리에서 해당 룸 이름의 데이터를 삭제
} else // 룸 정보가 변경된 경우
{
// 룸 이름이 딕셔너리에 없는 경우 새로 추가
if (rooms.ContainsKey(roomInfo.Name) == false) {
// RoomInfo 프리팹을 scrollContent 하위에 생성
GameObject roomPrefab = Instantiate(roomItemPrefab, scrollContent);
// 룸 정보를 표시하기 위해 RoomInfo 정보 전달
roomPrefab.GetComponent<RoomData>().RoomInfo = roomInfo;
// 딕셔너리 자료형에 데이터 추가
rooms.Add(roomInfo.Name, roomPrefab);
} else // 룸 이름이 딕셔너리에 없는 경우에 룸 정보를 갱신
{
rooms.TryGetValue(roomInfo.Name, out tempRoom); 룸검색해 RoomItem을 tempRoom에 저장
tempRoom.GetComponent<RoomData>().RoomInfo = roomInfo; //룸 정보 전달
}
}
Debug.Log($"Room={roomInfo.Name} ({roomInfo.PlayerCount}/{roomInfo.MaxPlayers})");
}
}
버튼 이벤트 동적 연결
OnRoomListUpdate() 함수에서 룸에 대한 정보에 따라서 RoomItem프리팹을 동적으로 생성하거나 이미 만들어진 RoomItem 프리팹에 룸 정보를 저장하고 클릭했을 때 버튼 이벤트에서 룸에 접속하기 위해 새로운 스크립트를 생성하고 이름을 RoomData로 지정한다. 스크립트는 다음과 같이 작성하고 프로젝트 뷰의 Resource 폴더에 있는 RoomItem 프리팹에 추가한다.
using UnityEngine;
using Photon.Pun;
using Photon.Realtime;
using TMPro;
public class RoomData : MonoBehaviour {
private RoomInfo _roomInfo;
private TMP_Text roomInfoText; // 하위에 있는 TMP_Text를 저장할 변수
private PhotonManager photonManager; // PhotonManager 접근 변수
// 프로퍼티 정의
public RoomInfo RoomInfo {
get {
return _roomInfo;
}
set {
_roomInfo = value;
// 룸 정보 표시
roomInfoText.text = $"{_roomInfo.Name} ({_roomInfo.PlayerCount}/{_roomInfo.MaxPlayers})";
// 버튼 클릭 이벤트에 함수 연결
GetComponent<UnityEngine.UI.Button>().onClick.AddListener(() => OnEnterRoom(_roomInfo.Name));
}
}
void Awake() {
roomInfoText = GetComponentInChildren<TMP_Text>();
photonManager = GameObject.Find("PhotonManager").GetComponent<PhotonManager>();
}
void OnEnterRoom(string roomName) {
// 유저명 설정
photonManager.SetUserId();
//룸의 속성 정의
RoomOptions ro = new RoomOptions();
ro.MaxPlayers = 20; //룸에 입장할 수 있는 최대 접속자수
ro.IsOpen = true; // 룸의 오픈 여부
ro.IsVisible = true; //로비에서 룸 목록에 노출시킬지 여부
// 룸 접속
PhotonNetwork.JoinRoom(roomName);
}
}
RoomData 스크립트는 OnRoomListUpdate에서 룸정보가 갱신될때 마다 접근해 roomInfo 데이터를 넘겨받아서 내부적으로 저장하고하위에 있는 텍스트 UI에 룸 이름과 접속자 정보를 표시한다. 또한 버튼을 클릭했을 때 룸에 접속하는 함수를 람다식으로 연결한다.
//룸정보 표시
roomInfoText.text = $"{_roomInfo.Name} ({_roomInfo.PlayerCount}/{_roomInfo.MaxPlayers})";
// 버튼 클릭 이벤트에 함수 연결
GetComponent<UnityEngine.UI.Button>().onClick.AddListener(() => OnEnterRoom(_roomInfo.Name));
예제 게임을 다시 빌드하고 룸을 생성하고 입장한 후 유니티 에디터에서 로비에 입장만 한 상태에서 룸 목록이 표시 되는지 확인해보자. 다음은 룸을 2개 생성하고 2명의 유저는 같은 방에 들어가고 한명의 유저는 혼자 룸에 입장한 시나리오일 때의 룸 목록이다. 룸목록에 표시된 버튼을 클릭하며 해당 룸으로 입장하는지 확인해보자
'유니티게임강좌 > 포톤클라우드 네트워크' 카테고리의 다른 글
[포톤클라우드] 룸 목록 UI구현 (0) | 2023.04.05 |
---|---|
[포톤클라우드] 게임룸입장 (0) | 2023.04.05 |
[포톤클라우드] 로그인 UI 제작 (0) | 2023.04.05 |
[포톤클라우드] 로비제작 (0) | 2023.04.05 |
[포톤클라우드] 피격및 리스폰(재생) (0) | 2023.04.05 |