PUN Classic (v1), PUN 2, Bolt는 휴업 모드입니다. Unity2022에 대해서는 PUN 2에서 서포트하지만, 신기능의 추가는 없습니다. 현재 이용중인 고객님의 PUN 및 Bolt 프로젝트는 중단되지 않고, 퍼포먼스나 성능이 떨어지는 일도 없습니다. 앞으로의 새로운 프로젝트에는 Photon Fusion 또는 Quantum을 사용해 주십시오.

Gameye로 호스팅하기

이 기능은 Photon Bolt Pro 버전에서 사용할 수 있습니다.

Gameye는 독립적인 인프라를 사용하여 전 세계에 게임 서버를 배포하는 호스팅 서비스입니다. Photon Bolt는 Gameye에서 실행할 수 있는 지원을 가지고 있으며 이 튜토리얼에서는 게임 서버를 몇 분 안에 시작하고 배포하는 데 필요한 모든 기능을 제공합니다.

Gameye 서비스에 대해

Gameye 서비스는 Docker 컨테이너를 사용하여 가상화를 기반으로 구축되며, 각 컨테이너는 플레이어를 리슨 하는 게임 서버입니다. REST API를 사용하여 이러한 게임 서버를 쉽게 생성, 제거 및 나열할 수 있으므로 서버 조정 및 자동화를 수행할 수 있습니다.

서비스 자체에 대한 자세한 내용은 공식 웹 사이트 https://gameye.com/와 설명서 페이지 https://docs.gameye.com/에서 확인할 수 있습니다.

작업 흐름

이 튜토리얼에서는 전용 게임 서버를 실행하고 Photon Bolt Pro를 사용하여 직접 연결할 수 있는 방법에 대해 중점적으로 설명합니다. 다음 단계를 따라 하세요:

  1. 헤드리스 게임 서버를 구성합니다.
  2. Gameye 서비스에 서버 컨테이너를 배포하고 전용 서버를 시작합니다.
  3. 원격 서버를 검색하고 연결할 수 있는 게임 클라이언트를 구축합니다.

이러한 각 단계에는 다음 섹션에서 설명하는 몇 가지 하위 단계가 있습니다. 이 체계를 구축하는 데 필요한 모든 파일을 오픈 소스 프로젝트로 사용할 수 있습니다. 다음 이미지는 우리가 구축할 부분의 개요를 보여줍니다.

bolt and gameye integration
Bolt 와 Gameye 통합.

사전 필요 사항

필요한 모든 부품을 제작하기 전에 다음 사항들이 필요합니다:

  1. Photon Bolt Pro. 이 샘플은 Pro 버전의 직접 연결 기능과 함께 사용하도록 제작되었습니다.
  2. 서비스를 사용할 수 있도록 Gameye 직원과 연락하여 Application Token을 받습니다. 이 토큰은 호출을 인증하는 데 사용됩니다.
  3. Docker and DockerHub 동작 방식에 대하여 기본적으로 이해하도록 합니다. 구성, 빌드, 실행, 그리고 docker imagesdocker containers의 업로드 방법을 이해합니다. 또한 다음 사항들이 필요합니다:
    1. 계정이 없다면 DockerHub 계정이 있어야합니다.
    2. 서버 이미지를 업로드할 저장소가 필요합니다.
  4. 기본 Bolt 튜토리얼을 마쳐야 합니다(시작하기고급 튜토리얼).
  5. Unity로 Linux Target Platform을 설치합니다.

헤드리스 게임 서버 구축하기

Gameye에서 전용 서버를 실행하려면 2 부분의 솔루션에 대해서 작업해야 합니다: (i) 헤드리스 서버를 실행하고 연결을 리슨 하는 유니티 프로젝트와 (ii) 서버 바이너리를 도커 이미지로 캡슐화하고, 이것은 나중에 애플리케이션을 컨테이너로 만드는 데 사용됩니다.

유니티 프로젝트

받은 SDK 패키지 안에는 samples_pro라는 폴더가 있는데, 이 폴더에는 다른 샘플 프로젝트 중 GameyeIntegration 폴더가 포함되어 있습니다. 헤드리스 서버를 실행하는 데 필요한 모든 파일이 들어 있습니다. 다음은 게임 서버에 사용된 코드 중 일부를 설명하겠습니다.

