🏆 목차.
🛒 개요
저번 글에서는 타이틀 화면에서 닉네임을 입력하고 로비로 진입을 하는 기능까지 구현해 봤습니다.
이번에는 진입한 로비에서 방을 만들거나 만들어진 방 목록을 눌러 방 입장을 하는 기능을 구현해 보겠습니다.
일단 간단하게 아래 사진과 같이 UI를 구성해 봤습니다.
방 생성 버튼과 방 입장 버튼은 모두 상호작용 비활성화 상태이고 특정 조건을 만족하면 활성화가 되도록 했습니다.
🎨 포톤 방 만들기 및 입장 코드
LobbyManager.cs
using Photon.Pun;
using Photon.Realtime;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using static UnityEngine.EventSystems.PointerEventData;
public class LobbyManager : MonoBehaviourPunCallbacks
{
[SerializeField] InputField input_RoomName;
[SerializeField] InputField input_MaxPlayer;
[SerializeField] Button btn_CreateRoom;
[SerializeField] Button btn_JoinRoom;
[SerializeField] GameObject roomListItem;
public Transform rtContent;
// 방 목록을 가지고 있는 Dictionaly 변수
Dictionary<string,RoomInfo> dicRoomInfo = new Dictionary<string, RoomInfo>();
void Start()
{
input_RoomName.onValueChange.AddListener(OnNameValueChanged);
input_MaxPlayer.onValueChange.AddListener(OnPlayerValueChange);
btn_CreateRoom.onClick.AddListener(OnClickCreateRoom);
btn_JoinRoom.onClick.AddListener(OnClickJoinRoom);
}
//방 목록의 변화가 있을 때 호출되는 함수
public override void OnRoomListUpdate(List<RoomInfo> roomList)
{
base.OnRoomListUpdate(roomList);
//Content에 자식으로 붙어있는 Item을 다 삭제
DeleteRoomListItem();
//dicRoomInfo 변수를 roomList를 이용해서 갱신
UpdateRoomListItem(roomList);
//dicRoom을 기반으로 roomListItem을 만들자
CreateRoomListItem();
}
void SelectRoomItem(string roomName)
{
input_RoomName.text = roomName;
}
void DeleteRoomListItem()
{
foreach (Transform tr in rtContent)
{
Destroy(tr.gameObject);
}
}
void UpdateRoomListItem(List<RoomInfo> roomList)
{
foreach (RoomInfo info in roomList)
{
//dicRoomInfo에 info 의 방이름으로 되어있는 key값이 존재하는가
if (dicRoomInfo.ContainsKey(info.Name))
{
//만약에 방이 삭제되었으면?
if (info.RemovedFromList)
{
dicRoomInfo.Remove(info.Name); //삭제
continue;
}
}
dicRoomInfo[info.Name] = info; //추가
}
}
void CreateRoomListItem()
{
foreach(RoomInfo info in dicRoomInfo.Values)
{
//방 정보 생성과 동시에 ScrollView-> Content의 자식으로 하자
GameObject go = Instantiate(roomListItem, rtContent);
//생성된 item에서 RoomListItem 컴포넌트를 가져온다.
RoomListItem item = go.GetComponent<RoomListItem>();
//가져온 컴포넌트가 가지고 있는 SetInfo 함수 실행
item.SetInfo(info.Name, info.PlayerCount, info.MaxPlayers);
//item 클릭되었을 때 호출되는 함수 등록
item.onDelegate = SelectRoomItem;
}
}
void OnNameValueChanged(string s)
{
btn_JoinRoom.interactable = s.Length > 0;
if (input_RoomName.text == "")
btn_CreateRoom.interactable = false;
}
void OnPlayerValueChange(string s)
{
btn_CreateRoom.interactable = s.Length > 0;
if(input_MaxPlayer.text =="")
btn_CreateRoom.interactable = false;
}
// 생성 버튼 클릭시 호출되는 함수
public void OnClickCreateRoom()
{
//방 옵션
RoomOptions options = new RoomOptions();
options.MaxPlayers = int.Parse(input_MaxPlayer.text);
//방 목록에 보이게 할것인가?
options.IsVisible = true;
//방에 참여 가능 여부
options.IsOpen = true;
//방 생성
PhotonNetwork.CreateRoom(input_RoomName.text,options);
}
public override void OnCreateRoomFailed(short returnCode, string message)
{
base.OnCreateRoomFailed(returnCode, message);
Debug.Log("방 생성 실패" + message) ;
}
public override void OnCreatedRoom()
{
base.OnCreatedRoom();
Debug.Log("방 생성 성공");
}
public void OnClickJoinRoom()
{
// 방 참여
PhotonNetwork.JoinRoom(input_RoomName.text);
}
public override void OnJoinedRoom()
{
base.OnJoinedRoom();
Debug.Log("방 입장 성공");
}
public override void OnJoinRoomFailed(short returnCode, string message)
{
base.OnJoinRoomFailed(returnCode, message);
Debug.Log("방 입장 실패" + message);
}
void JoinOrCreateRoom()
{
//방 옵션
RoomOptions options = new RoomOptions();
options.MaxPlayers = int.Parse(input_MaxPlayer.text);
//방 목록에 보이게 할것인가?
options.IsVisible = true;
//방에 참여 가능 여부
options.IsOpen = true;
PhotonNetwork.JoinOrCreateRoom(input_RoomName.text, options,TypedLobby.Default);
}
void JoinRandomRoom()
{
PhotonNetwork.JoinRandomRoom();
} // 참여 버튼 클릭시 호출되는 함수
public override void OnJoinRandomFailed(short returnCode, string message)
{
base.OnJoinRandomFailed(returnCode, message);
}
}
RoomListItem.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class RoomListItem : MonoBehaviour
{
public Text roomInfo;
//클릭되었을때 호출되는 함수
public Action<string> onDelegate;
public void SetInfo(string roomName, int currPlayer, int maxPlayer)
{
name = roomName;
roomInfo.text = roomName + '(' + currPlayer+ '/' + maxPlayer +')';
}
public void OnClick()
{
//만약 onDelegate 에 무언가 들어있다면 실행
if (onDelegate != null)
{
onDelegate(name);
}
////InputRoomName 찾아오기
//GameObject go =GameObject.Find("InputRoomName");
////찾아온 게임오브젝트에서 InputField 컴포넌트 가져오기
//InputField inputField = go.GetComponent<InputField>();
////가져온 컴포넌트에서 text 값을 나의 이름으로 셋팅하기
//inputField.text = name;
}
}
RoomListItem 클래스는 방 목록 버튼에 컴포넌트로 추가해 주고 프리팹화 해줍니다.
이렇게 프리팹화 한 방 이름 버튼은 ScrollView 하위에 방이 생성될 때마다 추가해 줄 것입니다.
🧶 코드 설명
간단한 로직을 제외하고 핵심코드 위주로 설명하겠습니다.
OnRoomListUpdate
- 부모 클래스의 함수에서 정의된 함수로 자식에서 재정의 했습니다.
로비에 변경사항이 있을 때마다 호출됩니다.
RoomInfo를 리스트로 받아오고 호출될 때마다 DeleteRoomListItem,
UpdateRoomListItem , CreateRoomListItem 함수를 호출합니다.
UpdateRoomListItem
- RoomInfo는 포톤에서 제공되는 클래스로 이름 그대로 방의 정보를 담고 있는 클래스입니다.
RoomInfo를 리스트로 받아오고 방이 없다면 Dictionary에서 삭제를 해줍니다.
그리고 Dictionary의 키 값인 Name에 info를 추가해 줬습니다.
CreateRoomListItem
- 업데이트된 방의 정보를 받아와서 방 목록을 새로 생성해 줍니다.
Diectionary에 담아둔 방의 정보를 하나씩 꺼내서 새로 생성한 방 목록에 정보를 적용해 줍니다.
item의 델리게이트에 호출되는 함수를 등록해 줬습니다.
OnClickCreateRoom
- 방 생성 버튼에 AddListener로 이벤트 핸들러에 등록해 주었습니다.
RoomOptions 클래스는 포톤에서 제공하는 클래스입니다.
방 생성 버튼이 눌리면 방의 옵션을 설정해 주는데 최대 인원과 방 목록에 보이는지,
방에 참여가 가능한지 여부를 설정해 줬습니다.
설정이 끝나면 PhotonNetwork.CreateRoom를 통해 방을 생성해 줍니다. 첫 번째 매개변수는 방의 이름입니다.
OnClickJoinRoom
- 방 참가 버튼에 AddListener로 이벤트 핸들러에 등록해 주었습니다.
PhotonNetwork.JoinRoom으로 매개변수에 들어가는 방 이름에 입장하게 됩니다.
🎯 결과
에디터 창을 2 개 열어서 하나로 방을 생성하고, 다른 에디터창에서 방 입장을 누르면 로그에 방 입장 성공이 뜨는 것을 볼 수 있습니다.
참고로 다른 컴퓨터에서 해당 목록을 보기 위해서는 전에 입력한 Run 아이디를 똑같이 입력해줘야 합니다.
아직 방 입장 후 UI는 추가하지 않았기 때문에 아무런 변화가 없어 보이지만 실제 내부에서는 생성된 방에 들어간 상태입니다.
다음 글에서는 방에 입장하고 서로 대화도 하며 상호작용 하는 기능을 구현해 보겠습니다.
'유니티' 카테고리의 다른 글
[Unity] Application.lowMemory 개념과 활용 (1) | 2024.01.25 |
---|---|
[Unity 3D] 오브젝트가 컬링되는 이유 (1) | 2023.10.28 |
[Unity] 포톤 서버 로비 입장하기 (0) | 2023.10.02 |
[Unity] 포톤 서버 구축 (0) | 2023.10.02 |
[Unity] 최적화 : Mesh Baker(메쉬 결합) (0) | 2023.09.29 |