05. 플레이어 동기화 시키기
동기화는 업데이트 빈도에 따라 크게 3가지 타입이 있다.
1. 잦은 업데이트(위치, 문자상태)
2. 가끔 업데이트(플레이어 행동)
3. 희귀 업데이트 & 상태(문의 개폐, 지도, 캐릭터 장비) - 생략
1. 잦은 업데이트(위치, 문자상태)
업데이트가 연속적으로 작동해야 되는 경우. ex) 캐릭터의 위치 값을 받아오는
객체 동기화를 사용한다.
객체 동기화는 움직임을 동기화 시킬 때 사용한다고 이해하면 쉽다.
2. 가끔 업데이트(플레이어 행동)
업데이트를 연속적으로 할 필요는 없으나 event를 받아야 되는 경우.
RPC동기화를 사용한다.
RPC동기화는 플레이어의 행동에 의한 event 메시지를 받을 때 사용한다.
< 객체 동기화 >
Photon View(Script)
<객체 동기화 photon View사용 기본 구조>
객체 동기화를 사용하기 위해서는
먼저, 동기화 시킬 게임오브젝트에 PhotonView Component를 가져와야 한다.
PhotonView Component의 구성요소를 하나하나 뜯어보면,
크게 Observed Components와 ObserveOption으로 구성되어있다.
Observed Components에는 동기화 시킬 components를 가져올 수 있다.
그 중 script component를 가져오는 경우는 특수한 경우이다.
script를 Observed Components로 가져오게 될 경우에 자동으로 네트워크 처리되는 것을
수동으로 조정할 수 있다.
수동으로 조정이 필요한 이유는 dead reckoning(데드 레커닝)을 해결하기 위해서이다.
*dead reckoning은 추측항해기법이라는 의미를 가지고 있다.
네트워크 연결시 지연현상(Latency)를 해결하기 위한 기법이다.
신호를 받지 못할 경우에 미리 다음 신호를 예측하여 행동하게 할 때 사용한다. (interpolate 보간 사용)
스크립트를 동기화 시키기 위해서 기본적으로 스크립트에 OnPhotonSerializeView를 추가해야 한다.
OnPhotonSerializeView를 사용하기 위해서는 class에 IPunObservable를 넣어줘야 한다.
ObservedOption은 네트워크의 통신규약을 정하는 옵션이다.
reliable은 TCP통신 unreliable은 UDP통신이다.
*TCP통신이란?
TCP통신에는 error correction이 존재한다. 이는 에러를 다시 바로 잡아준다는 것을 의미한다.
서버에서 클라이언트에게 정보를 보낼 때 확인 메시지를 서버에게 돌려주고, 클라이언트가 제대로 메시지를 받지 못하면 resend를 서버에 요청한다. 손실된 데이터를 다시 클라이언트에게 보낼 수 있다. 데이터를 손실하지 않고 보낼 수 있다.
*UDP통신이란?
UDP통신은 단방향 통신이다. 단방향 통신은 무조건 서버에서 클라이언트에게 메시지를 보내기만 한다. 그렇기 때문에 메시지 손실이 중간에 발생해도 이를 무시하고 메시지가 손실된 상태에서 계속 메시지를 보낸다. 따라서 UDP통신은 TCP통신에 비해서 빠르다는 장점을 가지고 있다.
작성자는 Unreliable On Change 옵션을 사용하는데.
이 통신 방식은 포톤에 특수하게 있는 것으로
변경사항이 있을 경우에만 통신을 지속하는 것이다. (쓸모없는 통신을 줄임.)
photon Transform View(Script)
포톤에서는 많이 사용하는 transform동기화를 script로 제공하고 있다.
하지만, 이는 자동으로 dead reckoning 문제를 해결해주지 않기 때문에 끊김 현상을 보완하고 싶을 경우 스크립트를 작성해야 한다.
< RPC동기화 >
RPC는 remote procedure calls의 축약어이다.
이는 원격으로 함수를 부른다는 의미를 가진다.
즉, RPC동기화는 이벤트가 발생(함수호출)하는 경우에 사용한다.
rpc동기화를 시키고 싶은 함수 위에 [PunRPC]를 사용한다.
그리고 PhotonView.RPC("함수 이름");으로 원하는 곳에서 RPC함수를 호출하여 사용한다.
동기화 전체 코드
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | using System.Collections; using System.Collections.Generic; using UnityEngine; using Photon.Pun; using Photon.Realtime; public class moveCtrl : MonoBehaviourPunCallbacks, IPunObservable { public float speed = 10.0f; private Transform tr; void Start() { tr = GetComponent<Transform>(); } void Update () { //controlled locally일 경우 이동(자기 자신의 캐릭터일 때) if (photonView.IsMine) { float moveHorizontal = Input.GetAxis("Horizontal"); float moveVertical = Input.GetAxis("Vertical"); Vector3 movement = new Vector3(moveHorizontal, 0.0f, moveVertical); tr.Translate(movement * Time.deltaTime * speed); } else { //끊어진 시간이 너무 길 경우(텔레포트) if ((tr.position - currPos).sqrMagnitude >= 10.0f * 10.0f) { tr.position = currPos; tr.rotation = currRot; } //끊어진 시간이 짧을 경우(자연스럽게 연결 - 데드레커닝) else { tr.position = Vector3.Lerp(tr.position, currPos, Time.deltaTime * 10.0f); tr.rotation = Quaternion.Slerp(tr.rotation, currRot, Time.deltaTime * 10.0f); } } } //클론이 통신을 받는 변수 설정 private Vector3 currPos; private Quaternion currRot; public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info) { //통신을 보내는 if (stream.IsWriting) { stream.SendNext(tr.position); stream.SendNext(tr.rotation); } //클론이 통신을 받는 else { currPos = (Vector3)stream.ReceiveNext(); currRot = (Quaternion)stream.ReceiveNext(); } } } | cs |
<mini 네트워크 과제>
움직이는 네모 박스 코드 직접 짜서 네트워크로 만들어보기.
'Project > Galapagos' 카테고리의 다른 글
네트워크 Day4 (포톤네트워크 PUN2 - Cross Device) (0) | 2018.12.18 |
---|---|
유체역학 이론 Day01(구간 반복 시키기 - Bound Movement) (0) | 2018.12.14 |
네트워크 Day2 (포톤네트워크 PUN2 - 네트워크 개념, 포톤네트워크 사용) (1) | 2018.12.12 |
네트워크 Day1 (포톤네트워크 PUN2 - 테스트) (0) | 2018.12.10 |
장치 연결 테스트 (0) | 2018.12.09 |