경일게임아카데미 멀티 디바이스 메타버스 플랫폼 개발자 양성과정 20220913 특강 2022/04/04~2022/12/14

Jinho Lee·2022년 9월 13일
0

2022.09.13 경일 메타버스 24주차 1일 특강 수업내용. 포톤 네트워크 엔진

  • 제대로 포톤을 다루기 위해서는 추가로 정리가 필요할 듯하다.

이론 제외 정리

PUN

  • 포톤에서 제공하는 유니티 네트워크 솔루션

  • PhotonNetwork

    • 포톤과 관련된 여러 가지 기능을 제공

      • 매치메이킹 / 방 생성 / 방 접속 등등
    • API

      • ConnectUsingSettings() : 매치메이킹 서버에 접속

        • PhotonServerSettings 스크립터블 오브젝트에서 서버와 관련된 여러 데이터 설정 가능
      • JoinRandomRoom() : 현재 접속 가능한 방 중 임의로 접속한다.

      • LoadLevel() : 방에 있는 모든 클라이언트를 특정 씬으로 이동시킨다.

      • CreateRoom() : 방을 생성한다.

  • MonoBehaviourPunCallbacks

    • MonoBehaviour에 PUN과 관련된 콜백 메소드를 제공
  • PhotonView

  • MonoBehaviourPun

    • photonView 제공

    • PhotonView 컴포넌트가 추가되어 있어야 함

네트워크 동기화 이론

  • 자료 : “레트로의 유니티 게임 프로그래밍 에센스” 2권 7부 ch. 18 p. 820 ~ 835

네트워크 동기화

  • 핵심
    ”4인 멀티플레이어 게임에서 플레이어 캐릭터는 총 16명이다.”

  • 로컬 오브젝트 : 주도권이 자신에게 있음

  • 리모트 오브젝트 : 주도권이 네트워크 너머의 타인에게 있음

  • 로컬 권한 검사

    • 로컬이든 리모트든 게임 오브젝트의 컴포넌트 구성은 같다
      모두 사용자 입력을 받을 수 있다.

    • 플레이어 조작 입력은 로컬 오브젝트에만 반영되어야 한다.

    • 이를 구현하기 위해서는 오브젝트가 로컬 권한을 가지고 있는지 검사해야 한다.

게임 서버의 종류

  • 서버(Server)클라이언트들이 참가할 수 있는 네트워크 공간을 마련하는 컴퓨터

    • 호스트(Host)라고도 불린다.

    • 게임 속 상호작용 연산도 담당

  • 클라이언트(Client)서버에 참가하여 게임을 플레이하는 컴퓨터

  • 네트워크 게임의 서버-클라이언트 방식

    • 전용 서버 (Dedicated Server)

    • 리슨 서버 (Listen Server)

    • P2P (Peer-to-Peer)

전용 서버 (Dedicated Server)

  • 서버의 모든 자원이 온전히 네트워크 서비스를 유지하는 데 사용되며, 서버가 플레이어로서 게임에 직접 참가하지 않는 형태

  • 장점

    • 언제든지 참가 가능

    • 고정된 고성능 서버 제공 → 쾌적한 환경

  • 단점

    • 많은 고정 비용 발생

리슨 서버 (Listen Server)

  • 클라이언트하나가 서버 역할

  • ‘Play as Host’라고도 불린다.

  • 마인크래프트, 로블록스 등

  • 장점

    • 적은 서비스 유지 비용

    • 물리적으로 매우 가까운 플레이어 사이에서는 전용 서버보다 빠른 네트워크 반응 속도

  • 단점

    • 호스트 플레이어의 컴퓨터 성능에 따라 달라지는 네트워크 품질

    • 호스트가 게임을 종료할 경우, 남은 클라이언트 중 새로운 호스트를 선정하는 절차 (Host Migration) 필요

