2 - 네트워크 콜백

<< 이전 챕터

목차

Bolt는 다른 유니티용 네트워킹 솔루션과 비교해보면 완전히 다른 방식으로 복제를 수행합니다. 데이터 직렬화에 대한 코드를 직접 코딩하는 대신에, Unity 네트워킹 솔루션에 내장된 OnSerializeNetworkView를 사용하는 것과 같이 Bolt는 트랜스폼, 애니메이션과 사용자 정의 프로퍼티를 네트워크상에서 자동적으로 복제 하도록 합니다 - 코딩을 전혀 할 필요가 없습니다. 사실 이 모든 튜토리얼에서 저수준 네트워킹 코드를 작성하지 않으며 Bolt가 모든 것을 대신해 줍니다.

카메라 추가하기

먼저 카메라를 추가하여 무엇이 어떻게 진행되는지 보게 할 것이지만 씬에 카메라를 그냥 놓는 대신에, Bolt를 살펴보고 콜백에 대하여 후킹을 할 것입니다. 완료된 튜토리얼은 우리가 필요한 모든 기능이 들어 있는 카메라의 기능을 이미 갖고 있기 때문에, 이 튜토리얼에서는 3인칭 카메라 구축에 대해서는 다루지 않을 것이고 그대로 사용할 것입니다.

Assets/samples/AdvancedTutorial/prefabs/singletons/resources/PlayerCamera에서 카메라 프리팹을 찾을 수 있으며 관련된 스크립트는 Assets/samples/AdvancedTutorial/scripts/player/PlayerCamera.cs에 있습니다. 카메라 스크립트는 Bolt 내부에서 정의되어 있는 유틸리티 기본 클래스인 BoltSingletonPrefab<T>에서 상속받았고, 자동으로 Resources의 프리팹을 로드하는데 사용됩니다.

이제 첫 번째 스크립트를 작성할 시간입니다. Tutorial/Scripts/Callbacks 폴더를 생성하고 나서 TutorialPlayerCallbacks.cs라고 하는 스크립트를 생성해 주세요.

  1. 클래스를 Bolt.GlobalEventListener에서 상속받습니다
  2. 이 클래스에 [BoltGlobalBehaviour("Level2")] 어노테이션을 적용 를 클래스에 적용합니다. 이 경우에 목표 씬인 Level2를 선택합니다.
  3. Bolt.GlobalEventListener에서 상속된 SceneLoadLocalDone 메소드를 오버라이드 합니다. 이 메소드에 대해서는 당사 API 페이지에서 확인해보세요.
  4. 파일의 상단에 using Bolt.AdvancedTutorial;을 삽입하여 PlayerCamera에 접근할 수 있도록 해 줍니다.
  5. SceneLoadLocalDone 내부에서 PlayerCamera.Instantiate() 호출을 오버라이드 합니다 (네, 아규먼트 없이)
  6. 씬의 어떤 게임 오브젝트에도 이 행위를 붙이지 않는 것이 매우 중요합니다
using Bolt.AdvancedTutorial;
using UnityEngine;

[BoltGlobalBehaviour("Level2")]
public class TutorialPlayerCallbacks : Bolt.GlobalEventListener
{
    public override void SceneLoadLocalDone(string map)
    {
        // this just instantiates our player camera,
        // the Instantiate() method is supplied by the BoltSingletonPrefab<T> class
        PlayerCamera.Instantiate();
    }
}

Callbacks Script
플레이어 콜백 스크립트 경로.

게임을 시작하기 전에, 여기에서 어떤 일이 발생하는지를 정확하게 설명하는 것은 좋은 생각입니다. [BoltGlobalBehaviour]는 도대체 무엇을 하는 거죠? Bolt가 시작할 때 그것은 [BoltGlobalBehaviour]를 가지고 있는 모든 클래스들을 찾을 것이고 동일한 방식으로 MonoBehaviour에서 상속된 모든 것을 찾습니다(Bolt.GlobalEventListener 자체가 MonoBehaviour에서 상속받았기 때문에 우리 클래스인 TutorialPlayerCallbacksMonoBehaviour 에서 상속받았다고 간주됩니다).

Bolt는 클래스들을 조사하여 이 두 개의 조건에 맞는 것을 찾아 자동으로 클래스들의 인스턴스를 생성하여 Bolt가 실행되었을 때 존재하도록 하게 만들고 Bolt가 셧다운 되었을 때 파괴시켜 줍니다. 생성된 모든 인스턴스들은 시작할 때 Bolt가 자동적으로 생성해 놓은 BoltBehaviours 게임 오브젝트에 추가될 것이고 씬의 계층구조에서 명백히 볼 수 있게 될 것입니다.