Scenes 폴더에는 이 샘플에서 사용할 (i) GameyeHeadlessServer, (ii) GameyeInGame, and (iii) GameyeClient의 세 가지 주요 씬이 있습니다. 게임 서버의 경우 처음 두 씬을 사용합니다.

GameyeHeadlessServer 씬부터 시작하며, 이 씬은 게임 서버를 제어하는 주요 진입점인 GameyeServer 스크립트를 실행하는 단순한 Game Object 하나만 사용합니다. 이 스크립트를 열면 매우 간단하다는 것을 알 수 있습니다.

이 스크립트는 BoltLauncher.StartServer(serverPort)를 호출하여 Bolt 서버를 시작하고 GameyeInGame 씬을 로드합니다. 하지만 여러분이 알아야 할 몇 가지 중요한 관점이 있습니다. Start에서는 command-line arguments를 구문 분석하여 로드할 맵과 같은 정보를 로드하지만 가장 중요한 것은 바인딩 할 포트입니다. 이와 같은 전용 서버를 실행할 때 두 개의 주 포트를 사용합니다. (i) 새로운 플레이어 연결을 청취할 서버 포트와 (ii) A2S 쿼리 프로토콜을 사용하여 서버에서 실시간 정보를 검색하는 데 사용됩니다.

Gameye에서 서버를 호스팅 할 때, Igniter(github)라고 하는 툴을 사용합니다. 이 툴은 게임 서버의 현재 상태를 추적하여 서비스 관리자에게 보고합니다. Igniter와 통신하려면 stdout 스트림에 특정 문자열을 출력해야 합니다(다음 섹션에서 해당 메시지에 대해 더 잘 설명하겠습니다). 이를 위해 간단히 핵심 문자열을 기록하는 GameyeIgniterApi를 구축했습니다. 예를 들면 starting, playing, 또는 exiting과 같은 상태를 나타내기 위해서 GameyeServer 스크립트에서 사용합니다.

GameyeServer 스크립트의 또 다른 중요한 측면은 A2SManager 클래스를 사용하는 것입니다. 이 관리자는 서버에 대한 내부 메타데이터를 업데이트할 책임이 있습니다. 이 정보는 나중에 클라이언트가 서버 구성을 확인하는 데 사용됩니다.

또한 이 스크립트는 세션에 연결된 플레이어가 없을 때 게임 서버를 자동으로 종료합니다. 그래서 게임 서버를 시작하고, 플레이어가 참여할 때까지 기다렸다가 필요한 만큼 플레이하게 하고, 마지막 플레이어가 연결이 끊기면 자동으로 종료됩니다. 이 동작을 확장하여 게임을 다시 시작하거나 타이머를 포함할 수 있습니다.

GameyeInGame 씬에 대해서는 현재로선 플레이스 홀더일 뿐 실제 컨텐츠나 게임 플레이는 없고 서버와 클라이언트가 플레이할 수 있는 또 다른 씬이 있는지 확인하기 위해 사용합니다.

좋습니다. 이제 서버에서 어떤 일이 일어나는지 잘 이해했으므로, 다음을 구축해 보겠습니다.

  1. Build Settings 창을 열고, 인덱스 0에 GameyeHeadlessServer, 인덱스 1에 GameyeInGame 씬을 포함합니다
  2. Bolt를 재컴파일(Bolt/Compile Assembly) 하여 씬 구성을 인식할 수 있도록 합니다.
  3. Target PlatformArchitecture x86Linux로 변경합니다.
  4. 게임을 빌드 합니다. 바이너리 명칭은 지금부터 game.x86로 사용하니 이대로 명명하는 것을 권장합니다.

Game Server 도커 이미지 빌드

Gameye 서비스의 핵심 특징 중 하나는 게임 실행 파일 구축 방식과 무관하며 도커 이미지 참조만 있으면 원하는 수의 서버를 돌릴 수 있다는 점입니다. 그러나 이 이미지는 약간의 설정이 필요하며 앞에서 말한 Igniter 툴을 사용해야 합니다. 이름에서 알 수 있듯이 Igniter는 게임을 실행하고 실행 파일을 제어합니다.

