Bolt 102 - はじめに

このチュートリアルでは、Boltでマルチプレイヤーゲームを作成する方法を説明します。Boltを使用してシンプルな画面を複数設定していきます。Boltの内部での変換の置換やオブジェクトのスポーンといった全ての基本タスクをいかに行うか、ステップ・バイ・ステップで見ていきましょう。チュートリアルとして明確に説明するため、自動化やテストツール内のBoltのビルドはできる限り使用せず、コードを記述します。

このチュートリアルは、BoltのDEBUGビルドを用いながら読み進めていくように作られております。それ以外のビルドに関する詳細については、Debug vs. Releaseのページを確認してください。Boltのアップグレード方法についてはUpgradingを参照してください。 Boltのインストールとアップグレードを行うと、以下のようなフォルダ構造を得られます。

Bolt Folder on Unity Assets
Unityアセット上のBoltフォルダ

パッケージフォルダには、Bolt用のアドオンがあります。たとえば、サンプルやサーバーモニターなどです。これらをインポートする場合には、はじめよう チュートリアルで、既存のBoltアセットを作成するよう確認されます。この場合には、インポートを保留するか、または同じ名前で新規に作成する前に既存のBoltアセットを削除できます。

Boltが、Unity向けの他のネットワーキングソリューションと異なるのは、ネットワーキングコードを手動で書く必要がほとんどないという点です。シリアル化、補間、アニメーション複製などはすべてBoltで自動的に処理されます。

ネットワーク上で を複製したいのか、のみBoltに伝える必要があります。これは、Window/Bolt/Assets内の Bolt Assets ウィンドウで設定できます。

Access Bolt Assets from Window Menu
WindowメニューからBolt Assetsにアクセス

アセットは4つのカテゴリーに分けられます:

  • ステート:これらは、Boltで構築されるほとんどのゲームの中核となります。ステートによって、名前、ヘルス、変換、アニメーションパラメータなどを定義できます。

  • オブジェクト: オブジェクトは、C#クラスでおこなうのと同様に複数のプロパティを論理的にグループ化する方法です。たとえば、RPGゲームでプレイヤーにインベントリーを作成するとします。この場合、Item という名前の Object を作成し ItemIdDurability などのプロパティを設定することができます。その後、State 上に Item オブジェクトの配列を作成することが可能です。

  • コマンド: これらは Bolt のオーソリテーティブな機能に特化して使用され、ユーザー入力の要約や、ユーザー入力をワールドでキャラクターに適用した際の結果 を要約します。 コマンド によって、クライアントサイドでの高度な予測の実装や、予測されたステートの自動修正をおこなえるようになります。

  • イベント: これらは単純なメッセージです。イベントを使用すると、ゲーム内の様々な部分を分離することができます。これは、同時にアクティブな単一イベントに複数のリスナーを持てるためです。

Bolt Assetsウィンドウの最下部にBoltのバージョン番号、Debug / Release モードのどちらで構築されたか、またBoltアセットをコンパイルおよび保存するための2つのボタンが表示されます。

Bolt Assetsウィンドウの空白部分で右クリックし、 New Stateを選択してください。

Bolt Assets Window - Create a new State
Bolt Assetウィンドウ - ステートを新規作成

BoltNewStateという名前のステートを新規作成し、そのステートをアクティブにして Bolt Editorウィンドウをポップアップします。

Bolt Assets Window - New State
Bolt Assetウィンドウ - 新しいステート

新しいステートを設定します:

  1. 最初のテキストフィールドで、ステートの名前を CubeState に変更します。
  2. このステートに新しいプロパティを作成するには、 New Propertyをクリックします。
  3. CubeTransform; プロパティの名前を CubeTransformと設定します。
  4. タイプをTransformと設定します。
  5. 他の設定はデフォルトのままにしてください。

Bolt Assets Window - Edit New State
Bolt Assetウィンドウ - 新しいステートを編集

必要のないプロパティやアセットを誤って加えてしまった場合 Ctrl キーを押したままにしてください。小さな赤い X が全てのアセットおよびプロパティの隣にポップアップされ、アセットやプロパティを削除できるようになります。

コンパイルが必要なステートやプロパティをBolt に認識させるには、 Assets/Bolt/Compile Assembly メニューオプションから、または Bolt Assets ウィンドウの小さな緑の矢印アイコンから設定をおこないます。どちらからも同じ内容が実行できます。

