728x90

🏆 목차.

  1. 개요
  2. 포톤 방 만들기 및 입장 코드
  3. 코드 설명
  4. 결과

 

🛒 개요

 

저번 글에서는 타이틀 화면에서 닉네임을 입력하고 로비로 진입을 하는 기능까지 구현해 봤습니다.

이번에는 진입한 로비에서 방을 만들거나 만들어진 방 목록을 눌러 방 입장을 하는 기능을 구현해 보겠습니다.

 

일단 간단하게 아래 사진과 같이 UI를 구성해 봤습니다.

방 생성 버튼과 방 입장 버튼은 모두 상호작용 비활성화 상태이고 특정 조건을 만족하면 활성화가 되도록 했습니다.

 

로비-UI
로비 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는 추가하지 않았기 때문에 아무런 변화가 없어 보이지만 실제 내부에서는 생성된 방에 들어간 상태입니다.

다음 글에서는 방에 입장하고 서로 대화도 하며 상호작용 하는 기능을 구현해 보겠습니다.

 

 

 

 

728x90

+ Recent posts