Photon Engine

[Unity Photon] 공부 2(로비 UI)

때류기 2023. 10. 22. 17:56

처음에는 간단하게 포톤 네트워크와 연결하고 자동으로 방을 생성하는 방법에 대해 공부해봤습니다.

이번엔 로비의 사용자 인터페이스(UI)에 대해 공부해볼까 합니다.

 

정보 출처: https://doc.photonengine.com/ko-kr/pun/current/demos-and-tutorials/pun-basics-tutorial/lobby-ui

 

1. 플레이 버튼

현재 로비는 접속하면 룸을 자동으로 안내해주게 했는데, 이번에는 방을 선택하여 플레이할 수 있도록 변경해보겠습니다.

 

1. 캔버스에 UILauncher라는 빈 오브젝트를 생성

2. UILauncher의 자식으로 서버에 접속하는 버튼을 생성

3. 생성후 버튼의 이름과, Text의 내용을 Play Button으로 변경

 

 

 

 

다음으로 Launcher의 UI들을 관리해주는 UILauncher  스크립트를 생성하겠습니다.

 

1. UILauncher 스크립트를 생성

2. 아래와 같이 코드를 작성하여 버튼 클릭 이벤트를 등록

3. Launcher 스크립트의 Start()의 내용 비우기

using UnityEngine;
using UnityEngine.UI;

namespace Com.MyCompany.MyGame
{

    public class UILauncher : MonoBehaviour
    {

        [SerializeField] private Button _playButton;
        [SerializeField] private Launcher _launcher;

        private void Start()
        {
            //버튼클릭시 _launcher.Connect()가 실행될 수 있도록 함.
            _playButton.onClick.AddListener(_launcher.Connect);
        }
    }
}

수정 전                                                                                                         수정 후

 

이제 버튼 클릭으로 네트워크를 연결할 것이기 때문에 Start 함수의 Connect()는 필요가 없게 되었습니다.

지금 상태에선 플레이 버튼을 누르기 전까지는 네트워크에 접속하지 않을 것 입니다.

 

 

2. 플레이어 이름

전형적인 게임에서 중요한 것중 하나는 자신의 이름을 가지고 있으며, 누구를 상대하고 있는 지 알 수 있어야합니다.

그러므로 PlayerPrefs에 이름의 값을 저장하고 사용하도록 해보겠습니다.

 

1. PlayerNameInputField 스크립트 생성
2. 아래 코드 내용 작성

3. Canvas에 InputField생성후 이름을 Name InputField로 변경

4. Name InputField에 PlayerNameInputField 스크립트 추가

using UnityEngine;
using UnityEngine.UI;

using Photon.Pun;
using Photon.Realtime;

//namespace는 필수는 아니나 다른 에셋과 개발자의 코드와의 충돌을 방지하기위해 작성
namespace Com.MyCompany.MyGame
{
    //이 스크립트를 오브젝트에 추가시 오브젝트에 InputField컴포넌트가 없을때 자동으로 InputField컴포넌트가 추가
    [RequireComponent(typeof(InputField))]
    public class PlayerNameInputField : MonoBehaviour
    {
        //오타를 방지하기 위해 PlayerPrefs 키 이름 저장
        static string _playerNamePrefKey = "PlayerName";


        private void Start()
        {
            //문자열 초기화
            //string.Empty를 사용한 이유는 내부적으로 object를 생성하지 않음
            string defaultName = string.Empty;
            InputField inputField = GetComponent<InputField>();

            if (inputField != null)
            {
                //inputField의 Text내용이 변경될때마다 SetPlayerName()함수가 실행되도록 이벤트 등록
                inputField.onValueChange.AddListener(SetPlayerName);

                //PlayerPrefs에 해당 키가 저장되있나 확인
                if (PlayerPrefs.HasKey(_playerNamePrefKey))
                {
                    //키에 저장되있는 String값을 받아와 defalutName에 넣어준다.
                    defaultName = PlayerPrefs.GetString(_playerNamePrefKey);
                    inputField.text = defaultName;
                }
            }

            //닉네임 지정
            PhotonNetwork.NickName = defaultName;
        }

