[Unity] Photon Network - 위치 동기화

박민주·2022년 5월 26일
0

Unity

목록 보기
26/40

https://youtu.be/vURIykhil2c
이영호 교수님의 강의를 들으면서 정리한 노트입니다.

using Photon.Pun;를 먼저 하고
MonoBehaviourPun를 상속받으면 Network 객체가 됨

해당 오브젝트에는 PhotonView 컴포넌트가 붙어있어야 함

그리고 스크립트에서
if(photonView.IsMine) 조건문을 통해
현재 객체가 나의 객체인지 확인할 수 있음

Tip.
네트워크 게임은 빌드가 빈번하다.
따라서 프로젝트의 볼륨이 커질수록 빌드 시간이 오래 걸리므로
되도록 리소스 없는 상태에서 네트워크를 구현하고 이후 리소스를 붙이는 게 좋음

자동으로 위치 동기화를 시켜주는 게 있음
사용하기 편한데 몇 가지 문제가 있음

내부적으로 Photon Transform View는 예를 들어 60도를 회전한 경우 Lerp걸린 것처럼 움직이게 됨
몸체가 분리되서 가는 경우도 생김

따라서 위와 같은 경고 메시지도 뜨는데,
제대로 하려면 Photon View Clasic 을 쓰거나 IPunObservable을 쓰는 게 제일 좋다고 함

그럼 IPunObservable을 사용한 방식으로 구현해보자
IPunObservable 상속받은 후 Alt Enter하면 꼭 구현해야 할 함수가 자동으로 작성됨

   // IPunObservable 상속 시 꼭 구현해야 하는 것
    // - 데이터를 네트워크 사용자 간에 보내고 받고 하게 하는 콜백 함수
    public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
    {
        // stream - 데이터를 주고 받는 통로 
        // 내가 데이터를 보내는 중이라면
        if(stream.IsWriting)
        {
            // 이 방안에 있는 모든 사용자에게 브로드캐스트 
            // - 내 포지션 값을 보내보자
            stream.SendNext(transform.position);
            stream.SendNext(transform.rotation);
            stream.SendNext(camera.rotation);
        }
        // 내가 데이터를 받는 중이라면 
        else
        {
            // 순서대로 보내면 순서대로 들어옴. 근데 타입캐스팅 해주어야 함
            transform.position = (Vector3)stream.ReceiveNext();
            transform.rotation = (Quaternion)stream.ReceiveNext();
            camera.rotation = (Quaternion)stream.ReceiveNext(); 
        }
    }

근데 위 코드처럼 하면 뚝뚝 끊겨 보일 수 있음

OnPhotonSerializeView에서 stream.ReceiveNext()를 통해 받은 값들을 바로 적용하지 않고
캐싱한 다음에 Update()에서 Lerp를 해주면 보간해줄 수 있다!

     void Update()
    {
        if (false == photonView.IsMine)
        {
            transform.position = Vector3.Lerp(transform.position, remotePos, 10 * Time.deltaTime);
            transform.rotation = Quaternion.Lerp(transform.rotation, remoteRot, 10 * Time.deltaTime);
            camera.rotation = Quaternion.Lerp(camera.rotation, remoteCamRot, 10 * Time.deltaTime);
            return;
        }
    }
    
    public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
    {
        // 내가 데이터를 보내는 중이라면
        if(stream.IsWriting) // 내꺼 보내는 거
        {
            // 이 방안에 있는 모든 사용자에게 브로드캐스트 
            // - 내 포지션 값을 보내보자
            stream.SendNext(transform.position);
            stream.SendNext(transform.rotation);
            stream.SendNext(camera.rotation);
        }
        // 내가 데이터를 받는 중이라면 
        else // 원격에 있는 나 
        {
            // 순서대로 보내면 순서대로 들어옴. 근데 타입캐스팅 해주어야 함
            remotePos = (Vector3)stream.ReceiveNext();
            remoteRot = (Quaternion)stream.ReceiveNext();
            remoteCamRot = (Quaternion)stream.ReceiveNext();
        }
    }

뭔가 아직은 이해가 잘 안된다..
OnPhotonSerializeView()에서 remotePos에 받은 다음
Update에서 IsMine이 아니라면 현재 객체에 저장을 해주는데

아 로컬 플레이어가 아니라면 입력을 통한 이동이 아닌
서버로부터 받은 pos를 적용시킨다고 보면 될 듯 하다..!

현재 씬에 해당 코드를 가진 플레이어가 여러 명일텐데
remotePos에는 원격에 있는 나의 position을 받아오는 건가보다

profile
Game Programmer

0개의 댓글