와이유스토리

[아르마딜로 대시] 6. 네트워크 평행세계, 객체 동기화 및 RPC(원격 프로시저 호출) 동기화 본문

프로젝트/게임

[아르마딜로 대시] 6. 네트워크 평행세계, 객체 동기화 및 RPC(원격 프로시저 호출) 동기화

유(YOO) 2022. 12. 8. 23:48

평행세계

내 화면의 아르마딜로 오브젝트와 친구 화면의 아르마딜로 오브젝트는 엄연히 다르다. 평행세계 느낌이므로 내가 호출한 함수는 다른 모든 기기에서 자동 함수 호출이 되어야 한다. 여기서 실제 내가 아닌 다른 기기에서의 나의 이름은 PhotonView이다. 내가 명령해서 다른 기기에서 움직이는 모든 변수와 함수 모두 PhotonView이다. 나와 너와 나에게 보여지는 너와 너에게 보여지는 나를 구분하자

1. 객체 동기화

  • 업데이트 자주할 때, 연속 작동
  • ex) 아르마딜로 위치, 애니메이션 동기화

1. 동기화시킬 Object에 PhotonView Component 추가

2. PhotonView Component

  • Observable Search : Auto Find All 자동 동기화시킬 컴포넌트 등록
  • Observed Components : 동기화시킬 기능 수동 선택
    •  transform
      • Photon Transform View (Script) 사용
    • animation
      • Photon Animator View (Script) 사용
        • Disable : 동기화X
        • Discreate : 초당 10번 동기화
        • Continuous : 매 프레임마다 동기화
    • script : dead reckoning 해결 위해 수동 조정, 스크립트 동기화
      • IPunObservable 인터페이스 상속
      • OnPhotonSerializeView 함수에서 컴포넌트 동기화 호출
  • Observe Option
    • Reliable : TCP
    • Unreliable : UDP
    • Unreliable On Change : UDP, 변경사항이 있을 때만 통신 지속, 게임 오브젝트가 휴식 중일 때 전송 안 함

 * dead reckoning : 추측항해기법, 네트워크 연결 시 지연현상(Latency) 해결 위한 기법.

2. RPC 동기화

  • 업데이트 가끔할 때, event 작동
  • ex) event 동기화, 스페이스바키로 아르마딜로 대시, 문어 보스의 숫자키 누르기 및 탄막 발사

1. Rpc 동기화하고 싶은 함수 위에 [PunRPC] 작성

2. pv(PhotonView 객체).RPC("함수명", RpcTarget.All)으로 호출

3. pv.RPC 사용하는 구문 바깥에 if(pv.IsMine)이나 if(pv.AmOwner) 필수 작성

  • 없으면 (나에게 보여지는 너)나 (너에게 보여지는 나)도 해당 구문을 실행해버리는 불상사가 발생
  • 주인이 실행할 수 있게 만든다.
  • RpcTarget.AllBufferedViaServer : 호출 후, 버퍼 저장된다. 이후에 들어오는 사람도 자동 순차 적용
    • 단,버퍼가 너무많으면 네트워크 약한 사용자는 끊어질 가능성 있다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Photon.Pun;
using Photon.Realtime;
using Hashtable = ExitGames.Client.Photon.Hashtable;

// 룸에서 플레이의 Ready 버튼
public class ReadyBtn : MonoBehaviourPunCallbacks, IPunObservable
{
    public PhotonView pv;            // Ready 텍스트 포톤뷰
    Hashtable temp;                  // 임시 해시 테이블
    string isReady;                  // Ready 여부 변수

    public void Start()
    {
        // Canvas 하위로 이동
        transform.SetParent(GameObject.Find("Canvas").GetComponent<Transform>(), false);
        ColorChange(isReady);
    }

    // ready 버튼 클릭(ex) 0번 플레이어가 0번 Ready를 눌러야만 로컬에서 색깔 바꿈)
    public void Update()
    {
        if(GameObject.Find("Ready").GetComponent<ReadyClick>().isClick)  // 본인 Ready 버튼 isClick X
        {
            if (pv.IsMine)
            {
                temp = PhotonNetwork.LocalPlayer.CustomProperties;

                if(temp.ContainsKey("Ready"))
                {
                    if (((string)temp["Ready"]).Equals("Yes"))
                    {
                        temp["Ready"] = "No";                                 // 직접 대입 X
                        PhotonNetwork.LocalPlayer.SetCustomProperties(temp);  // PunRPC에서 사용X
                        pv.RPC("ColorChange", RpcTarget.AllBufferedViaServer, "No");
                    }
                    else
                    {
                        temp["Ready"] = "Yes";
                        PhotonNetwork.LocalPlayer.SetCustomProperties(temp);
                        pv.RPC("ColorChange", RpcTarget.AllBufferedViaServer, "Yes");
                    }
                }
            }
            GameObject.Find("Ready").GetComponent<ReadyClick>().isClick = false;
        }
    }
    
    // Ready 텍스트 프로퍼티에 맞춰 변경
    [PunRPC]
    void ColorChange(string value) // Localplayer와 PhotonView(pv) 같지 않음
    {
        isReady = value;

        if ((value == null) || (value.Equals("No")))
        {
            gameObject.GetComponent<Text>().text = "";
        }
        else
        {
            gameObject.GetComponent<Text>().text = "Ready";
        }
    }

    public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
    {
        if (stream.IsWriting)
        {
            stream.SendNext(isReady);
        }
        else
        {
            this.isReady = (string)stream.ReceiveNext();
        }
    }
}

* 참고

https://ridohee.tistory.com/entry/네트워크-Day3-포톤네트워크-PUN2-동기화

Comments