P2P

  • 게임에 참가한 클라이언트 모두가 호스트

  • 서로 직접 연결된 형태

  • P2P의 연산

    • 네트워크 게임에서는 일반적으로 호스트는 클라이언트에 비해 연산 부담이 크다
      → 네트워크 룸을 유지하는 데 필요한 연산 + 게임 속 중요한 연산

    • P2P에서는 연산을 독점하는 호스트가 없다
      각 클라이언트가 자신의 담당 연산을 실행, 결과 전파

  • 장점

    • 호스트 교체 과정 (Host Migration) 불필요

    • 서버 유지비용 없음

    • 클라이언트 수가 적은 경우 다른 방법보다 빠른 네트워크 반응 속도

    • 프로그램 처리 흐름을 직관적으로 설계 가능

  • 단점

    • 참가자가 증가할수록 느려지는 반응 속도

      • 다른 방법에 비해 많은 연결 회선 수(참가자 인원 대비)
    • 다른 모든 클라이언트와 직접 연결 필요

    • 연결 수가 늘어날수록 빠르게 늘어나는 부담 연산량

      • P2P 개별 클라이언트가 호스트-클라이언트 방식의 호스트보다 많은 연산 부담을 질 수도 있다.
    • 수치 변조에 취약

      • 호스트가 있으면 중요 연산과 데이터는 호스트가 관리

      • P2P는 각 클라이언트가 연산 → 위조된 수치의 전파 위험이 큼

매치메이킹 서버 (Matchmaking Server)

  • 리슨 서버나 P2P 방식을 사용해도 참가할 클라이언트들이 서로를 찾아 방 하나에 모이는 과정이 필요 ⇒ 전용 서버

  • 이 전용 서버를 매치메이킹 서버라 부른다.

포톤 룸

  • 서버는 아니지만, 여러 클라이언트가 모인 네트워크 상의 가상 공간 단위

  • 유니티의 씬이 아니다.

    • 서로 다른 씬을 로드하는 것도 가능

    • 하나의 룸에서 정보 공유 / 같은 장소(씬)으로 이동

    • 비유 : 같은 주파수를 공유

      • 주파수를 공유(같은 룸에 입장)한다고 같은 물리적 장소(씬)에 있는 건 아니다.

네트워크 권한 분리

  • 네트워크 게임의 목표

    • 공정한 결과 보장

    • 수치에 대한 위변조 방지

  • 서버와 클라이언트 사이의 권한을 분리
    ⇒ 규칙 “중요한 연산은 모두 서버(호스트)에 위임”

    • 클라이언트는 서버 연산의 결과를 표시하는 화면일 뿐

호스트에 위임

  • 이유

    1. 동기화에 오차가 존재하는 경우 기준 월드를 선정

      • 모든 처리와 수치의 기준이 호스트의 게임 월드
    2. 클라이언트의 위변조 행위 방지

      • 위변조된 수치를 호스트가 무시
  • 중요한 연산은 호스트가 처리하고 클라이언트는 시각적 처리만 수행
    → 비주얼 이펙트, 효과음 재생, 애니메이션 재생 등
    → 반응 속도를 높이고 네트워크 대역폭 사용을 줄인다.

RPC (Remote Procedure Call)

  • 원격 프로시저 호출

  • 메소드, 처리를 네트워크를 넘어 다른 클라이언트에서 실행

  • 특정 클라이언트가 호스트에 처리를 위임 → 호스트는 그 결과를 모든 클라이언트에 전파

포톤 서버 준비

  • 유니티 네트워크 솔루션 중 가장 대중적

    • 포톤 PUN

    • Mirror

  • 유니티 공식 라이브러리 - UNet

    • Deprecated (사용 되지 않음) 선언

    • 현재 MLAPI 개발 중 → 실험 버전

인게임 서버 & 아웃게임 서버

  • 인게임 서버

    • 게임 자체 플레이에 대한 서버

    • 뒤끝 등

  • 아웃게임 서버

    • 게임 외적인 부분, 즉 로그인 화면이나 캐시 샵 등을 처리하는 서버

    • ProudNet 등

