유니티 Pun 사용법

JHO·2024년 11월 15일
0

유니티 3D

목록 보기
8/14
post-thumbnail

1. Photon 서버 생성


1-1 Pun 서버 생성


2. 패키지 추가


2-1 Pun2 패키지 추가

  • Asset Store에서 Pun2 무료 버전 받은 후 , 유니티 프로젝트에서 Pun2 다운.

2-2 서버 연동

  • 만들어 놓은 Pun 서버 Id를 입력 한뒤 , Setup Project.

2-3 ParrelSync 다운

  • 멀티 환경을 에디터 상에서 쉽게 테스트 하기 위해서 Parrel Sync zip 다운.
  • 다운받은 zip을 압축해제 후, ParrelSync 폴더를 추가.

3. 번외


3-1. 서버, 클라이언트

  • MonobehaviourPuncallbacks를 사용하는 경우는, 위 함수들을 필요로 할때(요청을 받을 때), 즉 이벤트를 필요로 할때만
    상속 받으면 됨.
  • 요청을 할때는 using Photon.Pun; 만 사용 하면 됨.
  • CreateRoom함수의 경우 2번째 인자로 방 Option설정가능.
  • JoinRandomOrCreateRoom 함수도 존재하며, 비어 있는 방이 없으면 새로 방을 만들어 들어가는 함수.
  • OnRoomListUpdate(List roomList)roomList 자체가 처음 로비 입장을 제외하고, 그 다음 부턴 변경된 사항들만 전달.
  • 로비에서 나가는 경우 모든 방 목록을 초기화당하고 / 다시 로비 입장시 처음에는 모든 방목록을 받는다
  • OnMasterClientSwitched함수는 방장이 바뀌면 호출됨.
  • PhotonNetwork.Instantiate: Resources 폴더의 프리펩을 생성, object타입의 Data또한 매개변수로 사용 가능.
  • photonView.InstantiationData를 통해 생성한 인스턴스에서 Data를 가져올 수 있음.
  • 삭제할때는 PhotonNetwork.Destroy를 사용.

3-2. Custom Property

  • 룸과 플레이어에 추가적인 정보를 원하는 경우, 커스텀 프로퍼티를 이용해서 구성 가능.
    -> ex) Room의 경우, 이름, 최대 참여가능 인원, 현재 참여인원, 공개여부
    -> ex) Player의 경우, 닉네임, 아이디, 방장여부 등
  • 커스텀 프로퍼티는 추가하고자 하는 정보의 이름과 값을 설정하여 같은 게임을 플레이하는 구성원들에게 정보를 공유하고 동기화 가능.
  • ExitGames.Client.Photon.hashTable은 포톤에서 구현한 자료로, c#의 Dictionary와 사용방법 일치.
    -> 네트워크 동기화를 위해서 직렬화가 가능한 위의 HashTable 사용이 필요.
  • 커스텀 프로퍼티는 위처럼, 확장메서드를 활용하는 것이 추후 활용면에서 편리.
  • using을 사용하여 Photonhashtable을 간략히 사용하면 편리.

3-3. Photon View, MonoBehaviourPun

  • Photon View: 동기화 해야하는 게임오브젝트를 관리하기 위한 컴포넌트
    -> ViewId, 객체의 소유자, 네트워크 변경사항 등을 읽고 쓰기 위한 스크립트를 보유.
  • MonoBehaviourPun: Photon View는 게임오브젝트를 동기화 하기 위한 기준이 되며, 보통의 경우 포톤 뷰를 포함하는 게임오브젝트의 스크립트는 포톤 뷰를참조하기 위한 변수를 가진 MonoBehaviourPun클래스를 상속하는 것을 추천.

3-4. IPunObservable

  • 그냥 MonoBehaviour를 사용해도 상관 x.
  • IPunObservable이 있어야 Photon View에서 Observed Components에 자동으로 동기화 될 스크립트로 구성.
  • OnPhotonSerializeView()함수에서 동기화할 변수를 지정 가능.
  • 보내고 받을때 꼭 보내는 순서와 개수를 일치시켜줘야함.
  • 참조타입은 불가능하고, 값타입 변수만 가능.
    -> 참조타입은 어떻게 동기화 할까?
    -> PhotonView 변수 사용하면 된다.
  • PhotonView를 통해 소유권자는 ID를 보내고, 받는 쪽에선 ID를 통해 참조타입을 가져올 수 있다.
    (또 다른 예시)
  • viewId가 달린 GameObject의 Id를 넘겨주어서, 그 Id를 찾은후, 넣어주기도 가능.