[BoltGlobalBehaviour]이 어떻게 행동하는지 구성하는 두 가지의 방법이 있습니다. 첫 번째 방법은 가장 간단한 것으로 서버 또는 클라이언트 또는 두 곳 모두에서 행동을 실행해야 할지에 대한 것을 결정할 수 있습니다. TutorialPlayerCallbacks 클래스에서 했던 것과 같이 아무것도 지정하지 않는 것은 서버와 클라이언트 모두 실행될 것입니다.

// only on the host
[BoltGlobalBehaviour(BoltNetworkModes.Server)]

// only on the client
[BoltGlobalBehaviour(BoltNetworkModes.Client)]

또한 예를 들어 Level2와 같이 Bolt에게 특정 씬에서만 사용할 수 있도록 할 수도 있습니다.

// only when the current scene is 'Level2'
[BoltGlobalBehaviour("Level2")]

// only when the current scene is 'Level1', 'Level2' or 'Level3'
[BoltGlobalBehaviour("Level1", "Level2", "Level3")]

이러한 것을 결합할 수도 있습니다.

// only when we are the host AND the current scene is 'Level2'
[BoltGlobalBehaviour(BoltNetworkModes.Server, "Level2")]

// only when we are the client AND the current scene is 'Level2'
[BoltGlobalBehaviour(BoltNetworkModes.Client, "Level2")]

이것은 DontDestroyOnLoad로 표시된 게임 오브젝트를 모든 장면에서 전달하면서 수동으로 검토할 필요 없이 전체 응용 프로그램이나 전체 씬에 대해 전역적인 동작으로 쉽게 정의할 수 있게 하는 Bolt에 내장된 부분입니다. 앞에서 언급했듯이 어떤 상황에서도 이러한 스크립트를 씬의 오브젝트에 수동으로 연결하지 않으면 Bolt가 자동으로 이 스크립트를 처리한다는 것이 중요합니다.

메인 화면으로

카메라 시작하기

Window/Bolt Scenes 윈도우를 열고 Level2 씬에서 Play As Server 를 클릭하십시오. 이제 Game 윈도우에서 서버가 시작되고 카메라의 인스턴스가 생성되는 것을 볼 수 있어야 합니다.

Play the game as Server
서버로서 게임 실행. (1) 서버로서 Level2 씬 시작, (2) 게임 실행, (3) BoltBehaviours 게임 객체, (4) 스크립트에 의해 생성된 PlayerCamera 객체, (5) Bolt와 같이 실행되는 TutorialPlayerCallbacks 스크립트.

씬 계층 구조를 보면 BoltBehaviours라는 게임 객체를 볼 수 있습니다. 이 객체는 Bolt 내부 객체이며, 완전히 보이게(HideFlags 아님)하여 모든 상황을 파악할 수 있습니다. 이 객체를 인스펙터에서 보면 Bolt가 자동으로 인스턴스화하는 모든 내부 동작과 아래에 TutorialPlayerCallbacks 동작이 표시됩니다. SceneLoadLocalDone 콜백에서 인스턴스화된 PlayerCamera도 표시됩니다.

메인 화면으로

프리팹 생성하기

이 섹션에서는 플레이어를 설정할 것이며, 이 프로세스는 Photon Bolt를 사용하여 동기화/컨트롤하기 위하여 모든 플레이어에 반복할 수 있습니다. 새로운 게임 오브젝트를 생성하여 TutorialPlayer로 이름을 부여합니다. 위치는 (0, 0, 0), 회전은 (0, 0, 0) 그리고 스케일은 (1, 1, 1) 으로 해주시기 바랍니다. 우리가 사용하려는 모델은 bolt_tutorial/art/models/sgtBolt 에 있으며 프리팹은 sgtBolt4Merged-ModelOnly입니다. 이 프리팹의 인스턴스를 계층구조로 드래그합니다. sgtBolt4Merged-ModelOnlyTutorialPlayer 객체와 같은 위치, 회전과 스케일 값을 갖도록 해 주세요. 이제 sgtBolt4Merged-ModelOnly 오브젝트를 TutorialPlayer 오브젝트의 자식에 오도록 드래그해주세요.

