Unity
[포톤] 직접 예제 만들어보기 (랜덤 입장할 때, 필터링하기 / 매칭하기)
푸쿠이
2021. 9. 29. 16:53
참고
https://doc.photonengine.com/ko-kr/pun/current/gameplay/synchronization-and-state
필터링하기
CustomPropertes를 사용하면 된다.
되게 간단하다.
1. CreateRoom(설정 값 A)
방을 생성할 때, 필터링하고 싶은 설정 값을 RoomOption 변수의 CustomProperties에 대입한다.
// UI에서 값 얻어오기.
byte maxPlayers = byte.Parse(m_dropdown_RoomMaxPlayers.options[m_dropdown_RoomMaxPlayers.value].text); // 드롭다운에서 값 얻어오기.
byte maxTime = byte.Parse(m_dropdown_MaxTime.options[m_dropdown_MaxTime.value].text);
// 방 옵션 설정하기.
RoomOptions roomOptions = new RoomOptions();
roomOptions.MaxPlayers = maxPlayers; // 인원 지정.
roomOptions.CustomRoomProperties = new ExitGames.Client.Photon.Hashtable() { { "maxTime", maxTime } }; // 게임 시간 지정.
roomOptions.CustomRoomPropertiesForLobby = new string[] { "maxTime" }; // 여기에 키 값을 등록해야, 참가할 때 필터링이 가능하다.
// 방 생성할 때, 옵션 넣어주기.
PhotonNetwork.CreateRoom(null, roomOptions);
2. JoinRandomRoom(설정 값 A)
설정했던 CustomProperties 값을 토대로 필터링해서 입장한다.
// UI에서 값 얻어오기.
byte maxPlayers = byte.Parse(m_dropdown_RoomMaxPlayers.options[m_dropdown_RoomMaxPlayers.value].text); // 드롭다운에서 값 얻어오기.
byte maxTime = byte.Parse(m_dropdown_MaxTime.options[m_dropdown_MaxTime.value].text);
// 방 옵션 설정한 것 그대로 HashTable 만들어준다. 이걸로 필터링하는 것이다.
ExitGames.Client.Photon.Hashtable customProperties = new ExitGames.Client.Photon.Hashtable() { { "maxTime", maxTime } };
// 방 입장할 때, 필터링할 옵션 넣어주기.
// maxPlayers는 자주 쓰이니까, 따로 변수로 빼준 듯하다.
PhotonNetwork.JoinRandomRoom(customProperties, maxPlayers);
나는 매칭 시스템을 할 것이라서 생성과 입장을 따로 두지 않았다.
방이 없으면 만들고, 방이 있으면 참가하도록 했다.
// UI에서 값 얻어오기.
byte maxPlayers = byte.Parse(m_dropdown_RoomMaxPlayers.options[m_dropdown_RoomMaxPlayers.value].text); // 드롭다운에서 값 얻어오기.
byte maxTime = byte.Parse(m_dropdown_MaxTime.options[m_dropdown_MaxTime.value].text);
// 방 옵션 설정하기.
RoomOptions roomOptions = new RoomOptions();
roomOptions.MaxPlayers = maxPlayers; // 인원 지정.
roomOptions.CustomRoomProperties = new ExitGames.Client.Photon.Hashtable() { { "maxTime", maxTime } }; // 게임 시간 지정.
roomOptions.CustomRoomPropertiesForLobby = new string[] { "maxTime" }; // 여기에 키 값을 등록해야, 참가할 때 필터링이 가능하다.
// 방 참가를 시도하고, 실패하면 생성해서 참가함.
PhotonNetwork.JoinRandomOrCreateRoom(
expectedCustomRoomProperties: new ExitGames.Client.Photon.Hashtable() { { "maxTime", maxTime } }, expectedMaxPlayers: maxPlayers, // 참가할 때의 기준.
roomOptions: roomOptions // 생성할 때의 기준.
);
매칭 시스템
전체적인 흐름은
1. 매칭 버튼을 누른다. (예를 들어서 최대 플레이어 수를 3으로 했다치자.)
-> 방이 없으면 만든다.
-> 방이 있으면 참가한다.
2. 방에 참가해서 기다린다.
-> 플레이어 수가 채워지지 않았다면, 로딩 UI 보여주면서 기다린다.
-> 플레이어 수가 채워졌다면, 방에 입장한 사람 모두가 씬을 이동한다.
움짤로 보는 게 편할 것 같다.
같은 설정 값일 땐, 서로 매칭이 된다.
다른 설정 값이면, 아예 방이 달라져서 만나지 않는다.
매칭 취소하면, 이렇게.
잘 동작하는 것 같다!!
전체 코드는 이렇다.
using UnityEngine;
using UnityEngine.UI;
using Photon.Pun;
using Photon.Realtime;
public class MyLauncher : MonoBehaviourPunCallbacks
{
public InputField m_inputField_Nickname; // 닉네임 입력받는 곳.
public Dropdown m_dropdown_RoomMaxPlayers; // 최대 인원 몇 명까지 할지.
public Dropdown m_dropdown_MaxTime; // 게임 시간은 몇 초로 정할 건지.
public GameObject m_panel_Loading; // 로딩 UI.
public Text m_text_CurrentPlayerCount; // 로딩 UI 중에서 현재 인원 수를 나타냄.
void Awake()
{
// 마스터 클라이언트는 PhotonNetwork.LoadLevel()를 호출할 수 있고, 모든 연결된 플레이어는 자동적으로 동일한 레벨을 로드한다.
PhotonNetwork.AutomaticallySyncScene = true;
m_panel_Loading.SetActive(false);
}
void Start()
{
print("서버 연결 시도.");
PhotonNetwork.ConnectUsingSettings();
}
public void JoinRandomOrCreateRoom()
{
string nick = m_inputField_Nickname.text;
print($"{nick} 랜덤 매칭 시작.");
PhotonNetwork.LocalPlayer.NickName = nick; // 현재 플레이어 닉네임 설정하기.
// UI에서 값 얻어오기.
byte maxPlayers = byte.Parse(m_dropdown_RoomMaxPlayers.options[m_dropdown_RoomMaxPlayers.value].text); // 드롭다운에서 값 얻어오기.
int maxTime = int.Parse(m_dropdown_MaxTime.options[m_dropdown_MaxTime.value].text);
RoomOptions roomOptions = new RoomOptions();
roomOptions.MaxPlayers = maxPlayers; // 인원 지정.
roomOptions.CustomRoomProperties = new ExitGames.Client.Photon.Hashtable() { { "maxTime", maxTime } }; // 게임 시간 지정.
roomOptions.CustomRoomPropertiesForLobby = new string[] { "maxTime" }; // 여기에 키 값을 등록해야, 필터링이 가능하다.
// 방 참가를 시도하고, 실패하면 생성해서 참가함.
PhotonNetwork.JoinRandomOrCreateRoom(
expectedCustomRoomProperties: new ExitGames.Client.Photon.Hashtable() { { "maxTime", maxTime } }, expectedMaxPlayers: maxPlayers, // 참가할 때의 기준.
roomOptions: roomOptions // 생성할 때의 기준.
);
}
public void CancelMatching()
{
print("매칭 취소.");
m_panel_Loading.SetActive(false);
print("방 떠남.");
PhotonNetwork.LeaveRoom();
}
private void UpdatePlayerCounts()
{
m_text_CurrentPlayerCount.text = $"{PhotonNetwork.CurrentRoom.PlayerCount} / {PhotonNetwork.CurrentRoom.MaxPlayers}";
}
#region 포톤 콜백 함수
public override void OnConnectedToMaster()
{
print("서버 접속 완료.");
}
public override void OnJoinedRoom()
{
print("방 참가 완료.");
Debug.Log($"{PhotonNetwork.LocalPlayer.NickName}은 인원수 {PhotonNetwork.CurrentRoom.MaxPlayers} 매칭 기다리는 중.");
UpdatePlayerCounts();
m_panel_Loading.SetActive(true);
}
public override void OnPlayerEnteredRoom(Player newPlayer)
{
Debug.Log($"플레이어 {newPlayer.NickName} 방 참가.");
UpdatePlayerCounts();
if (PhotonNetwork.IsMasterClient)
{
// 목표 인원 수 채웠으면, 맵 이동을 한다. 권한은 마스터 클라이언트만.
// PhotonNetwork.AutomaticallySyncScene = true; 를 해줬어야 방에 접속한 인원이 모두 이동함.
if (PhotonNetwork.CurrentRoom.PlayerCount == PhotonNetwork.CurrentRoom.MaxPlayers)
{
PhotonNetwork.LoadLevel("Game");
}
}
}
public override void OnPlayerLeftRoom(Player otherPlayer)
{
Debug.Log($"플레이어 {otherPlayer.NickName} 방 나감.");
UpdatePlayerCounts();
}
#endregion
}