Bolt Compile Menu
Boltのコンパイルメニュー

コンパイルすると、Boltは複数のメッセージをUnityエディターコンソール内に出力します。

Bolt Compile Output
Boltコンパイルの出力

Unity内の Project タブに進んで Tutorialという名前のフォルダを作成し、 ScriptsPrefabsという名前の2つのサブフォルダを作成してください。

New Tutorial Folder
新しいチュートリアルフォルダ

まず始めに、Bolt用にプレハブを作成します。これは標準的なUnityキューブとなります。新しいキューブの作成はGameObject/3D Object/Cube メニューからおこなってください。キューブを作成したら、Hierarchyから、Projectタブにある Tutorial/Prefabs のフォルダにドラッグしてください。ここまで完了したら、Hierarchyに残っているキューブを消去できます。

New Cube Prefab
新しいキューブプレハブ

この Cube のプレハブをBoltに認識させるには、プレハブに Bolt Entity コンポーネントを追加し、 Add Component をクリックして名前でコンポーネントを検索してください。

Bolt Entity Creation
Boltエンティティの作成

この Cube のプレハブをBoltが認識するのはこれが初めてであるため、Bolt Entityのコンポーネントエディタには複数のエラーが発生します。Prefab Id フィールドの下にある2つのエラーは、Bolt用のコンパイラーを実行することで解決できます。 Assets/Bolt/Compile Assembly から、または Bolt Assets ウィンドウにある緑の矢印アイコンからおこなってください。 State 欄の下にあるエラーを解決するには、ドロップダウンから ICubeStateステートを選択してください。現状では NOT ASSIGNED と表示されています。

Bolt Entity Setup
Boltエンティティのセットアップ

Bolt Entity のコンポーネントに関する設定の多くは変更可能です。ただし、ほぼ全てのプレハブやゲームのタイプでデフォルト設定が必要な条件を十分に満たしているため、設定を変更する必要はありません。これらの設定は、このドキュメントのさらに高度なセクションで説明されているような特殊な場合に用いられます。

実際のC#コードについて進めていく前に、キューブをスポーンさせたい単純なシーンをUnityに設定しましょう。新たにUnityシーンを作成し、Tutorial/Tutorial1に保存してください。 今回のシーンのために、GameObject/3D Object/Planeから接地面を作成します。GameObject/3D Object/Planeは基盤として、また接地面用の新しいマテリアルとして使用されます。接地面をTutorial/Material_Groundに保存してください。キューブ以外の色が使用可能となります。

Tutorial Scene Creation
チュートリアルシーンの作成

続いてメインカメラ接地面、Directional Lightを位置づけるための設定を説明します。これによって、類似したシーンの設定が可能になります。

Scene Configuration for each Game Object
各ゲームオブジェクトのシーン設定

それでは実際にコードを書いてみましょう。まず、 Tutorial/Scripts フォルダ内に NetworkCallbacks という名前の新たなスクリプトを作成します。 それを任意のテキストエディタで開き、デフォルトのUnityメソッドを削除してください。すると、ファイルは以下のようになります。

using UnityEngine;
using System.Collections;

public class NetworkCallbacks : MonoBehaviour
{

}

ベースクラスを MonoBehaviour から Bolt.GlobalEventListenerに変更します。Bolt.GlobalEventListener クラス自体が MonoBehaviour に由来するものです。このため、全て通常のUnityと同様の処理が可能ですが、最上部にはBolt特有のメソッドが複数追加されています。

using UnityEngine;
using System.Collections;

public class NetworkCallbacks : Bolt.GlobalEventListener
{

}

シーンがロードしているとき(今回は'Tutorial1'のシーンがロードしているとき)にコールバックを受信する必要があります。これは、 Cube のプレハブをインスタンス化 できるタイミングを把握するためです。Bolt は自動でネットワーク化されたUnityシーンのロードをサポートしており、これにフックしたいコールバックは、SceneLoadLocalDoneと呼ばれます。

Bolt は、メソッドの実装に public override 標準のC#を使用する点に留意してください。これはメソッドをオーバーライドとして指定しないUnityの方法と異なります。

using UnityEngine;
using System.Collections;