Player prefab
튜토리얼 플레이어 프리팹.

tutorial 폴더에서 Prefabs라는 새로운 폴더를 생성하고 TutorialPlayer 오브젝트를 이 폴더로 드래그하여 프리팹을 만들어 주세요. 이제 씬 계층구조에서 TutorialPlayer 오브젝트를 삭제할 수 있습니다.

Player prefab
튜토리얼 플레이어 프리팹.

TutorialPlayer 프리팹을 선택하고 여기에 Bolt Entity 컴포넌트를 추가해주세요.

Bolt Entity on prefab
프리팹상의 Bolt 엔티티. 예상되는 컴포넌트 상 모든 경고 (붉은 느낌표)로 다음 단계에서 해결합니다.

Bolt Entity 컴포넌트는 Unity 또는 Photon 내의 Network View 와 느슨하게 연결되어 있지만, Bolt 내에서 두 개의 추가적인 목적으로 이용됩니다. 첫 번째로 해야 할 것은 두 개의 에러를 잡는 것으로 상단 메뉴바에 있는 Bolt/Compile Assembly로 수행됩니다.

Assets/Compile Bolt Assets 을 실행하면 Bolt는 모든 프리팹과 다른 Bolt 관련된 에셋을 검토하여 효율적인 네트워크 프로토콜로 컴파일 하여 Assets/Photon/PhotonBolt/assemblies 폴더에 있는 bolt.user.dll내에 저장합니다. Bolt 내의 몇 가지 항목에 대해서 Assets/Compile Bolt Assets 커맨드가 수행되었으나 이 튜토리얼에서는 모든 것을 다루지 않을 것입니다.

컴파일을 수행 후, 프리팹에 있는 Bolt Entity 컴포넌트는 다음과 같이 보여야 합니다.

Tutorial Player Entity with new ID
새로운 ID를 가진 튜토리얼 플레이어 엔티티.

그림처럼, Bolt 엔티티는 상태가 없으며 다음 단계에서 다룹니다.

메인 화면으로

Bolt 내의 상태

세부적으로 더 살펴보기 전에 Bolt에서는 "상태" 가 무언인지 정의해보겠습니다. 상태는 게임 오브젝트의 트랜스폼, 애니메이션과 데이터입니다. Bolt는 엔티티들에게 트랜스폼과 애니메이션(메카님만, 레거시 미지원)을 포함하여 지정되어 있는 모든 상태를 네트워크를 통해 자동적으로 복제할 것 입니다.

다른 유니티용 네트워크 솔루션과 비교해보면, Bolt는 네트워크를 통해 데이터를 전송하는 것에 매우 다른 접근법을 취하고 있습니다. 직렬화, 비직렬화인터폴레이션 코드를 직접 코딩하는 대신 Bolt는 데이터와 상호작용을 Uniyt Editor의 편리한 인터페이스를 통해서 정의하도록 합니다. 우리는 앞으로 사용할 수 있도록 DSL(Domain Specific Language)을 추가 중이며 문장으로 동일하게 정의할 수 있도록 해줍니다.

Bolt에서는 Bolt/Assets 창에서 찾을 수 있는 네트워킹 에셋의 정의를 다루는 2개의 에디터 윈도우가 있습니다. Bolt Assets 창을 열면 완료된 튜토리얼 프로젝트에 있었던 에셋들의 목록을 볼 수 있을 것입니다.
TutorialPlayer용 상태를 생성하면서 시작할 것이고, Bolt Assets 창에서 우측 클릭을 하여 New State를 선택합니다.

Bolt Assets: These includes States, Objects, Commands and Events. Use this window to create a new *State* for our player.
Bolt Assets: 상태, 객체, 명령어와 이벤트들이 포함되어 있습니다. 플레이어용으로 새로운 State를 생성하기 위해 이 창을 사용합니다.

Bolt가 편집기 창을 자동으로 열지 않은 경우 새로 생성된 상태 NewState를 클릭하여 열 수 있습니다. 다음 단계를 따라 하여 이 새로운 state를 설정합니다.

  1. 상태 이름을 TutorialPlayerState로 부여합니다.
  2. 새로운 Property를 생성합니다.
  3. Transform으로 이름을 변경합니다.
  4. Transform으로 유형을 변경합니다.
  5. Replication 모드를 Everyone Except Controller로 변경합니다.