        //이름을 변경하는 함수
        public void SetPlayerName(string value)
        {
            //value가 null이거나 비어있으면?
            if(string.IsNullOrEmpty(value))
            {
                Debug.LogError("플레이어의 이름이 null이거나 비어 있습니다.");
                return;
            }
            
            //닉네임 변경
            PhotonNetwork.NickName = value;

            //키의 String값을 value로 변경
            PlayerPrefs.SetString(_playerNamePrefKey, value);
        }
    }
}

여기까지 진행하고 InputField에 텍스트를 입력 후 게임을 끄고 다시 키게되더라도 저번에 입력했던 텍스트가 저장되있는 것을 볼 수 있습니다.

 

 

3. 연결 진행과정

다음으로 InputField와 Play Button을 감추고 간단한 문자열인 "Connecting..."으로 대체하고 필요시 다시 교체하도록 해보겠습니다.

1. Canvas에 Create Empty 생성(이름: Control Panel)

2. Play Button과 Name InputField를 Control Panel의 자식으로 둠

3. Canvas/UILauncher에 Text 생성(이름 : Progress Label)후 텍스트 내용을 Connecting...으로 변경

4. UILauncher에 아래의 코드 추가

5. UILauncher 인스펙터창의 변수 할당

6.Launcher 스크립트에 UILauncher변수 추가(이름 _uiLauncher)

7.Launcher 인스펙터창 변수칸에 UILauncher등록

8.Launcher 스크립트의 Start(), OnDisconnected()안에 _uiLauncher.DisconnectedUI() 코드 삽입

   Connect()안에 _uiLauncher.ConnectedUI() 코드 삽입

 

using UnityEngine;
using UnityEngine.UI;

namespace Com.MyCompany.MyGame
{

    public class UILauncher : MonoBehaviour
    {

        [SerializeField] private Button _playButton;
        
        //두개의 변수 추가
        [SerializeField] private GameObject _controlPanel;
        [SerializeField] private GameObject _progressLabel;

        [SerializeField] private Launcher _launcher;

        private void Start()
        {
            //버튼클릭시 _launcher.Connect()가 실행될 수 있도록 함.
            _playButton.onClick.AddListener(_launcher.Connect);
        }


	//아래의 두 함수 추가
        //연결됬을 경우의 UI를 설정하는 함수
        public void ConnectedUI()
        {
            _progressLabel.SetActive(true);
            _controlPanel.SetActive(false);
        }

        //연결되지 않았을 경우의 UI를 설정하는 함수
        public void DisconnectedUI()
        {
            _progressLabel.SetActive(false);
            _controlPanel.SetActive(true);
        }
    }
}

 

using UnityEngine;
using Photon.Pun;
using Photon.Realtime;


//namespace는 필수는 아니나 다른 에셋과 개발자의 코드와의 충돌을 방지하기위해 사용
namespace Com.MyCompany.MyGame
{

    //MonoBehaviourPunCallbacks
    //.photonView와 PUN이 호출할 수 있는 모든 콜백 / 이벤트를 제공하는 클래스.
    //클래스에서 제공하는 이벤트 / 메서드를 재정의하여 사용
    public class Launcher : MonoBehaviourPunCallbacks
    {
        //게임 버전을 나타내는 변수
        //이미 출시되어 프로젝트에 큰 변경사항이 있을 때 까진 "1"을 유지
        private string _gameVersion = "1";

        //아래코드 추가
        [SerializeField] private UILauncher _uiLauncher;

        //방의 최대 입장인원
        [SerializeField] private byte _maxPlayerPerRoom = 4;