이를 최대한 부드럽게 하기 위해 몇 단계만 거치면 도커 이미지를 만들 수 있는 템플릿을 이미 구축했습니다. https://github.com/BoltEngine/gameye_bolt_server_image에 있는 프로젝트를 어서 복제하십시오.

리포지토리에 이미 이미지 작성 방법에 대한 설명이 포함되어 있지만 여기서 요약해보겠습니다.

  1. 리포지토리에 있는 파일을 다운로드합니다
  2. 게임 서버 바이너리를 빌드 합니다 (마지막 단계에서 완료했습니다)
  3. 서버 파일들을 build 폴더로 복사합니다. 실행 파일들과 데이터 폴더. 실행 명칭으로 game.x86으로 명명했다는 것을 기억하세요.
  4. Makefile 파일을 열고, DOCKER_USERNAME (DockerHub 사용자명) 그리고 GAME_IMAGE_NAME (DockerHub 리포지토리 명) 변수를 변경하세요.
  5. 폴더의 make를 실행하여 바이너리를 빌드 하세요.

좋습니다. 이제 업로드할 도커 이미지가 이미 설정되어 있어야 합니다. 이제 이 이미지를 사용할 때 알아야 할 모든 구성과 Gameye 서비스에 대해 몇 가지 메모해 두겠습니다.

Docker 측 루트 폴더에 Dockerfile이 있습니다. 이 구성 파일은 이미지 작성 방법을 설명하며, 주요 사항은 다음과 같습니다:

  1. 이 이미지는 ubuntu:latest 기반의 이미지입니다. 이 사항이 Linux 실행 파일로 유니티 프로젝트를 빌드 한 이유입니다. Gameye에서 실행되는 게임의 권장되는 OS입니다.
  2. 예를 들어 게임 바이너리와 같은 특정 폴더의 일부 파일을 GE_DIRGAME에 할당하는 데 사용되는 몇 가지 환경 변수를 정의합니다. README.md 파일은 이러한 모든 변수에 대해서 설명합니다.
  3. 결국, 우리는 이미지가 docker-entrypoint.sh 파일을 실행해야 한다는 신호를 Docker에게 보냅니다. 이 파일을 보면 특정 매개 변수를 사용하여 igniter-shell(Igniter툴에서 실행 가능)을 실행할 뿐입니다. 사용법에 대한 자세한 내용은 공식 페이지에서 찾아볼수 있습니다.

Gameye 관련 파일들에 대해서 알아보도록 하겠습니다. 서비스 문서를 읽어보셨으면, 2가지 종류의 구성 파일이 필요하다는 것을 아실 겁니다: (i) args.yaml 그리고 (ii) config.yaml 파일입니다. 게임 서버가 오케스트레이션 시스템과 함께 작동하려면 해당 파일에 대한 몇 가지 상세 값이 필요합니다.

우리의 경우에 있어서, args.yaml 파일은 arg/main.yaml에 있으며, 서버에서 오픈되어야 할 모든 필요한 포드들을 등록하여 외부 세계와 통신할 수 있도록 합니다. 보시다시피, (i) server (게임 서버 포트), (ii) query (A2S 쿼리용), 그리고 (iii) 모든 Photon 관련 포트들 (if you plan to use Photon을 매치메이킹으로 사용할 계획인 경우)을 사용할 수 있도록 되어 있습니다. 이 파일은 이전에 연락했던 Gameye 계정 관리자에게 전송되어, 관리자가 설정할 수 있도록 해야 합니다.

