지금까지 포톤 서버에 접속하고, 룸을 생성한 다음 입장하는 기능을 구현했다. 이제 주인공 캐릭터를 네트워크 통신이 가능하게 수정해보자. 하이라키뷰에서 Player를 선택하고 메뉴에서 [Component]->[Photon Networking]->[Photon View]를 선택해 PhotonView 컴포넌트를 추가한다.

PhotonView 컴포넌트

플레이어간 데이터를 송수신하는 통신 모듈이다. 동일한 룸에 입장한 다른 플레이어에게 자신의 위치와 회전 정보를 동기화시키고 특정 데이터를 송수신하려면 이 컴포넌트가 필요하다.

Synchronization

  • None : 동기화 처리한지 않는다.
  • Reliable Dellta Compress : 마지막 데이터가 변경되지 않았을 때 데이터를 송신하지 않는다
  • Unreliable : 송신한 패킷의 수신 여부를 확인하지 않는다.
  • Unreliable On Change : Unreliable과 동일한데 변경사항이 발생했을 때만 송신한다.

Observed Components : Photon View 컴포넌트가 관찰해 데이터를 송수신할 대상을 등록하는 속성이다.

주인공 캐릭터는 같은 룸에 입장한 다른 유저에게 자신의 위치와 회전값, 애니메이션에 대한 정보를 동기화해야한다.

  • Photon Transform View, Photon Animation View 컴포넌트를 사용하는 방식
  • OnPhotonSerializeView 콜백 함수를 사용하는 방식

첫번째 방식은 가장 쉽게 네트워크를 동기화 할 수 있지만. 세밀한 조정을 할 수 없으며 레이턴시 발생시 수동으로 보정할 수 없다.  2번째 방식은 Photon의 컴포넌트를 사용하지 않고 수동으로 관리하는 방식이다.

 

Photon Transform View, Photon Animator View

먼저 첫번째 방식으로 컴포넌트를 이용해 구현해보자. 하이라키뷰의 Player를 선택하고 [Component]-[Photon Networking] 하위 Photon Transform View와 Photon Animator View 컴포넌트를 추가해 동기화할 데이터및 속도를 지정할 수 있다.

Photon Animatior View에서 동기화 속도를 설정해야한다. 모드 Discrete로 지정한다.

네트워크 환경에서 생성하기 위한 준비

프로젝트뷰에서 Resouces 폴더를 생성한 후 하이라키 뷰의 Player를 Resources 폴더로 드래그해 프리팹으로 생성한후 하이라키뷰의 Palyer는 삭제한다. 포톤에서 네트워크로 동기화할 대상은 PhotonNetwork.Instantiate 함수를 사용하며 모두 Resources 폴더에 위치해야 한다.

 

다수의 네트워크 유저가 접속하기 때문에 미리 스폰 포인트를 설정하고 그중에서 랜덤한 위치에 생성되게 한다. 8장의 SpawnPointGroup을 생성했던 내용을 참고해 동일하게 생성한다.

접속한 유저가 출현할 불규칙한 위치 정보는 게임 매니저가 알고 있어야 한다. 먼저 빈 게임오브젝트를 생성하고 SpawnPointGroup으로 지정한다. Position은 (0,0,0)이다 SpawnPointGroup를 선택하고 하위에 빈게임오브젝트를 생성하고 Point라고 이름을 바꾼다.

시각적으로 표현하기 위해 MyGizmo.cs를 작성해서 연결한다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MyGizmo : MonoBehaviour
{
    public Color _color = Color.yellow;
    public float _radius = 0.1f;
    private void OnDrawGizmos() {
        Gizmos.color = _color;
        Gizmos.DrawSphere(transform.position, _radius);
    }
}

이제 유저가 접속했을때 여러 Spawn Point중에서 랜덤으로 발생시킬것이다. . 

포인트를 Ctr-D로 복사해서 여러군대 배치한다. 이름을 Point_1 ~ Point_9로 변경한다.

PhotonManager 스크립트에서 룸에 입장한 후 주인공 캐릭터를 네트워크상에서 동기화되게 생성한다. OnJoinedRoom  함수를 다음과 같이 수정한다. 

 

// 룸에 입장한 후 호출되는 콜백 함수
public override void OnJoinedRoom() {
    Debug.Log($"PhotonNetwork.InRoom = {PhotonNetwork.InRoom}");
    Debug.Log($"Player Count = {PhotonNetwork.CurrentRoom.PlayerCount}");
    foreach (var player in PhotonNetwork.CurrentRoom.Players) {
        Debug.Log($"{player.Value.NickName} , {player.Value.ActorNumber}");
    }
    //출연위치를 배열에 저장
    Transform[] points = GameObject.Find("SpawnPointGroup").GetComponentsInChildren<Transform>();
    int idx = Random.Range(1, points.Length);
    //네트워크에 캐릭터 생성
    PhotonNetwork.Instantiate("Player", points[idx].position, points[idx].rotation, 0);
}

유니티를 실행후 Player(Clone)이 생성되었는지 확인한다.

런타임(동적)으로 생성되었기 때문에 시네머신 카메라의 Follow와 LookAt속성이 모두 연결이 끊어져 주인공을 따라가지는 않는다. 다음과 같이 Movement.cs를 수정해서 따라가도록 한다. 

using Photon.Realtime 네임스페이스를 추가한다.

using Cinemachine;
using Photon.Pun;
using Photon.Realtime;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

우선 .Movement Class의 MonoBehaviour속성을 MonoBehaviourPunCallbacks로 변경한다.

public class Movement : MonoBehaviourPunCallbacks{

네트워크에 의해 생성한 캐릭터 참조 pv와 시네머신 가상 카메라를 저장할 변수를 전역변수로 지정한다.

// PhotonView 컴포넌트 캐시처리를 위한 변수
private PhotonView pv;
// 시네머신 가상 카메라를 저장할 변수
private CinemachineVirtualCamera virtualCamera;

자신이 생성한 캐릭터와 네트워크 유저는 Photonview.IsMine속성으로 구별할 수 있다. true일 경우 자신이다.  

Start()에서 연결한 virtualCamera를 pv.IsMine==true일 경우 연결한다.

void Start() {
    controller = GetComponent<CharacterController>();
    transform = GetComponent<Transform>();
    animator = GetComponent<Animator>();
    camera = Camera.main;

    pv = GetComponent<PhotonView>();
    virtualCamera = GameObject.FindObjectOfType<CinemachineVirtualCamera>();
    //PhotonView가 자신의 것일 경우 시네머신 가상카메라를 연결
    if (pv.IsMine) {
        virtualCamera.Follow = transform;
        virtualCamera.LookAt = transform;
    }
    // 가상의 바닥을 주인공의 위치를 기준으로 생성
    plane = new Plane(transform.up, transform.position);
}

네트워크 유저 캐릭터는 PhotonView에 의해서 관리되므로 자신이 생성한 캐릭터만 관리한다

    void Update() {
        // 자신이 생성한 네트워크 객체만 컨트롤
        if (pv.IsMine) {
            Move();
            Turn();
        }
    }

실행후 룸에 접속했을때 주인공 캐릭터가 불규칙한 위치에 생성되고 카메라가 주인공을 따라가는 것을 볼 수 있다. 하이라키뷰에서 Player(Clone)을 선택하고 인스펙터뷰에서 PhotonView의 IsMine속성과 Controller, Owner, Creator에 대한 정보를 확인할 수 있다.

 

PhotonManager.cs
0.00MB
Movement.cs
0.00MB
MyGizmo.cs
0.00MB

+ Recent posts