This document is about: PUN 1
SWITCH TO

PUN Classic (v1), PUN 2, Bolt는 휴업 모드입니다. Unity2022에 대해서는 PUN 2에서 서포트하지만, 신기능의 추가는 없습니다. 현재 이용중인 고객님의 PUN 및 Bolt 프로젝트는 중단되지 않고, 퍼포먼스나 성능이 떨어지는 일도 없습니다. 앞으로의 새로운 프로젝트에는 Photon Fusion 또는 Quantum을 사용해 주십시오.

파트 8 - 플레이어 네트워크 인스턴스 생성

이 섹션에서는 네트워크를 통한 Player 프리팹 인스턴스 생성과 플레이 하는 동안 자동 신 전환에 필요한 다양한 기능에 대해서 구현 할 것 입니다.

Player 인스턴스 생성하기

Player 프리팹의 인스턴스를 생성하는 것은 정말로 쉽습니다.
룸에 들어갔을 때 바로 인스턴스를 생성할 필요가 있으며, 우리가 경기장을 로드 했다는 것을 의미 하는 GameManager 스크립트 Start() 에서 할 수 있습니다. 이 의미는 설계상에서 우리가 룸에 있다는 의미 입니다.

  1. GameManager 스크립트를 오픈 합니다.

  2. Public Variables region 에서 다음의 변수를 추가 합니다.

    C#

    [Tooltip("The prefab to use for representing the player")]
    public GameObject playerPrefab;
    
  3. Start() 메소드에서 다음을 추가한 다음 GameManager 스크립트를 저장 합니다.

    C#

    if (playerPrefab == null) {
        Debug.LogError("<Color=Red><a>Missing</a></Color> playerPrefab Reference. Please set it up in GameObject 'Game Manager'",this);
    } else {
        Debug.Log("We are Instantiating LocalPlayer from "+Application.loadedLevelName);
    // we're in a room. spawn a character for the local player. it gets synced by using PhotonNetwork.Instantiate
        PhotonNetwork.Instantiate(this.playerPrefab.name, new Vector3(0f,5f,0f), Quaternion.identity, 0);
    }
    
  4. GameManager 스크립트를 저장 합니다.

노출된 public 필드는 Player 프리팹을 참조합니다. Player 프리팹이 에셋이므로 참조가 온전하게 유지 되기 때문에 GameManager 프리팹은 각 신에서 작업 하는 대신 직접 드래그앤 드롭 할 수 있어 편리 합니다.

WARNING: 프리팹은 Resources 폴더안에서 네트워크를 통하여 인스턴스 생성되어야 하는 것이 Photon 의 요건임을 항상 확인 하세요.
GameManager Inspector
GameManager 인스펙터

그리고 나서 Start() 에서 인스턴스를 생성 했습니다( 프리팹 Player 레퍼런스를 적절히 체크 한 이후)

바닥 위에 인스턴스가 잘 생성한 것을 주목 하세요( 플레이어가 2 유닛 높이를 가졌고 5 유닛 위에).
새로운 플레이어가 룸에 참여 할 때 플레이어들이 경기장 중심에서 돌아 다닐 수 있도록 갑작스러운 충돌을 방지하는 방법들 중 하나의 방식입니다.
또한 "떨어지는" 플레이어는 게임에서 새로운 엔터티라고 깔끔하게 알려주게 됩니다.

하지만 우리의 경우에 있어 충분하지가 않습니다. 트위스트가 있습니다 :)
다른 플레이어들이 참여할 때, 다른 신들이 로드될 것이며 일관성을 유지하고 나갔기 때문에 제거 하지는 않을 것 입니다.
따라서 유니티에게 우리가 생성했던 인스턴스를 제거 하지 말라고 알려 줄 필요가 있습니다. 신이 로드 될 때 인스턴스 생성이 필요한지 체크하는 것이 필요 합니다.

플레이어 인스턴스의 파악

  1. PlayerManager 스크립트를 오픈 합니다.

  2. Public Variables Region 에서 다음을 추가 합니다.

    C#

    [Tooltip("The local player instance. Use this to know if the local player is represented in the Scene")]
    public static GameObject LocalPlayerInstance;
    
  3. Awake() 메소드에서 다음을 추가 합니다.

    C#

    // #Important
    // used in GameManager.cs: we keep track of the localPlayer instance to prevent instantiation when levels are synchronized
    if ( photonView.isMine)
    {
        PlayerManager.LocalPlayerInstance = this.gameObject;
    }
    // #Critical
    // we flag as don't destroy on load so that instance survives level synchronization, thus giving a seamless experience when levels load.
    DontDestroyOnLoad(this.gameObject);
    
  4. PlayerManager 스크립트를 저장 합니다.

이 변경사항으로 GameManager 스크립트 내에서 필요한 인스턴스만 체크하는 구현을 할 수 있습니다.

  1. GameManager 스크립트를 오픈 합니다.

  2. if 문장으로 인스턴스 생성 호출을 둘러 쌉니다.

    C#

    if (PlayerManager.LocalPlayerInstance==null)
    {
        Debug.Log("We are Instantiating LocalPlayer from "+Application.loadedLevelName);
        // we're in a room. spawn a character for the local player. it gets synced by using PhotonNetwork.Instantiate
        PhotonNetwork.Instantiate(this.playerPrefab.name, new Vector3(0f,5f,0f), Quaternion.identity, 0);
    }else{
        Debug.Log("Ignoring scene load for "+Application.loadedLevelName);
    }
    
  3. GameManager 스크립트를 저장 합니다.

이것으로 로컬 플레이어의 기존 인스턴스의 참조가 없을 때만 인스턴스 생성을 하게 됩니다.

경기장 밖에 있을 때 플레이어 위치 관리

우리가 주의 해야 할 것이 하나 더 있습니다.
경기장의 크기는 플레이어 수에 따라 변합니다. 이 의미는 한명의 플레이어가 나가고 다른 플레이어들이 현재 경기장 크기의 제한에 가까울 경우가 있다는 의미 입니다. 이 상황을 고려할 필요가 있으며 이 경우에 경기장의 중심부로 플레이어들의 위치를 단순히 재조정 합니다.
이것은 분명히 게임 플레이와 레벨 디자인에 이슈가 발생 할 수 있습니다.

  1. GameManager 스크립트를 오픈 합니다.

  2. MonoBehaviour CallBacks region 내에 다음의 메소드를 추가 합니다.

    C#

    void OnLevelWasLoaded(int level)
    {
        // check if we are outside the Arena and if it's the case, spawn around the center of the arena in a safe zone
        if (! Physics.Raycast(transform.position, -Vector3.up, 5f)) 
        {
            transform.position = new Vector3(0f,5f,0f);
        }
    }
    

직관적입니다. 유니티의 OnLevelWasLoaded 콜백을 사용하여 현재 플레이어 아래로 raycast 하여 어떤 것에 접촉하는지 확인 합니다.
이렇게 하지 않으면 경기장 바닥위에 아무것도 없으며 룸에 처음 들어 갔을 때와 똑같이 중심부로 위치를 재조정 해야 할 필요가 있습니다.

다음 파트.
이전 파트.

Back to top