Setup the new Bolt State `TutorialPlayerState` for using during the Advanced Tutorial
고급 튜토리얼을 진행하는 동안 사용되는 새로운 Bolt 상태 TutorialPlayerState 설정.

Transform에 있는 다른 사용 가능한 설정은 기본값 그대로 두어야 합니다. 이 옵션들은 속성의 우선순위와 스무딩 알고리즘과 같은 Bolt의 더 복잡한 부분을 구성하도록 해 줍니다. Bolt 에셋에 대해서 변경을 했으므로 Bolt/Compile Assembly 메뉴에서 을 다시 컴파일을 수행해 주세요.

다시 TutorialPlayer 프리팹을 선택하고 Prefab & State / State 하단의 Bolt Entity 스크립트가 ITutorialPlayerState 라고 하는 시리얼라이저를 이제 사용할 수 있습니다. 이 코드는 State 정의를 기반으로 내부 복제 구현을 위한 네트워크 준비 인터페이스인 컴파일 후 Bolt가 생성하는 코드의 일부입니다. 변경 사항을 저장하려면 Apply 버튼을 클릭해야 하는 것을 잊지 마세요.

Select the new State *ITutorialPlayerState* to be used by the *TutorialPlayer* prefab
TutorialPlayer 프리팹에서 사용되는 새로운 상태 ITutorialPlayerState 선택.

현재까지 Prefab에서 해야 할 모든 일이며, 나중에 이 State를 코드로 사용하여 네트워크로 연결될 항목을 설정할 것입니다.

메인 화면으로

씬 로딩 콜백

게임에서 캐릭터 스폰 하기 전에 몇 가지 일을 더 해야 합니다. 서버 또는 서버와 클라이언트 모두에게 프리팹의 인스턴스를 생성하는 콜백을 후킹 할 필요가 있습니다.

Tutorial/Scripts/Callbacks 폴더에서 TutorialServerCallbacks 스크립트를 생성합니다.

New `TutorialServerCallbacks` script
새로운 TutorialServerCallbacks 스크립트.

using UnityEngine;

[BoltGlobalBehaviour(BoltNetworkModes.Server, "Level2")]
public class TutorialServerCallbacks : Bolt.GlobalEventListener
{
    public override void SceneLoadLocalDone(string map)
    {
        BoltNetwork.Instantiate(BoltPrefabs.TutorialPlayer);
    }

    public override void SceneLoadRemoteDone(BoltConnection connection)
    {
        BoltNetwork.Instantiate(BoltPrefabs.TutorialPlayer);
    }
}

TutorialServerCallbacks 클래스는 Bolt.GlobalEventListener 클래스에서 상속되어야 합니다. 클래스는 BoltGlobalBehaviour를 이용하여 서버(BoltNetworkModes.Server)에서만 수행될지 Level2 씬에서만 수행될지 선택해야 합니다.

씬 로딩에서 해주어야 하는 2개의 콜백을 오버라이딩합니다:

  1. SceneLoadLocalDone : 로컬 컴퓨터에서 씬 로딩이 끝났을 때 호출될 것이고 이 행동은 서버에서만 수행되도록 표시되어 서버에서만 활성화될 것입니다.

  2. SceneLoadRemoteDone : 로드된 씬으로 전달(BoltConnection connection)되어지는 연결 말단에서 씬을 로드할 때 호출됩니다. 따라서 Bolt는 이 행동을 서버에서만 수행되어 클라이언트가 현재 씬의 로딩을 완료했을 때를 알려주게 됩니다.

두 메소드 모두에서 TutorialPlayer 프리팹 복사본을 인스턴스화합니다. BoltPrefabs 클래스에는 Bolt 엔티티 프리팹들의 각 필드를 포함하고 있으며 모두에 쉽게 접근할 수 있다는 것을 참고하세요.

Bolt Scenes 윈도우에서 Play As Server 버튼을 눌러 서버의 인스턴스를 시작합니다. 이전에 씬에서 시작했던 것과는 크게 다르지 않지만 계층구조에서 TutorialPlayer 프리팹의 인스턴스를 볼 수 있을 것 입니다.

The TutorialPlayer prefab instantiated on the scene
씬에서 인스턴스화된 TutorialPlayer 프리팹.

서버에 접속하는 독립된 클라이언트를 빌드하고 실행할 수 있습니다. 계층 구조에서 두 개의 TutorialPlayer 프리팹을 볼 수 있을 것입니다.

다음 챕터 >>

기술문서 TOP으로 돌아가기