public class NetworkCallbacks : Bolt.GlobalEventListener
{
    public override void SceneLoadLocalDone(string map)
    {
        // Your code here...
    }
}

Bolt でプレハブのインスタンスを作成するには、 BoltNetwork.Instantiate メソッドを使用します。通常、これはUnityでの組み込みGameObject.Instantiate と 全く同様に動作します。このメソッドには様々な負荷やパラメータが存在しますが、ここでは比較的シンプルなものを用いていきます。Bolt プレハブリファレンス、ポジション、ローテーションを使用します。

using UnityEngine;
using System.Collections;

public class NetworkCallbacks : Bolt.GlobalEventListener
{
    public override void SceneLoadLocalDone(string map)
    {
        // randomize a position
        var spawnPosition = new Vector3(Random.Range(-8, 8), 0, Random.Range(-8, 8));

        // instantiate cube
        BoltNetwork.Instantiate(BoltPrefabs.Cube, spawnPosition, Quaternion.identity);
    }
}

XZ接地面での位置をランダム化し、全員が同じ場所にスポーンしないようにします。それから、BoltNetwork.Instantiateをランダムポジション、デフォルトローテーション、Cubeへのリファレンスと共に呼び出します。

BoltPrefabs.Cubeの使用は、Boltに慣れていないうちは難しいかもしれません。BoltPrefabsは静的なクラスで、Assets/Bolt/Compile Assemblyを実行した際にコンパイルおよびアップデートされます。BoltPrefabsには各プレハブへの一意のリファレンスとそれにおけるBolt Entityが含まれます。また、任意でプレハブに通常のGameObjectリファレンスを渡すことも可能です。

NetworkCallbacksスクリプトについて完了する前に、[BoltGlobalBehaviour]と呼ばれる属性を追加する必要があります。public class NetworkCallbacks ... 定義の上の行にこの属性を追加してください。

using UnityEngine;
using System.Collections;

[BoltGlobalBehaviour]
public class NetworkCallbacks : Bolt.GlobalEventListener
{
    public override void SceneLoadLocalDone(string map)
    {
        // randomize a position
        var spawnPosition = new Vector3(Random.Range(-16, 16), 0, Random.Range(-16, 16));

        // instantiate cube
        BoltNetwork.Instantiate(BoltPrefabs.Cube, spawnPosition, Quaternion.identity);
    }
}

この属性によって、Boltは自動的にこのスクリプトを検知し、そのインスタンスを作成できるようになります。これは Bolt と共生し、Boltがシャットダウンされると破棄されます。

重要: このスクリプトのインスタンスは、Unity内のどのGameObjectにも手動で添付しないでください。添付はBoltが自動で行います。Bolt.GlobalEventListener を手動でどこかに添付したい場合には、 [BoltGlobalBehaviour] の属性を追加してはいけません

キューブのスポーンをテストする前の最後のステップは、Boltを開始するメインメニューのスクリプトの設定です。新たなシーンを作成し、それを Tutorial/Tutorial1_Menuに保存してください。

先に進んでメニュー用のコードを書く前に、Tutorial1Tutorial1_Menuの両方のシーンが、Unity内のBuild Settingsに追加されていることを確認してください。

Configure Scenes to build
ビルドするシーンを設定

重要: 両方のシーンを追加したら、Assets/Bolt/Compile Assemblyを再度実行し、Boltにシーンを認識させてください。また、Tutorial1_Menu シーンが最初のシーンで(インデックス0)、ゲームが始まったらこの読み込まれるようになっていることを確認してください。

非常にシンプルなメニュースクリプトを作成し、それをTutorial1_Menuシーン内の MainCamera に添付します。 Tutorial/Scripts 内に、Menuという名前のスクリプトを作成してください。

using UnityEngine;
using System.Collections;

public class Menu : Bolt.GlobalEventListener
{
    void OnGUI()
    {
        // Your code here...
    }
}

デフォルトのUnityメソッドを削除し、 OnGUIメソッドを追加してください。画面のほぼ全体に渡るボタンを2つ作成します。1つはサーバーのスタート用、もう一つはクライアントのスタート用です。通常どおり、このクラスは Bolt.GlobalEventListenerから拡張するように設定する必要があります。これは、Boltの挙動を使用できるようにするためです。

using UnityEngine;
using System.Collections;
using System;
using UdpKit;

