PUN Classic(PUN1이라고도 불립니다)은 PUN의 첫 버전입니다.         현재는 리팩토링 및 기능 확장에 의해 PUN2로 새롭게 바뀌었습니다.          새 프로젝트에는 PUN2를 이용해 주시고, 기존의 프로젝트도 가능하면 PUN1에서 PUN2로 옮기는 것을 권장합니다.  자세한 내용은: "마이그레이션 노트". PUN Classic은 곧 점검이 시작됩니다.        중요한 버그의 수정과 Unity의 신버전의 지원 등을 예정하고 있습니다. 신기능의 추가는 PUN2에서만 이루어지므로 주의해 주십시오.

파트 4 - 게임 매니저와 레벨

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

Contents

경기장 로딩 루틴

4개의 다른 룸을 생성하였으며 플레이어 수의 마지막 문자로 룸의 이름을 지었기 때문에 룸안의 현재 플레이어 수와 관련된 신을 bind 하는 것은 매우 쉽습니다. "convention over configuration" 로 알려져 있는 매우 효율적인 테크닉이며 "환경설정"기반 접근법으로 예를 들어 주어진 룸 안의 플레이어 수로 신 이름의 테이블 목록을 찾아 유지관리하는 것이 쉽습니다.

  1. GameManager 스크립트를 오픈 합니다.
  2. region Private Methods 영역에 새로운 메소드를 추가할 것 입니다.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.Log( "PhotonNetwork : Loading Level : " + PhotonNetwork.room.playerCount );
    PhotonNetwork.LoadLevel("Room for "+PhotonNetwork.room.playerCount);
}

#endregion

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

여기에서 두가지의 주의 할 점들이 있으며 매우 중요 합니다.

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

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

Back To Top

플레이어들의 연결 관찰

현재 GameManager 는 일반적인 MonoBehaviour 스크립트입니다. 이 튜토리얼 이전 파트에서 Photon 콜백을 얻는 다양 한 방식을 학습했기 때문에 GameManager 에서 플레이어 접속과 접속해제를 Listen 할 필요가 있습니다. 다음을 구현해 봅시다.

  1. GameManager 스크립트를 오픈합니다.
  2. 기본 클래스를 MonoBehaviour 에서 Photon.PunBehaviour 로 변경합니다.

        public class GameManager : Photon.PunBehaviour {
  3. 다음의 Photon 콜백 메시지를 추가하고 GameManager 스크립트를 저장 합니다.

#region Photon Messages

public override void OnPhotonPlayerConnected( PhotonPlayer other  )
{
    Debug.Log( "OnPhotonPlayerConnected() " + other.name ); // not seen if you're the player connecting

    if ( PhotonNetwork.isMasterClient ) 
    {
        Debug.Log( "OnPhotonPlayerConnected isMasterClient " + PhotonNetwork.isMasterClient ); // called before OnPhotonPlayerDisconnected

        LoadArena();
    }
}

public override void OnPhotonPlayerDisconnected( PhotonPlayer other  )
{
    Debug.Log( "OnPhotonPlayerDisconnected() " + other.name ); // seen when other disconnects

    if ( PhotonNetwork.isMasterClient ) 
    {
        Debug.Log( "OnPhotonPlayerConnected isMasterClient " + PhotonNetwork.isMasterClient ); // called before OnPhotonPlayerDisconnected

        LoadArena();
    }
}

#endregion

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

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

Back To Top

로비에서 경기장 로딩

  1. Launcher 스크립트를 편집 합니다.
  2. OnJoinedroom() 메소드에 다음을 추가하고 Launcher 스크립트를 저장 합니다.
// #Critical: We only load if we are the first player, else we rely on  PhotonNetwork.automaticallySyncScene to sync our instance scene.
    if (PhotonNetwork.room.playerCount == 1)
    {
        Debug.Log("We load the 'Room for 1' ");

        // #Critical
        // Load the Room Level. 
        PhotonNetwork.LoadLevel("Room for 1");
    }

Launcher 신을 오픈 후 실행하여 테스트 해 봅시다. "Play" 를 클릭하여 시스템이 연결하고 룸에 참여하도록 합니다. 다 되었습니다. 이제 로비가 있거나 또는 작업 중 입니다. 하지만 룸을 나간 경우 다시 로비로 돌아왔을 때 자동으로 재 참여 하게 됩니다. 아직 이렇게 되지 않는 다면 "간단하게" 로그를 분석 해 봅니다.

직접 해 보세요. 아직 소스에서 문제를 발견 하지 못했다면 같이 해 보겠습니다.

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

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

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

            /// <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 OnPhotonRandomJoinFailed()
            PhotonNetwork.JoinRandomRoom();
        }

다시 Launcher 신을 실행하여 테스트 하여 로비와 게임 사이를 왔다 갔다 해보면 모든 것이 잘 됩니다 :) 신의 자동 동기화 테스트를 하기 위해서는 어플리케이션을 게시(테스트시 가장 빠른 데스크탑용으로) 해야할 필요가 있으며 유니티와 동시에 실행시켜 두 명의 플레이어들이 연결되고 룸에 참여 할 수 있도록 합니다.

만약 유니티 에디터가 먼저 룸을 생성하게 되면 MasterClient 가 되기 때문에 유니티 콘솔에서 "PhotonNetwork : Loading Level : 1" 로그를 확인 할 수 있고 게시된 인스턴스로 접속 할 때 "PhotonNetwork : Loading Level : 2" 로그를 체크할 수 있습니다.

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

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

다음 파트.
이전 파트.

기술문서 TOP으로 돌아가기