동일한 패턴을 따라 하여, config/main.yaml에 있는 config.yaml 파일이 있습니다. argsconfig 파일은 동일한 이름 (우리의 경우에는 main.yaml)으로 사용되어야 한다는 것을 주의해 주십시오. 이 구성 파일은 좀 크지만, 파악하기는 쉽습니다:

  1. cmd: 여기에서는 서버로 보낼 명령 줄 인수에 대해 설명합니다. 따라서 우리는 게임을 헤드리스 모드 (-batchmode -nographics -logFile)로 시작하고 아규먼트로 필요한 포트 정보를 전달합니다(-port ${port.server} -query ${port.query}). Igniter 는 적절한 값으로 동적 갑을 교체하는 것에 대해 책임이 있습니다.
  2. script: 이 섹션에서는 게임 서버가 수행할 수 있는 모든 상태와 전환에 대해 설명하고, 여기서 이전에 얘기했던 key strings을 구성합니다. 보시다시피 Igniterplaying 상태로 변경할 때 GAMEYE STATE CHANGE PLAY와 같은 값을 기대합니다. 모든 파라미터는 Gameye 페이지에 잘 설명되어 있습니다.
  3. defaults: 마지막으로, 아규먼트에 대한 몇 가지 기본값을 설정합니다.

이제 템플릿의 작동 방식에 대한 모든 기본 사항을 알게 되었으며, 필요한 사항을 수정할 준비가 되어 있어야 합니다. Docker Image를 업로드하기 전에, you need to setup the Gameye를 설정하여 Docker 리포지토리에 접근하고 푸시 웹 후크를 구성하여 바이너리의 새로운 버전을 업로드할 때 서비스가 알 수 있도록 해야 합니다. Gameye 문서 페이지에서 더 많은 내용을 확인하실 수 있습니다. 빌드 알림 전송이미지 권한 섹션을 찾아보십시오. 또다시, Gameye 계정 관리자가 다시 한번 이 단계를 도와줄 것입니다.

좋습니다. 이제 모든 준비가 완료되었으니 make upload 명령을 실행하는 DockerHub에 이미지를 업로드하거나 docker push username/image_name:version을 사용하여 수동으로 이미지를 업로드하십시오. 몇 분 안에 사용할 수 있을 것입니다.

서버 배포 체크

배포에 문제가 없는지 간단하게 확인할 수 있는 한 가지 방법은 Gameye REST API를 사용하여 새 서버를 요청하고 새 서버가 있는지 확인하는 것입니다. REST API 문서에 대해서는 이 링크를 확인해보시기 바랍니다.

이제 Gameye 직원이 보내 준 정보인 Gameye Application Token을 사용할 때입니다. 모든 {key}를 받은 Token으로 바꾸십시오. 먼저 다음 명령을 실행하여 이미 실행 중인 서버가 있는지 확인해야 합니다.

bash

curl --request GET \
  --url https://api.gameye.com/fetch/match \
  --header 'authorization: Bearer {key}'

실행되고 있는 서버가 없다는 다음과 같은 응답을 받게 됩니다:

JSON

{
    "match": {}
}

게임 서버를 요청하기 위해서는, 다음과 같은 다른 API 엔드 포인트를 사용합니다:

bash

curl --request POST \
  --url https://api.gameye.com/action/start-match \
  --header 'authorization: Bearer {key}' \
  --header 'content-type: application/json' \
  --data '{"locationKeys":["{locationKeys}"],"matchKey":"{name}","gameKey":"{gameKey}","templateKey":"{templateKey}","endCallbackUrl":"{endCallbackUrl}"}'

이 호출에 대하여 몇 가지 주의 사항들입니다:

  1. locationKeys: 사용 가능한 지역의 목록은 여기를 참고하세요.
  2. matchKey: 새로운 요청을 할 때마다 유일한 ID가 되어야 합니다. 복제된 키는 서버가 존재하지 않더라도 에러가 발생됩니다.
  3. gameKey: 어떤 서버가 실행될지를 나타내는 키로 Gameye 직원에 의해서 고정되고 설계됩니다. 해당 직원이 사용할 키를 알려주게 됩니다.
  4. templateKey: args.yaml 그리고 config.yaml에서 사용되는 파일의 이름과 동일하게 템플릿 값을 맞춰야 합니다. 우리 예제에서는, 이 파일들의 이름으로 main.yaml을 사용하고 있으므로, 이 아규먼트로는 "main" 문자열을 전달해주어야 합니다.
  5. endCallbackUrl: 이름에서 알 수 있듯이, 이것은 플레이가 끝날 때 호출될 웹 후크입니다. 서버에서 통계를 가져오는 데 유용합니다.

