4 - 게임 매니저와 레벨
이 섹션에서는 룸 안에서 현재 플레이하고 있는 플레이어 수에 기반하여 다양한 레벨 로딩 처리에 대한 추가 기능을 다룰 것 입니다.
경기장 로딩 루틴
4개의 다른 룸을 생성하였으며 플레이어 수는 룸의 마지막 문자로 했기 때문에 룸안의 현재 플레이어 수와 관련된 씬을 바인딩하는 것은 매우 쉽습니다.
"convention over configuration" 로 알려져 있는 매우 효율적인 테크닉입니다. "configuration" 기반 접근법으로 예를 들어 주어진 룸 안의 플레이어 수로 신 이름의 테이블 목록을 찾아 유지관리하는 것이 쉽습니다.
스크립트는 그 리스트를 보고 이름이 전혀 중요하지 않은 씬으로 돌려받았을 것이다.
"configuration" 은 일반적으로 더 많은 스크립팅이 필요하기 때문에, 우리는 코드를 관련 없는 기능으로 지저분하게 하지 않고 더 빨리 코드를 작동시킬 수 있는 "개념"을 추구할 것입니다.
GameManager
스크립트를 오픈 합니다.private 메소드 영역에 새로운 메소드를 추가할 것 입니다.
GameManager
스크립트를 저장하는 것을 잊지 마세요.C#
#region Private Methods void LoadArena() { if (!PhotonNetwork.IsMasterClient) { Debug.LogError("PhotonNetwork : Trying to Load a level but we are not the master Client"); return; } Debug.LogFormat("PhotonNetwork : Loading Level : {0}", PhotonNetwork.CurrentRoom.PlayerCount); PhotonNetwork.LoadLevel("Room for " + PhotonNetwork.CurrentRoom.PlayerCount); } #endregion
GameManager
스크립트를 저장합니다
이 메소드를 호출 할 때에 현재 있는 룸의 PlayerCount
프로퍼티에 기반한 룸을 로드 할 것 입니다.
여기에서 눈여겨 봐야할 주의 할 점들이 있으며 매우 중요 합니다.
- PhotonNetwork.LoadLevel() 은 마스터 클라이언트인 경우에만 호출 되어야 합니다. 따라서 PhotonNetwork.isMasterClient 를 이용하여 마스터 클라이어인트인지를 체크 합니다.
이것을 체크하는 것은 호출자의 책임이 될 것 이며 이 섹션의 다음 파트에서 다룰 것 입니다. - PhotonNetwork.LoadLevel() 을 이용하여 원하는 레벨을 로드 합니다. 이 게임에서는 PhotonNetwork.automaticallySyncScene 을 사용하도록 해놓았기 때문에 룸 안의 모든 접속한 클라이언트에 대해 이 레벨 로드를 유니티가 직접 하는 것이 아닌 Photon 이 하도록 하였습니다.
이제 원하는 레벨을 로드하는 기능이 있으므로 플레이어들의 연결과 연결해제에 대하여 바인드 해 보겠습니다.
플레이어들의 연결 관찰
튜토리얼의 이전 장에서 Photon 콜백을 얻는 다양한 방식을 학습했으며 이제는 GameManager
가 플레이어의 연결과 연결해제를 리슨할 필요가 있습니다. 다음을 구현해 봅시다.
GameManager
스크립트를 오픈합니다.다음의 Photon 콜백을 추가하고
GameManger
스크립트를 저장합니다.C#
#region Photon Callbacks public override void OnPlayerEnteredRoom(Player other) { Debug.LogFormat("OnPlayerEnteredRoom() {0}", other.NickName); // not seen if you're the player connecting if (PhotonNetwork.IsMasterClient) { Debug.LogFormat("OnPlayerEnteredRoom IsMasterClient {0}", PhotonNetwork.IsMasterClient); // called before OnPlayerLeftRoom LoadArena(); } } public override void OnPlayerLeftRoom(Player other) { Debug.LogFormat("OnPlayerLeftRoom() {0}", other.NickName); // seen when other disconnects if (PhotonNetwork.IsMasterClient) { Debug.LogFormat("OnPlayerLeftRoom IsMasterClient {0}", PhotonNetwork.IsMasterClient); // called before OnPlayerLeftRoom LoadArena(); } } #endregion
GameManager
스크립트를 저장합니다.
이제 설정이 완료 되었습니다. 플레이어들이 참여 또는 룸을 떠날 때 마다 통지를 받게 되고 위에서 구축 해 놓은 LoadArena()
메소드를 호출 할 것 입니다. 하지만 PhotonNetwork.isMasterClient 를 이용하여 마스터인 경우에만 LoadArena()
를 호출 할 것 입니다.
이제 로비로 되돌아와서 룸에 참여할 때 맞는 씬을 로드 할 수 있습니다.
로비에서 경기장 로딩
Launcher
스크립트를 편집 합니다.OnJoinedroom()
메소드에 다음을 추가합니다.C#
// #Critical: We only load if we are the first player, else we rely on `PhotonNetwork.AutomaticallySyncScene` to sync our instance scene. if (PhotonNetwork.CurrentRoom.PlayerCount == 1) { Debug.Log("We load the 'Room for 1' "); // #Critical // Load the Room Level. PhotonNetwork.LoadLevel("Room for 1"); }
Launcher
스크립트를 저장합니다.
Launcher
씬을 오픈 후 실행하여 테스트 해 봅시다. "Play" 를 클릭하여 시스템으로 연결하고 룸에 참여하도록 합니다. 이게 다 입니다. 이제 로비가 작업하게 됩니다. 하지만 룸을 나간 경우 다시 로비로 돌아왔을 때 자동으로 재 참여 하게 됩니다. 이런... 이 문제를 해결해 보도록 합시다.
왜 이런 현상이 발상하는지 모르겠다면 "간단하게" 로그를 분석합니다. 저는 간단하게 로그 문장을 넣었으며, 문제를 파악하고 어디서 보고 어떻게 그것을 디버그 할지를 알기 위해서는 연습과 경험이 필요하기 때문에, 간단하게 파악할 수 있는 문장을 넣습니다.
이제 스스로 시도해보고 아직 소스에서 문제를 발견 하지 못했다면 같이 해 보겠습니다
Launcher
씬을 실행 합니다.- "Play" 버튼을 누르고 "Room for 1" 에 참여하여 로드될 때 까지 기다립니다.
- 유니티 콘솔 창을 clear 합니다.
- "Leave Room" 을 누릅니다.
- 유니티 콘솔 창을 관찰하여 "PUN Basics Tutorial/Launcher: OnConnectedToMaster() was called by PUN" 이 기록되어 있는지 확인 합니다.
- Launcher 씬을 중지 합니다.
- 로그 항목 "PUN Basics Tutoria/Launcher: OnConnectedToMaster() was called by PUN" 을 더블 클릭하면 해당 호출이 발생한 지점의 스크립트로 이동하게 됩니다.
- 음.... 연결 되면 매번 알림을 받게 되고 자동적으로 JoinRandomRoom 으로 참여 하지만 우리가 원하는 것이 아닙니다.
이것을 고치기 위해서 우리는 컨텍스트에 대해서 알 필요가 있습니다. 사용자가 "Play" 버튼을 누를 때 , 사용자에 의해서 접속이 진행 중이라는 플래그를 얻어야 합니다.
그리고 나서 이 플래그를 체크하여 다양한 Photon 콜백내에서 적절하게 처리 해 주어야 합니다.
Launcher
스크립트를 편집 합니다.Private Fields 영역에 새로운 프로퍼티를 생성 합니다.
C#
/// <summary> /// Keep track of the current process. Since connection is asynchronous and is based on several callbacks from Photon, /// we need to keep track of this to properly adjust the behavior when we receive call back by Photon. /// Typically this is used for the OnConnectedToMaster() callback. /// </summary> bool isConnecting;
Connect()
메소드의 첫 부분에 다음을 추가 합니다.C#
// keep track of the will to join a room, because when we come back from the game we will get a callback that we are connected, so we need to know what to do then isConnecting = true;
OnConnectedMaster()
메소드에서 다음의if
문장안에PhotonNetwork.JoinRandomRoom()
을 놓습니다.C#
// we don't want to do anything if we are not attempting to join a room. // this case where isConnecting is false is typically when you lost or quit the game, when this level is loaded, OnConnectedToMaster will be called, in that case // we don't want to do anything. if (isConnecting) { // #Critical: The first we try to do is to join a potential existing room. If there is, good, else, we'll be called back with OnJoinRandomFailed() PhotonNetwork.JoinRandomRoom(); }
Launcher
스크립트를 저장합니다.
다시 Launcher 씬을 실행하여 테스트 하여 로비와 게임 사이를 왔다 갔다 해보면 모든 것이 잘 됩니다. :)
씬의 자동 동기화 테스트를 하기 위해서는 어플리케이션을 게시(테스트시 가장 빠른 데스크탑용으로) 해야 할 필요가 있으며 유니티와 동시에 실행시켜 두 명의 플레이어들이 연결되고 룸에 참여 할 수 있도록 합니다.
만약 유니티 에디터가 먼저 룸을 생성하게 되면 MasterClient 가 되기 때문에 유니티 콘솔에서 "PhotonNetwork : Loading Level : 1" 로그를 확인 할 수 있고 게시된 인스턴스로 접속 할 때 "PhotonNetwork : Loading Level : 2" 로그를 체크할 수 있습니다.
좋습니다! 많이 진행하였으나 전체 작업의 반일 뿐 입니다... :)
플레이어 자체와 씨름할 필요가 있고 다음 섹션에서 다루게 될 것 입니다.
가끔 컴퓨터와 멀리 떨어져 휴식을 취해 보세요. 다양한 개념이 설명되므로 휴식을 한 후 집중하면 더 효과가 있을 것 입니다.
특정 기능에 의문이 있거나 튜토리얼을 따라하는데 어려움이 있고 여기에서 다루지 않은 오류들이 발생 했을 때 언제든지 포럼으로 질문하세요. 기꺼이 도와 드리도록 하겠습니다. :)
Back to top