3-5.함수의 동기화 RPC

  • photon ServerSettings에서 Rpc List확인가능.
    • 함수의 경우 PunRPC를 통해, 동기화 가능하다.
    • PunRPC함수 생성 자체는 MonoBehaviourPun을 상속받은 클래스에서만 가능.
    • 호출 조건은 RPC함수가 구현된 클래스가 붙어있는 객체에 Photonview가 있어야함.
      -> 호출하는 클래스는 Pun을 굳이 상속받을 필요없이
      pun을 상속받은 클래스의 photonview를 가져와 RPC함수호출이 가능**.
      -> 또한, 호출하는 클래스는 photonview없어도 Photonview가 달린 클래스를 찾아와 RPc호출 가능.
  • 위의 경우 FindObjectOfType으로 예시를 들긴했지만, 원하는 객체의 PHotonview를 참조할 때, 인스펙터창에서 public변수 또는 GetComponent로 참조 가능.

3-6. 지연보상

  • 서버에서 RPC를 보낸시간을 현재시간에서 빼서 지연시간을 계산.
  • 지연시간 만큼 미리 position을 앞으로 보내고 그자리에서 생성하는 식의 지연보상처리가 가능.
  • 물리 지연 처리 방법.
private Vector3 networkPosition;
private float deltaPosition;
private Quaternion networkRotation;
private float deltaRotation;
private void Update()
{
    if (photonView.IsMine == false)
    {
        transform.position = Vector3.MoveTowards(transform.position, networkPosition, deltaPosition * Time.deltaTime * PhotonNetwork.SerializationRate);
        transform.rotation = Quaternion.RotateTowards(transform.rotation, networkRotation, deltaRotation * Time.deltaTime * PhotonNetwork.SerializationRate);
    }
}
public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
{
    if (stream.IsWriting)
    {
        stream.SendNext(transform.position);
        stream.SendNext(transform.rotation);
    }
    else if (stream.IsReading)
    {
        networkPosition = (Vector3)stream.ReceiveNext();
        networkRotation = (Quaternion)stream.ReceiveNext();
        deltaPosition = Vector3.Distance(transform.position, networkPosition);
        deltaRotation = Quaternion.Angle(transform.rotation, networkRotation);
    }
} 
  • 물리 객체가 아닌 지연 보상은 Transform 컴포넌트를 사용하여 동기화, 이전 시점데이터와 현재 시점의 데이터의 차이에서 계산을 진행하고 조정.

3-7. 마이그레이션, RoomObject

  • 마이그레이션: 온라인 멀티플레이어 게임의 개념으로 방장이 연결이 해제되는 경우에도 다른 클라이언트가 호스트 권한을 승계하고 게임을 자연스럽고 끊임없이 전이 하는 기법.
  • 마스터 클라이언트가 변경 되며, 기존의 마스터 클라이언트가 생성한 게임 씬에 필요한 게임오브젝트들은 소유자가 사라지면서 같이 사라지게 되는 상황이 있을 수 있음.
  • 게임에서 소유자와 무관하게 계속해서 유지되기 원하는 공용으로 사용할 게임오브젝트는 RoomObject로 생성하고, 이는 마스터 클라이언트만 컨트롤 권한을 가지고 동작가능.
    -> 마스터클라이언트가 트랜스폼뷰가달린 룸오브젝트를 이동시키면 동기화 됨.
    -> is.mine이나, Masterclient 조건 사용시 룸오브젝트 다루기 가능.
    -> 마스터 클라이언트가 교체될 경우 권한을 승계하는 방식으로 동작.

3-8. RigidbodyView, TransformView

  • 포톤에는 이미 Rigidbody 또는 Transform만 동기화하도록 View를 제공.
  • 절대 두가지 View를 동시에 사용 x.
  • TransformView는 다른Pc에서 부드러운 이동이 가능하지만,
    만약 순간이동 느낌을 원한다면 OnPhotonSerializeView를 통해 위치를 변수로 동기화.

3-9. 서버 세팅

  • Photon - PhotonUnityNetworking - Resources - Photon Server Settings.
  • Window - PhotonUnityNetworking - HighlightServer Settings.

3-10. PlayerNumbering

using Photon.Pun;
using Photon.Pun.UtilityScripts;
using Photon.Realtime;
public class PlayerInfoDisplay : MonoBehaviour
{
   void Start()
   {
       foreach (Player player in PhotonNetwork.PlayerList)
       {
           int number = PlayerNumbering.GetPlayerNumber(player);
           Debug.Log($"Player {player.NickName} has number {number}");
       }
   }
}

  • PlayerNumbering 스크립트가 존재해야 GetPlayerNumber 제대로 사용가능.
  • 없으면, -1만 계속 출력.
  • customProperty의 설정도 확인 가능.
  • Playerindex 즉 numbering은 그대로 유지.
    -> Player0 입장, Player1입장.
    -> Player0퇴장해도 Player1의 인덱스는 1로 그대로 유지.
    -> 다시 새로운 Player들어오면 0번 입장 받음.
profile
개발노트

0개의 댓글