4 - 게임 매니저와 레벨

이 섹션에서는 룸 안에서 현재 플레이하고 있는 플레이어 수에 기반하여 다양한 레벨 로딩 처리에 대한 추가 기능을 다룰 것 입니다.

Contents

경기장 로딩 루틴

4개의 다른 룸을 생성하였으며 플레이어 수는 룸의 마지막 문자로 했기 때문에 룸안의 현재 플레이어 수와 관련된 씬을 바인딩하는 것은 매우 쉽습니다. "convention over configuration" 로 알려져 있는 매우 효율적인 테크닉입니다. "configuration" 기반 접근법으로 예를 들어 주어진 룸 안의 플레이어 수로 신 이름의 테이블 목록을 찾아 유지관리하는 것이 쉽습니다. 스크립트는 그 리스트를 보고 이름이 전혀 중요하지 않은 씬으로 돌려받았을 것이다. "configuration" 은 일반적으로 더 많은 스크립팅이 필요하기 때문에, 우리는 코드를 관련 없는 기능으로 지저분하게 하지 않고 더 빨리 코드를 작동시킬 수 있는 "개념"을 추구할 것입니다.

  1. GameManager 스크립트를 오픈 합니다.
  2. private 메소드 영역에 새로운 메소드를 추가할 것 입니다. GameManager 스크립트를 저장하는 것을 잊지 마세요.

        #region Private Methods
    
    
    void LoadArena()
    {
        if (!PhotonNetwork.IsMasterClient) 
        {
            Debug.LogError("PhotonNetwork : Trying to Load a level but we are not the master Client");
        }
        Debug.LogFormat("PhotonNetwork : Loading Level : {0}", PhotonNetwork.CurrentRoom.PlayerCount);
        PhotonNetwork.LoadLevel("Room for " + PhotonNetwork.CurrentRoom.PlayerCount);
    }
    
    
    #endregion
  3. GameManager 스크립트를 저장합니다

이 메소드를 호출 할 때에 현재 있는 룸의 PlayerCount 프로퍼티에 기반한 룸을 로드 할 것 입니다.

여기에서 눈여겨 봐야할 주의 할 점들이 있으며 매우 중요 합니다.

  • PhotonNetwork.LoadLevel() 은 마스터 클라이언트인 경우에만 호출 되어야 합니다. 따라서 PhotonNetwork.isMasterClient 를 이용하여 마스터 클라이어인트인지를 체크 합니다. 이것을 체크하는 것은 호출자의 책임이 될 것 이며 이 섹션의 다음 파트에서 다룰 것 입니다.
  • PhotonNetwork.LoadLevel() 을 이용하여 원하는 레벨을 로드 합니다. 이 게임에서는 PhotonNetwork.automaticallySyncScene 을 사용하도록 해놓았기 때문에 룸 안의 모든 접속한 클라이언트에 대해 이 레벨 로드를 유니티가 직접 하는 것이 아닌 Photon 이 하도록 하였습니다.

이제 원하는 레벨을 로드하는 기능이 있으므로 플레이어들의 연결과 연결해제에 대하여 바인드 해 보겠습니다.

Back To Top

플레이어들의 연결 관찰

튜토리얼의 이전 장에서 Photon 콜백을 얻는 다양한 방식을 학습했으며 이제는 GameManager 가 플레이어의 연결과 연결해제를 리슨할 필요가 있습니다. 다음을 구현해 봅시다.

  1. GameManager 스크립트를 오픈합니다.
  2. 다음의 Photon 콜백을 추가하고 GameManger 스크립트를 저장합니다.

        #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
  3. GameManager 스크립트를 저장합니다.

이제 설정이 완료 되었습니다. 플레이어들이 참여 또는 룸을 떠날 때 마다 통지를 받게 되고 위에서 구축 해 놓은 LoadArena() 메소드를 호출 할 것 입니다. 하지만 PhotonNetwork.isMasterClient 를 이용하여 마스터인 경우에만 LoadArena() 를 호출 할 것 입니다.

이제 로비로 되돌아와서 룸에 참여할 때 맞는 씬을 로드 할 수 있습니다.

Back To Top

로비에서 경기장 로딩

  1. Launcher 스크립트를 편집 합니다.
  2. OnJoinedroom() 메소드에 다음을 추가합니다.

        // #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");
    }
  3. Launcher 스크립트를 저장합니다.