        private void Awake()
        {
            //이 값이 true일 때 MasterClient는 PhotonNetwork.LoadLevel()을
            //호출 가능하며 모든 연결된 플레이어들은 동일한 레벨을 자동적으로 로드 가능
            PhotonNetwork.AutomaticallySyncScene = true;
        }

        private void Start()
        {
            //UI 변경
            _uiLauncher.DisconnectedUI();
        }


        public void Connect()
        {
            //포톤 네트워크와 연결이 됬을 경우 true, 연결되지 않았을 경우 false를 반환
            //만약 포톤 네트워크와 연결되었을 경우?
            if (PhotonNetwork.IsConnected)
            {
                //현재 사용되는 로비의 입장 가능한 방에 참여. 입장 가능한 방이 없으면 실패 
                //입장 성공시 OnJoinedRoom함수 호출
                //입장 실패시 OnJoinRandomFailed함수 호출
                PhotonNetwork.JoinRandomRoom();
            }
            //연결되지 않았을 경우
            else
            {
                //게임 버전을 설정한다.
                PhotonNetwork.GameVersion = _gameVersion;

                //Photon Editer에 설정된 값대로 서버 접속을 시작하는 지점
                //접속에 성공하면 OnConnectedToMaster 함수 호출(콜백)
                PhotonNetwork.ConnectUsingSettings();
            }

            //UI변경
            _uiLauncher.ConnectedUI();
        }

        //MonoBehaviourPunCallbacks의 함수
        //클라이언트가 마스터 서버에 연결되어 작업을 수행할 준비가 되면 호출
        //PhotonNetwork.ConnectUsingSettings()로 서버 접속이 성공하면 이 함수 호출
        public override void OnConnectedToMaster()
        {
            Debug.Log("서버 접속 성공!");

            //현재 사용되는 로비의 입장 가능한 방에 참여. 입장 가능한 방이 없으면 실패 
            //입장 성공시 OnJoinedRoom함수 호출
            //입장 실패시 OnJoinRandomFailed함수 호출
            PhotonNetwork.JoinRandomRoom();
        }

        //MonoBehaviourPunCallbacks의 함수
        //서버와의 연결이 끊은 후 호출
        //PhotonNetwork.Disconnect()가 성공하면 호출
        public override void OnDisconnected(DisconnectCause cause)
        {
            Debug.LogWarningFormat("서버연결 끊어짐!{0}", cause);

            //UI변경
            _uiLauncher.DisconnectedUI();
        }

        //MonoBehaviourPunCallbacks의 함수
        //PhotonNetwork.JoinRandomRoom()로 방 참가가 실패하면 호출
        public override void OnJoinRandomFailed(short returnCode, string message)
        {
            Debug.Log("랜덤 매칭 실패!");

            //방을 생성하는 함수
            //변수목록( roomName = 방의 이름, RoomOptions = 최대 입장 가능 인원, 초기 사용자 정의, 룸 속성등을 설정 가능
            //RoomOptions의 자세한 설명 https://doc-api.photonengine.com/en/pun/v1/class_room_options.html
            //typedLobby = null인 경우 룸은 형재 사용되는 로비에 자동 생성[명시하지 않은 경우 "default"]
            PhotonNetwork.CreateRoom("방 이름", new RoomOptions {MaxPlayers = _maxPlayerPerRoom});
        }

        //MonoBehaviourPunCallbacks의 함수
        //방에 참가하면 호출
        //PhotonNetwork.CreateRoom(), PhotonNetwork.JoinedRoom()이 성공하면 호출
        public override void OnJoinedRoom()
        {
            Debug.Log("방 접속 성공!");
        }
    }
}

 

 

여기까지 진행하시면 초기 시작시 InputField와 Button만 보일 것이고 Button클릭시 Connecting...이라는 글자로 변경되는것을 보실 수 있습니다!

'Photon Engine' 카테고리의 다른 글

[Unity Photon] 공부 3(게임 씬)  (0) 2023.10.24
[Unity Photon] 공부 1(로비)  (0) 2023.10.20