올바른 파라미터로 요청을하면, 다음과 같은 응답을 받게됩니다:

JSON

{
    "id": "bfc5890f-9ba2-46ef-bb69-31ac5cf6a092",
    "image": "boltgameimage",
    "location": "washington_dc",
    "host": "123.456.789.000",
    "created": 1590002692454,
    "port": {
        "server": 53723,
        "query": 51642,
        "masterServer1": 55488,
        "masterServer2": 49784,
        "gameServer1": 62047,
        "gameServer2": 50203,
        "nameServer1": 57337,
        "nameServer2": 61128
    }
}

새 게임 서버를 성공적으로 배포했으며 일부 플레이어에 대한 준비가 완료되었음을 나타냅니다. 보시다시피 공개 IP와 수신 포트에 대한 정보는 args.yaml 파일에 나와 있습니다.

좋습니다. 이제 서버를 종료하겠습니다. 다음 호출을 사용하여 Gameye에게 세션을 중지하도록 요청하십시오:

bash

curl --request POST \
  --url https://api.gameye.com/action/stop-match \
  --header 'authorization: Bearer {key}' \
  --header 'content-type: application/json' \
  --data '{"matchKey":"example-match"}'

보시다시피, 우리는 어떤 세션을 킬할 것인지 알리기 위해 matchKey만 사용할 것입니다. 쉽습니다. 이 요청에 대해서는 응답이 없습니다.

게임 클라이언트 상세 내용

이제 작업 서버가 생겼으니 연결할 클라이언트가 필요합니다. 이 섹션에서는 구축한 클라이언트 샘플에 대해 설명하므로, 이 샘플부터 시작하여 필요에 맞게 확장할 수 있습니다. samples_pro 안에 있는 GameyeIntegration 폴더를 다시 보면 우리가 이전에 언급했던 GameyeClient 씬이 나옵니다. 이것이 우리 플레이어들의 시작점이 됩니다.

요약하면, 플레이어에서는 사용 가능한 모든 게임 서버를 볼 수 있는 단순화된 로비 씬을 사용하지만 REST API를 사용한 것처럼 새 서버를 찾을 수 없는 경우 새 서버를 요청합니다.

플레이어의 UI는 매우 간단하며, 두 가지 주요 부분으로 구성됩니다. (i) 새 서버 요청 버튼이 있는 서버를 찾을 수 없음 패널과 (ii) 서버 목록을 보여주는 로비 목록입니다.

이는 GameyeUIManager 클래스가 관리하며, 이벤트(클래스의 requestServerEvt 액션 참고)를 사용하여 서버 요청을 발생시키는 역할과 서비스에서 수신된 데이터와 서버 목록을 나타내줍니다(다음에서 더 자세하게 다룹니다). GameyeUIServerInfoManager 클래스도 있는데, 이 클래스는 서버 리스트 안에 있는 항목을 나타내며 UI 컨텐츠를 발생하고 참여버튼을 클릭하는 것에 대하여 응답하는 역할을 하고 있습니다.

게임 클라이언트의 핵심 섹션은 다음과 같은 클래스입니다.

GameyeApi

여기서는 Gameye 문서에 설명된 REST API를 기반으로 간단한 HTTP 클라이언트를 구현했습니다. API를 사용할 때 두 가지 유형이 모두 필요하기 때문에 GETPOST 요청을 수행할 수 있습니다.

이 샘플에서는 다음 방법으로 표현되는 두 가지 유형의 요청만 사용합니다.

  1. RequestServer: 이 기능을 호출하면 Gameye에 미리 정의된 값을 가진 새 게임 서버를 생성하도록 요청할 수 있습니다. 이 작업의 결과는 인수로 전달된 작업 콜백에 수신됩니다.

  2. GetSessionList: 이 메소드는 현재 활성 게임 서버 목록을 요청하고 정보를 관리되는 형식으로 구문 분석합니다. 이 메소드는 GameyeData.cs 파일에서 이 서버의 클래스 정의를 찾을 수 있습니다.

