Unity Photon.Pun2 멀티 플레이
스파르타 내배캠 41일차 TIL
C3조_ 이석삼조
팀프로젝트 본격 시작에 앞서 멀티플레이 강의를 다시 한 번 공부했다. 단순하게 방을 생성해서 게임을 시작하는 단계에 대해서는 이해했지만 우리 팀이 원하는 멀티 플레이에 비해 단계가 많이 간소했다. 그래서 구글링과 한국 유튜브를 뒤졌지만 방 생성과 공개방, 비공개방에 대한 자세한 내용을 정리한 것을 찾지 못했다. 그래서 결국 영어 듣기를 통해 기본적인 멀티 방식을 구현했고 정리 해보려고 한다.
1. Photon, Pun Import
포톤 서버를 이용하기 위해서는 유니티 에셋 스토어에서 photon.pun을 받아야 한다. 무료로 풀려있기 때문에 서버를 처음 시작하는 사람들이 쉽게 이용할 수 있다. 에셋 스토어에서 다운을 받게 되면 프로젝트에서 임포트 해야한다.
MyAssets에서 검색 후 임포트 하게 되면 포톤 App ID를 입력해야 서버를 사용할 수 있다. App ID는 포톤 홈페이지에서 프로젝트를 올려서 받을 수 있다.
로그인 후 프로젝트를 생성하게 되면 다음과 같은 화면에서 App ID를 확인할 수 있다.
App ID는 패키지를 임포트한 후에 바로 입력 가능한 창이 있지만 가끔 창이 안 뜰 때가 있다. 그런 상황이라면 Server Setting 인스펙터에서 입력 가능하다.
2. 펀 서버 접속
1번을 완료하면 기본적으로 서버 이용이 가능해진다. 이제부터는 Pun에서 제공하는 기본 메소드를 이용할 수 있다. 서버를 이용하려면 서버에 먼저 접속해야 한다. 그러기 위해서 빈 오브젝트를 만들고 새로운 스크립트를 생성해야 한다.
private void Start()
{
Debug.Log("Connecting to Master");
PhotonNetwork.ConnectUsingSettings();
}
public override void OnConnectedToMaster()
{
Debug.Log("Connected to Master");
PhotonNetwork.JoinLobby();
PhotonNetwork.AutomaticallySyncScene = true;
}
public override void OnJoinedLobby()
{
MenuManager.instance.OpenMenu("title");
Debug.Log("Joined Lobby");
}
이 상태에서 제일 기본으로 방을 만들어 보자. 방을 만들 UI를 만들고 각 버튼을 통해 값을 받아올 수 있게 해야한다.
여기서 가장 중요한 것은 RoomOption이다. RoomOption을 만들어서 방의 설정을 입력하여 CreateRoom에 매개변수로 넘겨서 설정할 수 있다.
public void CreateRoom()
{
if (MenuManager.instance.CheckRoomName())
{
RoomOptions options = new RoomOptions(); // 초기 룸 정보 세팅
switch (roomType)
{
case RoomType.PRIVATE:
options.IsOpen = false; break;
case RoomType.PUBLIC:
options.IsOpen = true; break;
}
options.MaxPlayers = playerCnt;
PhotonNetwork.CreateRoom(MenuManager.instance.roomInputField.text, options);
MenuManager.instance.OpenMenu("loading");
}
}
위 스크립트에서는 IsOpen과 MaxPlayer만 사용했는데 photon 스크립트를 열어보면 사용 가능한 변수가 여러 개 있다. 그 중에서 가장 많이 사용하는 것을 정리 해보려고 한다.
MaxPlayer | 방에 있을 수 있는 최대 플레이어 수. 0은 '제한없음'을 의미한다. |
IsVisible | 이 룸이 로비에 나열되는지 정의한다. 보이지 않는 방은 로비 클라이언트에게 전송되는 방 목록에서 제외된다. 보이지 않는 방은 이름으로 참가할 수 있지만 무작위 매치메이킹에서는 제외된다. |
IsOpen | 이 방에 참여할 수 있는지 여부를 정의한다. 방이 닫혀 있으면 어떤 플레이어도 참여할 수 없다. 예를 들어, 플레이어 4명 중 3명이 게임 플레이를 일찍 시작하고 게임 중에 누구도 참여하는 것을 원하지 않는 경우에 적합하다. |
그 외 속성은 아래 링크에서 확인 가능하다.
Photon Unity Networking 2: RoomOptions Class Reference
Wraps up common room properties needed when you create rooms. Read the individual entries for more details. More... Wraps up common room properties needed when you create rooms. Read the individual entries for more details. This directly maps to the fields
doc-api.photonengine.com
옵션을 설정해서 방을 만들면 다른 플레이어가 들어올 수 있게 된다. 이 방을 찾을 수 있으려면 서버에 생성된 방 리스트를 확인하고 들어올 수 있어야 한다. 그래서 아래와 같이 UI를 만들고 메서드를 이용하여 방을 확인할 수 있게 작성했다.
public override void OnRoomListUpdate(List<RoomInfo> roomList)
{
// 룸 리스트 초기화
foreach(Transform trans in roomListContent)
{
Destroy(trans.gameObject);
}
// 룸 리스트 업데이트
for(int i = 0; i < roomList.Count; i++)
{
if (roomList[i].RemovedFromList)
continue;
Instantiate(roomListPrefab, roomListContent).GetComponent<RoomListItem>().SetUp(roomList[i]);
}
}
이때 룸 정보를 불러와야 하기 때문에 RoomInfo를 이용했다. roominfo에는 각 방의 정보가 담겨있다. 방 갯수대로 프리팹을 불러와서 플레이어가 룸 리스트를 확인할 수 있게 했다.
이제 플레이어가 방에 들어갈 수 있게 됐다. 버튼을 누르면 아래 코드가 동작하게 된다.
public override void OnJoinedRoom()
{
Debug.Log(PhotonNetwork.CurrentRoom);
MenuManager.instance.OpenMenu("room");
MenuManager.instance.roomNameText.text = PhotonNetwork.CurrentRoom.Name;
Player[] players = PhotonNetwork.PlayerList;
for (int i = 0; i < players.Length; i++)
{
Instantiate(playerListPrefab, playerListContent).GetComponent<PlayerListItem>().SetUp(players[i]);
}
gameStartButton.SetActive(PhotonNetwork.IsMasterClient);
}
코드는 간단하다. photon에서 제공하는 player에 플레이어를 저장하고 저장된 플레이어 만큼 들어간 방에서 플레이어 닉네임을 확인할 수 있게 된다.
Trouble Shooting
여기서 문제가 생겼다. 위의 코드에서 nick2가 나갔다가 다시 그 방에 들어가게 되면 nick2 화면에 플레이어 정보가 중복으로 입력된다.
해결
그래서 위의 코드에 플레이어 리스트를 초기화한 후에 리스트를 다시 불러오도록 추가했다.
public override void OnJoinedRoom()
{
...
foreach (Transform child in playerListContent)
{
Destroy(child.gameObject);
}
...
}
마지막으로 방에 들어가서 게임을 시작하기 위한 버튼을 방 마스퍼만 누를 수 있도록 했고 방 마스터가 방을 나가면 마스터를 변경하는 로직을 추가하여 완성도를 높혔다.
public override void OnMasterClientSwitched(Player newMasterClient)
{
gameStartButton.SetActive(PhotonNetwork.IsMasterClient);
}
마무리하며
물론 아직 완성을 한 것은 아니다. public과 private의 참가를 나눠야 하고 제한 인원이 모두 찬 방은 들어갈 수 없게 해야한다. 게임의 완성이 빠르다면 욕심을 부려서 대기실에서 플레이어를 움직이고 캐릭터를 변경하고 모두 동의 하에 게임이 시작될 수 있게 만들고 싶다.
아쉬운 점은 유튜브를 참고했다는 사실이다. 처음에는 공식문서를 최대한 사용해 보려고 했지만 동작 구조를 이해 못한 상황에서 너무 어렵게 늦겨졌다. 그리고 일주일이라는 시간 안에서 멀티만 잡고 있게 되면 다른 구현이 밀릴 것 같아서 서치를 통해 구현하게 된 것 같다. 요번 기회를 통해 기본적인 매커니즘을 익혔기 때문에 다음에는 공식 문서를 참고하여 세부화 시켜보면 좋을 것 같다.
혹시나 해서 참고 영상을 첨부하도록 하겠다~
https://www.youtube.com/watch?v=zPZK7C5_BQo&list=PLhsVv9Uw1WzjI8fEBjBQpTyXNZ6Yp1ZLw&index=1