Launcher 씬을 오픈 후 실행하여 테스트 해 봅시다. "Play" 를 클릭하여 시스템으로 연결하고 룸에 참여하도록 합니다. 이게 다 입니다. 이제 로비가 작업하게 됩니다. 하지만 룸을 나간 경우 다시 로비로 돌아왔을 때 자동으로 재 참여 하게 됩니다. 이런... 이 문제를 해결해 보도록 합시다.

왜 이런 현상이 발상하는지 모르겠다면 "간단하게" 로그를 분석합니다. 저는 간단하게 로그 문장을 넣었으며, 문제를 파악하고 어디서 보고 어떻게 그것을 디버그 할지를 알기 위해서는 연습과 경험이 필요하기 때문에, 간단하게 파악할 수 있는 문장을 넣습니다.

이제 스스로 시도해보고 아직 소스에서 문제를 발견 하지 못했다면 같이 해 보겠습니다

  1. Launcher 씬을 실행 합니다.
  2. "Play" 버튼을 누르고 "Room for 1" 에 참여하여 로드될 때 까지 기다립니다.
  3. 유니티 콘솔 창을 clear 합니다.
  4. "Leave Room" 을 누릅니다.
  5. 유니티 콘솔 창을 관찰하여 "PUN Basics Tutorial/Launcher: OnConnectedToMaster() was called by PUN" 이 기록되어 있는지 확인 합니다.
  6. Launcher 씬을 중지 합니다.
  7. 로그 항목 "PUN Basics Tutoria/Launcher: OnConnectedToMaster() was called by PUN" 을 더블 클릭하면 해당 호출이 발생한 지점의 스크립트로 이동하게 됩니다.
  8. 음.... 연결 되면 매번 알림을 받게 되고 자동적으로 JoinRandomRoom 으로 참여 하지만 우리가 원하는 것이 아닙니다.

이것을 고치기 위해서 우리는 컨텍스트에 대해서 알 필요가 있습니다. 사용자가 "Play" 버튼을 누를 때 , 사용자에 의해서 접속이 진행 중이라는 플래그를 얻어야 합니다. 그리고 나서 이 플래그를 체크하여 다양한 Photon 콜백내에서 적절하게 처리 해 주어야 합니다.

  1. Launcher 스크립트를 편집 합니다.
  2. Private Fields 영역에 새로운 프로퍼티를 생성 합니다.

            /// <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;
  3. Connect() 메소드의 첫 부분에 다음을 추가 합니다.

            // 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;
  4. OnConnectedMaster() 메소드에서 다음의 if 문장안에 PhotonNetwork.JoinRandomRoom() 을 놓습니다.

            // 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();
        }
  5. Launcher 스크립트를 저장합니다.

다시 Launcher 씬을 실행하여 테스트 하여 로비와 게임 사이를 왔다 갔다 해보면 모든 것이 잘 됩니다. :) 씬의 자동 동기화 테스트를 하기 위해서는 어플리케이션을 게시(테스트시 가장 빠른 데스크탑용으로) 해야 할 필요가 있으며 유니티와 동시에 실행시켜 두 명의 플레이어들이 연결되고 룸에 참여 할 수 있도록 합니다. 만약 유니티 에디터가 먼저 룸을 생성하게 되면 MasterClient 가 되기 때문에 유니티 콘솔에서 "PhotonNetwork : Loading Level : 1" 로그를 확인 할 수 있고 게시된 인스턴스로 접속 할 때 "PhotonNetwork : Loading Level : 2" 로그를 체크할 수 있습니다.

좋습니다! 많이 진행하였으나 전체 작업의 반일 뿐 입니다... :) 플레이어 자체와 씨름할 필요가 있고 다음 섹션에서 다루게 될 것 입니다. 가끔 컴퓨터와 멀리 떨어져 휴식을 취해 보세요. 다양한 개념이 설명되므로 휴식을 한 후 집중하면 더 효과가 있을 것 입니다.

특정 기능에 의문이 있거나 튜토리얼을 따라하는데 어려움이 있고 여기에서 다루지 않은 오류들이 발생 했을 때 언제든지 포럼으로 질문하세요. 기꺼이 도와 드리도록 하겠습니다. :)

다음 파트.
이전 파트.

기술문서 TOP으로 돌아가기