PUN 2

  • PUN : Photon Unity Network, 유니티용으로 제작된 포톤 네트워크 엔진.

  • 플랫폼과 상관없이 동작

  • 포톤의 여러 API를 유니티 컴포넌트로 랩핑하여 제공

유니티 네트워크 솔루션 - 포톤 PUN 2

App ID 얻기

Multiplayer Game Development Made Easy | Photon Engine

  • 사용 용도 / 제목 / 내용 - 생성된 AppID 복사

PUN2 에셋 추가

PUN 2 - FREE | Network | Unity Asset Store

  • 에셋 스토어 PUN 2 - FREE

  • 로비 구현 예시 코드

using Photon.Pun; // 유니티용 포톤 컴포넌트들
using Photon.Realtime; // 포톤 서비스 관련 라이브러리
using UnityEngine;
using UnityEngine.UI;

// 마스터(매치 메이킹) 서버와 룸 접속을 담당
public class LobbyManager : MonoBehaviourPunCallbacks {
    private static readonly string GAME_VERSION = "1"; // 게임 버전

    public Text ConnectionInfoText; // 네트워크 정보를 표시할 텍스트
    public Button JoinButton; // 룸 접속 버튼

    // 게임 실행과 동시에 마스터 서버 접속 시도
    private void Start()
    {
        // 접속에 필요한 정보를 설정한다.
        PhotonNetwork.GameVersion = GAME_VERSION;

        // 마스터 서버로 접속을 시도한다.
        PhotonNetwork.ConnectUsingSettings();

        // UI 표시
        JoinButton.interactable = false;
        ConnectionInfoText.text = "마스터 서버에 접속 중...";
    }

    // 마스터 서버 접속 성공시 자동 실행
    public override void OnConnectedToMaster()
    {
        // UI 표시
        JoinButton.interactable = true;
        ConnectionInfoText.text = "온라인 : 마스터 서버와 접속 됨.";
    }

    // 마스터 서버 접속 실패시 자동 실행
    public override void OnDisconnected(DisconnectCause cause)
    {
        // UI 표시
        JoinButton.interactable = false;
        ConnectionInfoText.text = "오프라인 : 재접속 중...";

        // 재접속 시도
        PhotonNetwork.ConnectUsingSettings();
    }

    // 룸(세션) 접속 시도
    public void Connect()
    {
        // 접속 버튼을 비활성화
        JoinButton.interactable = false;

        // 서버에 접속 중이냐
        if (PhotonNetwork.IsConnected)
        {
            // 접속 중이라는 것을 UI에 표시
            ConnectionInfoText.text = "룸에 접속합니다!";

            // 접속을 실행
            PhotonNetwork.JoinRandomRoom();
        }
        // 아니라면
        else
        {
            // UI 표시
            ConnectionInfoText.text = "오프라인 : 재접속을 시도해주세요.";

            // 다시 마스터 서버에 재접속 시도
            PhotonNetwork.ConnectUsingSettings();
        }
    }

    private static readonly RoomOptions ROOM_OPTIONS = new RoomOptions()
    {
        MaxPlayers = 4
    };
    // (빈 방이 없어)랜덤 룸 참가에 실패한 경우 자동 실행
    public override void OnJoinRandomFailed(short returnCode, string message)
    {
        // UI 표시
        ConnectionInfoText.text = "방 생성...";

        // 방 생성
        PhotonNetwork.CreateRoom(null, ROOM_OPTIONS);
    }