GameyeClientManager

이 클래스는 플레이어 관리의 중앙 클래스로, 이미 설명한 다른 모든 부품을 통합하고 함께 작동하도록 하는 역할을 합니다. 이 클래스는 다음 작업을 수행할 수 있는 것으로 설명할 수 있습니다:

  1. API를 사용하여 Gameye 서비스에 정보를 요청하고 처리된 데이터로 UI를 채워 활성 서버 목록을 업데이트합니다. 이 문제는 refreshInterval을 기반으로 정기적으로 발생합니다. 간격값(UpdateSessions 메소드)입니다.
  2. UI 입력을 기반으로 새 게임 서버 생성을 요청합니다.(RequestServer 메소드).
  3. 클라이언트를 시작하고 원격 게임 서버에 연결합니다 (JoinSession 메소드).

모든 메소드들은 보다 상세한 정보로 잘 문서화되어 있습니다.

Game 클라이언트 실행하기

이제 움직이는 부분들이 어떻게 연동되는지 더 잘 알았으니 전용 서버에 연결하도록 클라이언트를 구성해 보겠습니다. 유니티 클라이언트는 서버에 있었던 두 씬으로 구성되어 있습니다. (i) 지난 섹션에서 설명한 GameyeClient는 메뉴 씬이고, (ii) 우리가 본 것과 같은 게임 내 씬인 GameyeInGame은 플레이스 홀더에 불과합니다.

게임 클라이언트 실행을 위해서 다음 단계를 따라 하십시오:

  1. GameyeClient 씬을 엽니다. 씬에서 GameyeClient (오리지널 이름)라고 이름이 붙여진 것을 찾을 수 있으며, 이것을 인스펙터에서 오픈합니다. GameyeClientManager 컴포넌트가 있으며 반드시 Gameye Application Token으로 구성해야 합니다. 프리팹 변경 내용을 적용하고 씬을 저장할 수 있습니다.
  2. Build Settings 창을 열고 씬 목록의 인덱스 0에는 GameyeClient, 인덱스 1에는 GameyeInGame로 설정합니다.
  3. Bolt 를 재컴파일(Bolt/Compile Assembly)하여 씬 구성을 인식할 수 있도록 합니다.
  4. 이제 편집기에서 클라이언트를 실행하거나 독립 실행형 버전을 만들 수 있습니다.

클라이언트를 실행하면 새 서버 요청 버튼이 30초 동안 기본적으로 비활성화되어 있습니다. 새 서버를 요청하기 전에 이미 실행 중인 서버가 없는지 확인하기 위한 것입니다.

request new server panel
새로운 서버 패널 요청.

서버 목록은 기본적으로 20초마다 업데이트되며, "새로 고침 간격" 슬라이더를 이동하여 변경할 수 있습니다. Gameye1분당 API 요청 제한이 있으므로, 적절한 값으로 두기를 권고합니다. 서버를 사용할 수 없는 경우 요청 단추를 클릭하면 비동기 요청이 수행됩니다. 모든 것이 정상적으로 진행되면 콘솔 로그에 JSON 응답이 표시되고 몇 초 후(또 다른 새로 고침 업데이트 후) 세션이 로비 목록에 나타납니다. 일부 서버 정보는 서버 이름, 현재 로드된 맵, 플레이어 수/최대 플레이어 수 및 작성 시간과 같이 표시됩니다. 이 모든 추가 정보는 A2S Server Queries API를 통해 제공됩니다.

lobby screen
로비 씬.

이 서버에 연결하려면 참여 버튼을 클릭하십시오. 클라이언트가 게임 내 장면을 연결하고 로드합니다.

in game scene
In Game Scene.

좋습니다. 여기서 샘플 코드의 기본 기능을 확장하여 세션을 필터링하거나 서버에 대한 자세한 정보를 표시하거나 특정 게임 서버 유형을 요청할 수 있습니다(이 작업은 이름 및 값이 다른 여러 config.yaml 파일이 있고 서버를 요청할 때 올바른 templateKey를 사용하여 수행됩니다).

Back to top