유니티/PUN2

동기화 방법

잼잼재미 2024. 6. 6. 23:46

동기화 방법


1.  PhotonView


  • 갱신이 빈번한 경우에 사용
    • ex) 위치 이동, 상태 변경
  • 캐릭터의 동기화에 사용 (PhotonView, PhotonTransformView 스크립트 추가)

 

 

Setting

 

Ownership

  • Fixed : Ownership 고정
  • Takeover : Ownership을 클라이언트가 가져갈 수 있음
  • Request : Ownership을 클라이언트가 가졀갈 수 있지만, 주인에게 허락을 맡아야 함

 

 

 

Synchronization

  • Off : RPC만 사용할 경우
  • Reliable Delta Compressed : 받은 데이터를 비교해 같으면 보내지 않음
  • Unreliable : 계속 보냄 (손실 가능성 있음)
  • Unreliable On Change : 변경이 있을 때 계속 보냄

* Off 이외에는 모두 Observed Components에 Component가 하나라도 있어야 함

 

 

Observed Components

  • 동기화 할 컴포넌트를 넣는 줌
  • 변경된 값 중, 동기화 할 것을 관찰해서 다른 클론들에게 보내는 역할

 

 

객체 동기화

// PhotonView를 사용하여 플레이어를 생성하는 간단한 로직
private void OnJoinPlayer()
{
	int index = UnityEngine.Random.Range(0, spawnPoints.Length);
	PhotonNetwork.Instantiate("Player", spawnPoints[index].position, spawnPoints[index].rotation);
}

// 프리팹 파괴
PhotonNetwork.Destroy(gameObject);

 

* 반드시, 유니티 내장 Instantiate()가 아닌 해당 메소드를 사용해야 함!

* 프리팹은 Resources 폴더에 있어야 함!

* Room을 생성하거나, 참여한 뒤, 해당 메소드를 사용해야 함!

 

 

내가 생성한 객체 판단

private PhotonView _photonView;

// 플레이어 이동, 회전의 간단한 예제
private void Update()
{
    if (!_photonView.IsMine)
        return;

    float h = Input.GetAxis("Horizontal");
    float v = Input.GetAxis("Vertical");

    tr.Translate(Vector3.forward * v * Time.deltaTime * speed);
    tr.Rotate(Vector3.up * h * Time.deltaTime * rotSpeed);
}

 

 

 

 

2. RPC


  • 원격 프로시저 호출 (Remote Procedure call)
    • 별도의 원격 제어를 위한 코딩 없이 다른 주소 공간에서 함수나 프로시저를 실행할 수 있게하는 프로세스 간 통신 기술
  • 갱신이 드문 경우 사용
  • 방에 있는 모든 Player에게 이 함수를 실행하도록 하는 의미
  • 사용자가 직접 발생시키는 동기화
  • PhotonView를 사용하지 않고 RPC를 사용하는 이유
    • PhotonView는 많은 전송을 요구
    • PhotonView를 통해 계속 동기화 대상을 늘리는 것은 좋은 방법은 아님
  • ex) 총알의 동기화에 사용
  • Lobby에서는 사용 불가, Room에서 사용
  • 매개변수 전달 가능
    • 객체를 들고 있는 RaycastHit, Collider 등은 전달할 수 없음
    • int, vector3 등 전달 가능

 

 

  • PC1의 A Player (mine)의 RPC 실행 -> PC2의 A Player 함수 실행
  • PC2의 B Player (mine)의 RPC 실행 -> PC2의 B Player 함수 실행
  • 같은 Photonview 컴포넌트를 가지고 있는 Player의 함수 실행
  • 다른 PC에서 행동을 제어 받아서 자신의 PC에서 실행하는 원리로 멀티 플레이

 

 

사용 예시

private void Update()
{
    if (!_photonView.IsMine)
        return;

    bool fire = Input.GetMouseButton(0);
    if (fire)
    {    
        _photonView.RPC("Fire", RpcTarget.AllViaServer, rigidbody.position, rigidbody.rotation);
    }
}

[PunRPC]
public void Fire(Vector3 position, Quaternion rotation, PhotonMessageInfo info)
{
    float lag = (float)(PhotonNetwork.Time - info.SentServerTime);
    GameObject bullet;

    // 불릿 생성
    bullet = Instantiate(BulletPrefab, gunOffset.position, Quaternion.identity) as GameObject;
    // 불릿 초기화 로직
    bullet.GetComponent<BulletCtrl>().InitializeBullet(photonView.Owner, (rotation * Vector3.forward), Mathf.Abs(lag));
}

 

  • RpcTarget
    • All : 이 클라이언트에서 즉시 실행하고, 방에 있는 모든 Player가 함수 실행
    • AllBuffered : 이 클라이언트에서 즉시 실행하고, 방에 있는 모든 Player가 함수 실행. 새로운 Player는 이 클라이언트가 떠날때까지 함수 실행
    • AllViaServer : 서버를 통해, 방에 있는 모든 Player(이 클라이언트 포함)가 순서대로 함수 실행
    • Other : 이 클라이언트에서 실행하지 않고, 모든 Player가 함수 실행

 

 

멀티 플레이 코드를 싱글 플레이에 사용하는 방법

PhotonNetwork.OfflineMode = true;

 

오프라인 모드를 활성화 하면, 포톤으로 구현한 RPC 전송, PhotonNetwork.Instantiate 코드를 싱글 플레이 모드에서 똑같이 사용할 수 있다. PhotonNetwork.OfflineMode = false; 또는 서버 연결로 오프라인 모드를 중지할 수 있다.

 

 

호출 빈도 변경

PhotonNetwork.SendRate = 60; // 기본 설정 값 = 20

 

위 코드로 RPC 초당 호출 빈도를 변경할 수 있다.

 

 

3. OnPhotonSerializeView


  • PhotonView의 OnPhotonSerializeView 메서드를 사용하여 데이터를 전송, 수신
  • IPunObservable 인터페이스를 추가해야 함
  • 변수를 동기화할 때, 사용
  • 1초에 10번 데이터 전송

 

 

스크립트 작성

// 인터페이스를 추가하고 이 함수를 추가해야 함
public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
{
    // 데이터 보내기 (isMine == true)
    if(stream.IsWriting)
    {
        stream.SendNext(GameManager.I.DataManager.PlayerData.KoreaTag);
        stream.SendNext(GameManager.I.DataManager.PlayerData.Level);
    }
    // 데이터 받기 (isMine == false)
    else
    {
        _roomEnemyCharacterName = (string)stream.ReceiveNext();
        _roomEnemyCharacterLevel = (int)stream.ReceiveNext();
    }
}

 

* class 데이터는 전송할 수 없기때문에, int, string과 같은 변수를 전달해야 함!

 

 

Observed Components 추가

 

OnPhotonSerializeView 함수가 있는 스크립트를 추가

 

 

호출 빈도 변경

PhotonNetwork.SerializationRate = 60; // 기본 설정 값 = 10

 

위 코드로 OnPhotonSerializeView의 초당 호출 빈도를 변경할 수 있다.

'유니티 > PUN2' 카테고리의 다른 글

멀티 씬 이동  (1) 2024.06.15
Player 동기화 (PhotonTransformView, OnPhotonSerializeView , PhotonAnimatorView)  (0) 2024.06.13
채팅 구현  (0) 2024.06.11
서버, 로비 접속 및 방 생성  (0) 2024.06.06
PUN2 준비하기  (0) 2024.06.04