Bolt 튜토리얼 - 챕터 2

<< 이전 챕터

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

카메라 추가하기

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

bolt_tutorial/prefabs/singletons/resources/PlayerCamera 에서 카메라 프리팹을 찾을 수 있으며 관련된 스크립트는 bolt_tutorial/scripts/player/PlayerCamera.cs 에 있습니다.

카메라 스크립트는 Bolt 내부에서 정의되어 있는 유틸리티 베이스 클래스인 BoltSingletonPrefab\ 에서 상속받았고, 자동으로 Resources 의 프리팹을 로드하는데 사용됩니다.

이제 첫 번째 스크립트를 작성할 시간입니다. tutorial 폴더내에 TutorialPlayerCallbacks.cs 라고하는 스크립트를 생성해주세요.

  • 클래스를 Bolt.GlobalEventListener 에서 상속 받습니다
  • [BoltGlobalBehaviour] 를 클래스에 적용합니다
  • Bolt.GlobalEventListener 에서 상속된 SceneLoadLocalDone 메소드를 오버라이드 합니다
  • SceneLoadLocalDone 내부에서 PlayerCamera.Instantiate() 호출을 오버라이드 합니다 (네, 아규먼트 없이)
  • 씬의 어떤 게임 오브젝트에도 이 행위를 붙이지 않는 것이 매우 중요합니다
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();
  }
}

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

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

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

// only on the server
[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 server 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가 자동으로 이 스크립트를 처리한다는 것이 중요합니다.

Back To Top

카메라 시작하기

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

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

Back To Top

프리팹 생성하기

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

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

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

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

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

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

Back To Top

Bolt 내의 상태

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

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

Bolt에서 2개의 에디터 윈도우인 Window/Bolt Engine/AssetsWindow/Bolt Engine/Editor 를 사용할 수 있는데 네트워킹 에셋 정의를 합니다. Window/Bolt Engine/Assets 윈도우를 열면 완료된 튜토리얼 프로젝트에 있었던 에셋들의 목록을 볼 수 있을 것 입니다.

이제 TutorialPlayer 프리팹에 대한 상태를 생성하겠습니다. Bolt Assets 아무데서나 우측 클릭을 하여 New State 를 선택합니다. States 헤더 옆에 있는 작은 아이콘을 클릭해도 됩니다.

Bolt가 자동적으로 에디터를 오픈하지 않으면 새롭게 생성된 상태 NewState 를 클릭하여 오픈할 수 있습니다. 상태를 TutorialPlayerState 로 이름을 부여 합니다.

지금까지는 상태관련 설정을 변경하지 않고 그대로 두었으나, 복제를 위하여 우리 트랜스폼의 속성을 생성할 필요가 있습니다. 방금 변경했던 상태명 상단 왼쪽에 있는 'New Property' 를 클릭합니다. 속성 이름을 'Transform' 로 부여하고 타입은 'Transform' 으로 선택해주세요.

Transform에 있는 다른 사용가능한 설정은 기본값 그대로 두어야 합니다. 이 옵션들은 속성의 우선순위와 스무딩 알고리즘과 같은 Bolt의 더 복잡한 부분을 구성 하도록 해 줍니다. Run Assets/Bolt Compile Assets (All) 을 다시 수행해주세요.

다시 TutorialPlayer 프리팹을 선택하면 Serializer 하단의 Bolt Entity 스크립트가 ITutorialPlayerState 라고하는 시리얼라이저를 이제 사용할 수 있습니다.

Back To Top

씬 로딩 콜백

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

tutorial/Scripts/Callbacks 폴더에서 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 를 이용하여 서버에서만 수행될지 Level2 씬에서만 수행될지 선택해야 합니다.

씬 로딩에 관련되어 있는 두개의 콜백을 오버라이딩 할 것인데 하나는 SceneLoadLocalDone 으로 로컬 컴퓨터에서 씬 로딩이 끝났을 때 호출될 것이고 이 행동은 서버에서만 수행되도록 표시되어 서버에서만 활성화 될 것 입니다.

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

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

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

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

다음 챕터 >>

기술문서 TOP으로 돌아가기