    // 룸에 참가 완료된 경우 자동 실행
    public override void OnJoinedRoom()
    {
        // UI 표시
        ConnectionInfoText.text = "방에 참가합니다.";

        // 모든 클라이언트 Main 씬 로드
        PhotonNetwork.LoadLevel("Main");
    }
}
  • 서버에 접속 시도

    • PhotonNetwork.ConnectUsingSettings()
  • DisconnectCause

    • 접속 실패한 이유들을 열거형으로 나열
  • 서버 접속 여부를 나타내는 프로퍼티

    • PhotonNetwork.IsConnected
  • 방을 선택하여 접속하고 싶다면 마스터 서버로부터 룸의 정보 / 갯수를 받아 UI로 목록(List)을 제공, 선택할 수 있도록 구성해야 한다.

    • 룸의 정보(방 읽어들이기) : GetCustomRoomList()

    • 임의의 접속 가능한 방에 접속 : JoinRandomRoom()

    • 특정 방에 접속(선택하여 접속) : JoinRoom()

  • PhotonNetwork.CreateRoom()

    • 이름 - null을 넣으면 서버에서 랜덤 생성

    • 룸 옵션 - 여러 옵션 - MaxPlayers는 0을 넣으면 No Limit을 의미한다.

    • 로비 타입, 티어 시스템 등등 추가 가능

  • 씬을 로드할 때, SceneManager가 아닌 PhotonNetwork.LoadLevel() 사용

    • 이유 :
      모든 클라이언트가 씬을 로드해야 하기 때문. 네트워크 동기화
  • 현재는 포톤 서버를 사용하고 있지만, 후에 서버를 준비하고 도메인을 준비하고 어떤 포트를 사용할지 정하면 모두 PhotonServerSettings라는 스크립터블 오브젝트에 업데이트해야 한다.

포팅

  • 핵심 : 요청실행분리한다.

  • Player에 새롭게 추가된 컴포넌트

    • Photon View

      • 네트워크를 통해 동기화될 모든 게임 오브젝트는 이 컴포넌트를 가져야 한다.

      • 네트워크 상에서 구별 가능한 식별자 View ID를 부여한다.

        • 로컬과 리모트의 구분이 가능해진다.
      • 변화한 수치를 관측하고 다른 클라이언트에게 전달 / 동기화할 수 있다.

        • 관측할 컴포넌트를 Observed Components 리스트에 할당한다.

        • 단, IPunObservable 인터페이스를 상속한 컴포넌트만 관측할 수 있다.

      • inspector 창

        • Synchronization

          • Off

            • 공유하지 않는다, 동기화하지 않는다.
          • Reliable Delta Compressed

            • 상대방이 최근에 수신한 값과 동일한 값은 송신하지 않는다.

            • Reliable : 신뢰할 수 있다, 유실이 없다.

          • Unreliable

            • 패킷의 수신 여부를 검사하지 않고 지속적으로 송신한다.
          • Unreliable On Change

            • 패킷의 수신 여부를 검사하지 않고 값의 변화가 감지될 때만 송신한다.
    • Photon Transform View

      • 플레이어의 Transform동기화한다.

      • 트랜스폼 컴포넌트 값의 변화를 측정하고, Photon View 컴포넌트를 사용해 동기화한다.

      • 자신이 로컬이라면 트랜스폼의 속성값을 감지하고 리모트로 전송한다.
        자신이 리모트라면 송신된 로컬의 값을 받아 자신의 트랜스폼에 적용한다.

      • 로컬 게임 오브젝트와 리모트 게임 오브젝트 사이 트랜스폼 컴포넌트의 속성값동기화

    • Photon Animator View

      • 플레이어의 애니메이션동기화한다.

      • 애니메이터 컴포넌트의 파라미터를 동기화하여 서로 같은 애니메이션을 재생

      • 자신이 로컬이라면 애니메이터 컴포넌트의 파라미터를 관측하고 리모트로 전달한다.
        자신이 리모트라면 송신된 로컬의 값을 받아 자신의 애니메이터 컴포넌트의 파라미터에 덮어쓴다.

    • Camera Setup

      • 시네머신 가상 카메라가 로컬 플레이어만 추적하도록 설정

0개의 댓글