public class Menu : Bolt.GlobalEventListener
{
    void OnGUI()
    {
        GUILayout.BeginArea(new Rect(10, 10, Screen.width - 20, Screen.height - 20));

        if (GUILayout.Button("Start Server", GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true)))
        {
            // START SERVER
            BoltLauncher.StartServer();
        }

        if (GUILayout.Button("Start Client", GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true)))
        {
            // START CLIENT
            BoltLauncher.StartClient();
        }

        GUILayout.EndArea();
    }

    public override void BoltStartDone()
    {
        if (BoltNetwork.isServer)
        {
            string matchName = Guid.NewGuid().ToString();

            BoltNetwork.SetServerInfo(matchName, null);
            BoltNetwork.LoadScene("Tutorial1");
        }
    }

    public override void SessionListUpdated(Map<Guid, UdpSession> sessionList)
    {
        Debug.LogFormat("Session list updated: {0} total sessions", sessionList.Count);

        foreach (var session in sessionList)
        {
            UdpSession photonSession = session.Value as UdpSession;

            if (photonSession.Source == UdpSessionSource.Photon)
            {
                BoltNetwork.Connect(photonSession);
            }
        }
    }
}

全ての GUILayout.* コールは、標準的なUnityの仕様となっていますので割愛します。コードで特に重要な2点は、メソッドBoltStartDoneSessionListUpdated内にあります。

サーバーはBoltLauncher.StartServerを呼ぶことで起動され、これによってこのピアはゲームの ホストとして設定されます。サーバーを起動後に(BoltStartDone が呼ばれたら)、2つの重要なメソッドを呼び出します。

  1. BoltNetwork.SetServerInfo: このメソッドはPhoton Server上にPhoton Cloudのルームを設定します。これによって、新しいピアがこのルームに接続し参加できるようになります。この関数の最初の引数を使用してルーム名を設定します。たとえば、ルームにランダムな名前を作成することができます。
  2. BoltNetwork.LoadScene: このメソッドは Tutorial1 シーンをロードするよう Boltに伝えます。

クライアント上の処理はサーバー上での処理に似ています。このピアをクライアントとして設定して他のゲームに参加できるようにするため、 BoltLauncher.StartClientを呼び出します。主な違いは、クライアントが Host ピアに接続するには、Photon Server上でゲームサーバーによって作成されたルームについての情報が必要である点です。

Boltは自動でこの処理をおこなうため、設定は不要で利便性が高まっています。クライアントが開始すると、クライアントはPhoton Serverに接続し、クラウド上に登録され表示されているすべてのルームについての情報を取得します。この情報を取得するには、SessionListUpdatedハンドラーを使用します。このハンドラーは新しいルームの情報が内部的に到達すると、Boltによって定期的に呼び出されます。

SessionListUpdatedの実装では、利用可能なすべてのセッションを対象に Photon Session を検索し、最初に見つかったものに接続します。 クライアントは Host でパンチスルー処理を開始し、ゲームに参加します。

Menu スクリプトを Tutorial1_Menu シーン内の MainCamera ゲームオブジェクトに添付してください。

Tutorial Menu scene Setup
Tutorial Menuシーンのセットアップ

重要: Menu スクリプトの添付先が正しいシーンであることを確認してください。

ゲームを開始する前に、Unityの'Player Settings'で'Run In Background'を有効化してください。

Configure game to Run in Background
Run in Backgroundするよう、ゲームを設定

ゲームのスタンドアロンなデスクトップバージョンを作成し、その2つのインスタンスを開始してください。ほとんどの場合、ウィンドウには Windows Firewall のポップアップが表示されるので、Allow accessをクリックしてください。 Mac のマシン上では、ピアが接続を試行すると類似したウィンドウが表示されるためAllowをクリックします。

Windowed モードで実行している点と、 16:9の比率の解像度を選択してください。

Start game configuration
ゲームの設定を開始

ゲームが開始したら最初の Start Server と2つ目の Start Client をクリックしてください。 ゲームの2つのインスタンスが実行中である点と、2つのキューブがスポーンしている点を確認できます(ゲームの各インスタンスに対するものです)

Game running.
実行中のゲーム

Debug モードで実行した場合に Bolt がデフォルトで追加する Console と、小さなBolt Performanceディスプレイが最下部に表示されます。

次章 >>に続きます。

ドキュメントのトップへ戻る