• T, M T, M
  • — 5 months ago
Unity初心者がawsサーバーとWebSocketを使ってのリアルタイム同期通信について学ぶ①_下書き

◆まえがき

次の仕事まで少し時間が出来たので、空いた期間になにかしようという話になり・・・

「マルチプレイヤーオンライン(MO)ゲームでよくある複数ユーザーの同期処理をやってみたいんだけど勉強していい?」

・・・と会社に提案してみた所、有難くオッケーを頂いたので、UnityとAWSを使っての同期処理を勉強する事にしました。

なお、筆者はサーバーのエンジニアなので、Unityについてはほぼ初心者です。
そのためLvの高くないサンプルとなりますが、ご理解をお願いします。

なお、今回は同じ社内で手空きになっている3人(I.K、K.O、YH)に協力して頂いてます。 協力感謝です。

◆作りたい内容

作りたい内容を簡単に図にすると下記のようになります。

細かい話をすると、画面外へ移動できないようにしたいとか、スムーズに動かしたいとか、ユーザー登録したいとか、ROOMの選択したいとか色々ありますが、まずはこれを目標にします。

実装方法としては、クライアント部はUnity、サーバー部はAWS、通信はWebSocketを使用しての実装となります。
最終的には4人が同時にわちゃわちゃ動く所まで作ってみたいと思います。

◆クライアント部の作成(同期なし)

まずはクライアント部から作ります。

クライアント部の作成はUnityを使います。

Unityのバージョンは「2019.4.16f1」となります。

ここで作るPGは同期通信のないガワ部分だけとなります。
サーバー部や同期通信を行ったプログラムは後々の記述となります。

なお、サンプルはWindows上での動作確認までとなります。
Android端末やiOS端末に入れての動作確認は行っておりません。

①プロジェクト作成

Unityのインストール辺りは情報が沢山あるので割愛です。
とりあえず「Unity Hub」と「Unity」はインストールしている体でお願いいたします。

Unity Hub を起動、「新規作成」ボタンを押下しプロジェクトを作成します。

プロジェクト名は「websocket」です。
保存場所は任意で設定してください。

作成直後は、こんな感じです。



②プログラム格納用のディレクトリの作成

最初はProjectの「Assets」ディレクトリの下に「Scenes」ディレクトリしかないため、下記の3つのディレクトリを作成します。
(ProjectタブのAssetsの文字付近で右クリック>create>folderで作成できます)

・Plugins ・・・・・ WebSocket用のプラグインを配置するディレクトリ
・Resources・・・ リソースを配置するディレクトリ
・Scripts・・・・・・ スクリプトを配置するディレクトリ

ディレクトリを作成すると、こんな感じになります。



③使用するプラグインの配置

Websocketを使うためのプラグインと、通信で使用するJSONを読み込むためのプラグインを入手して配置します。

・WebSocket用のDLL「websocket-sharp.dll」を入手

下記のURLを参考に「websocket-sharp.dll」を入手
参考:https://qiita.com/oishihiroaki/items/bb2977c72052f5dd5bd9

作成した「websocket-sharp.dll」は②で作成した「Plugins」ディレクトリに配置してください。

・JSON用のDLL「Newtonsoft.Json.dll」を入手

下記URLより Newtonsoft.Json のDLLをダウンロード
https://github.com/JamesNK/Newtonsoft.Json/releases
※筆者がDLした時は「Json120r3.zip」をダウンロードしました。

DLしたファイルを解凍した後に「Bin/netstandard2.0」以下に「Newtonsoft.Json.dll」があるので、上記と同様に「Plugins」ディレクトリに配置してください。

プラグインを配置すると、こんな感じになります。



④シーンの作成

Assetsの「Scenes」ディレクトリにイメージ図の「タイトル画面」と「プレイ画面」にあたる下記の2つのシーンを作成します。
(ProjectタブのScenesの文字付近で右クリック>create>Sceneで作成できます)

・TitleScenes・・・タイトル画面
・PlayScene・・・・・プレイ画面

なお、最初からある不要な「SampleScene」は削除します。

シーンを作成すると、こんな感じになります。



⑤タイトル画面の作成(表示物)

作りたい内容のタイトル画面を作成していきます。

1.シーンの選択
タイトルが面のシーンを選択します。
(ProjectタブのAssets/Secenesを選択し、作成した「TitleScene」を選択)

2.画面の構成要素の作成
選択したシーンの「Hierarchy」に下記のように画面の構成要素を作成します。

・タイトル用のTextを作成
(Hierarchyタブで 右クリック > UI > Text で作成)
※同時にHierarchyに「Canvas」と「EventSystem」も作成されます。

作成された「Text」を選択し、画面右側のInspectorタブにプロパティが表示されるので下記を設定

・名前
    TxtTitle
・Rect Transform
    PosX:0、PosY:80、PosZ:0、Width:200、Height:100
・Text 
    Text:MO実験PG
・Character 
    Font Size:32に設定
・Paragraph 
    Alignment:上下中央、左右中央

設定すると、こんな感じです。



・ユーザー名用のTextを作成
(Hierarchyタブで 右クリック > UI > Text で作成(タイトルと同じ))

作成された「Text」を選択し、Inspectorを下記のように設定

・名前
    TxtUserName
・Rect Transform
    PosY:0、PosY:30、PosZ:0
・Text
    Text:ユーザー名
・Paragraph
    Alignment:上下中央、左右中央

・ユーザー名入力用のテキストボックスを作成
(Hierarchyタブで 右クリック > UI > Input Field で作成)

作成された「Input Field」のプロパティを下記のように設定

・名前
    pfUserName

・ログインと、アプリ終了用のボタンの二つを作成 (Hierarchyタブで 右クリック > UI > Button で作成)

作成された2つの「Button」を選択し、それぞれのInspectorを下記のように設定

ログインボタン
・名前
    BtnLogin
・Rect Transform
    PosY:0、PosY:-40、PosZ:0
・Text
    Text:ログイン
    ※HierarchyタブでBtnLoginを選択するとTextが紐づいているので、そこのTextを編集

アプリ終了ボタン
・名前
    BtnExit
・Rect Transform
    PosY:0、PosY:-80、PosZ:0
・Text
    Text:アプリ終了
    ※HierarchyタブでBtnExitを選択するとTextが紐づいているので、そこのTextを編集

上記を設定すると、こんな感じになります。



画面のGameタブを見て頂けると解りますが、それらしくタイトル画面が表示されています。
これにてタイトル画面の表示物作成は完成となります。

⑥タイトル画面の処理の作成

1.プレイ画面のシーンを選択します。
(ProjectタブのAssets/Secenesを選択、作成した「TitleScene」を選択)

2.タイトル画面で実行するスクリプトを作成
(ProjectタブのAssets/Scriptを選択、右クリック > create > C# script を実行 。名前は「TitleManager」で作成)

3.作成したスクリプトを実行する空オブジェクトの作成&アタッチ
Unityはシーン実行時に、シーン上のオブジェクトを読み込み、読み込んだオブジェクトにアタッチしているスクリプトを実行します。
そのため、作成したスクリプトを実行するためには、シーン上に一旦空のオブジェクトを配置し、そこに実行するスクリプトをアタッチします。

・空のオブジェクト(TitleManager)を作成
(Hierarchyタブを選択 >右クリック > Create Empty > Game Objectを実行。名前は「TitleManager」で作成)

・作成したTitleManagerを選択し、作成したTitleManagerをアタッチします。
(作成したTitleManagerを選択 >Inspectorの「Add Component」ボタン押下 > Scripts > TitleManager(追加したいファイル) を選択) ※慣れるとProjectタブから該当ファイルをドラッグ&ドロウして、Inspectorに放り込んでもOK

アタッチするとInspector上で指定したスクリプト(TitleManager)が表示されます。

無事 アタッチすると。こんな感じになります。



4.作成したスクリプトに実行プログラムを記述
作成したスクリプトファイルを開き、下記の実行プログラムを記述します。
(ProjectタブのAssets/Scriptを選択、作成した「TitleManager」をエディターで編集)

using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

public class TitleManager : MonoBehaviour
{
    // ユーザー名の入力テキスト
    public InputField IpfUserName;

    /// <summary>
    /// ログインボタン押下時の処理 
    /// </summary>
    public void OnClickLoginButton()
    {
        // 入力したユーザー名の取得 
        UserLoginData.userName = IpfUserName.text;

        // プレイ画面へ遷移
        SceneManager.LoadScene("PlayScene");
    }

    /// <summary>
    /// アプリ終了ボタン押下時の処理
    /// </summary>
    public void OnClickExitButton()
    {
        Application.Quit();
    }
}

処理の簡単な説明をすると下記のようになります。

・「OnClickLoginButton」
ログイン押下時に実行するメソッドです。
入力したユーザー名を取得し、プレイ画面へ遷移します。
※ここで使用している「UserLoginData」クラスは次の⑦で定義いたします。

・「OnClickExitButton」
アプリ終了ボタン押下時に実行するメソッドです。
単にアプリを落としているだけです。

5.作成したスクリプトをログインボタンとアプリ終了ボタンにアタッチ

上記で作成したメソッドを各種ボタン押下時に実行するように、各種ボタンアタッチします。

5-1.ログインボタンへのアタッチ

5-1-1.ログインボタンへのアタッチ 手順①
「Hierarchy」タブで「BtnLogin」を選択、ログインボタンのInspector内の「On Click」の「+」ボタンを押下、「On Click」に3つのテキストを表示させます。

5-1-2.ログインボタンへのアタッチ 手順②
オブジェクトを指定する部分(None(Object)と記載されているテキストボックス)に「Hierarchy」タブの「TitleManager」をドラッグ&ドロウしてアタッチします。

5-1-3.ログインボタンへのアタッチ 手順③
メソッドを指定する部分(No Functionと記載されているセレクトボックス)を選択 > TitleManager > OnClickLoginButton を選択

選択すると下記のようになります。



5-2.アプリ終了ボタンへのアタッチ
5-1と同様の方法で「Hierarchy」タブより「BtnExit」を選択して、「OnClickExitButton」メソッドをアタッチします。

⑦シーン間でデータをやりとりするクラスの作成

タイトル画面とプレイ画面とのシーン間でログインユーザ情報をやりとりするためのクラス「UserLoginData」を作成します。
(ProjectタブのAssets/Scriptを選択 >右クリック > create > C# script を実行 名前を「UserLoginData」で作成)

作成したスクリプトをエディターで開き、下記のようにコードを記載します。

public static class UserLoginData
{
    public static string userName;
}

上記を見れば解りますが、現状はやりとりする情報はユーザー名だけの定義となります。

⑧プレイ画面の作成(表示物)

プレイ画面のオブジェクトを作成していきます。

1.シーンの選択
プレイ画面のシーンを選択します。
(ProjectタブのAssets/Secenesを選択し、作成した「PlayScene」を選択)

2.床の作成
フィールドの床となるオブジェクトを作成します。
ここでは「Plane」オブジェクトで実装します。
(Hierarchyタブで 右クリック > 3D Object > Plane で作成)

作成された「Plane」を選択し、Inspectorを下記のように設定

・名前
    PlnYuka
・Transform
    Position 
        X:0、Y:-0.5、Z:0
    ScaleX
        X:1、Y:1、Z:1

3.カメラの調整
メインカメラの調整を行います。
(最初からHierarchyにある「Main Camera」を選択し、Inspectorを下記のように設定)

・Transform
    Position
        X:0、Y:7、Z:-7
    Rotation
        X:60、Y:0、Z:0
    ScaleX
        X:1、Y:1、Z:1

4.操作ボタンの作成
上下左右と退室ボタンを作成します。
(Hierarchyタブで 右クリック > UI > Button で作成)

作成された「Button」を選択し、それぞれInspectorを下記のように設定
TextはHierarchyタブで作成した「Button」を選択するとTextが紐づいているので、そこのTextを編集

上ボタン
・名前
    BtnUp
・Rect Transform
    PosY:0、PosY:-150、PosZ:0、Width:120、Height:50
・Text
    Text:↑

下ボタン
・名前
    BtnDown
・Rect Transform
    PosY:0、PosY:-200、PosZ:0、Width:120、Height:50
・Text
    Text:↓

左ボタン
・名前
    BtnDown
・Rect Transform
    PosY:-120、PosY:-175、PosZ:0、Width:120、Height:50
・Text
    Text:←

右ボタン
・名前
    BtnDown
・Rect Transform
    PosY:120、PosY:-175、PosZ:0、Width:120、Height:50
・Text
    Text:→

退室ボタン
・名前
    BtnDown
・Rect Transform
    PosY:120、PosY:-225、PosZ:0、Width:120、Height:50
・Text
    Text:退室

上記を設定すると画面的にはこんな感じになります。



画面のGameタブを見て頂けると解りますが、それらしくプレイ画面が表示されています。
これにてプレイ画面の表示物作成は完了となります。

⑨プレイヤーの作成

プレイヤーとなるオブジェクトを作成します。

1.プレイヤーの作成
プレイヤーとなるオブジェクトを作成します。 ここでは「Sphere」オブジェクトで実装します。 (Hierarchyタブで 右クリック > 3D Object > Sphere で作成)

作成された「Sphere」を選択し、Inspectorを下記のように設定

・名前
    SphPlayer
・Transform
    Position
        X:0、Y:0、Z: 0
    ScaleX
        X:1、Y:1、Z:1

2.ネームプレート作成
プレイやーの名前を表示するオブジェクトを作成します。

(Hierarchyタブで1.で作成した「SphPlayer」を選択、右クリック > 3D Object > 3D Text で作成)

作成された「New Text」を選択し、Inspectorを下記のように設定

・名前
    SphPlayer
・Transform
    Position
        X:0、 Y:1、Z: 0
    ScaleX
        X:1、 Y:1、 Z:1

・Text Mesh
    Text
        ユーザー名
    Character Size:0.2
    Anchor:Middle center
    Alignment:Center
    Color:黒(スポイトで黒を選択)

3.リソースへの登録

作ったプレイヤーオブジェクトをリソース化します。

(ProjectタブのAssets/Resourcesを選択し、HierarchyタブのSphPlayerを「Project」タブのAssets/Resourcesのディレクトリにドラッグ&ドロウ)

Assets/Resourcesのディレクトリに「SphPlayer」が無事リソース化されたら、不要になったSecene上にあるShpPlayerを削除します。
(Hierarchyタブで1.で作成した「SphPlayer」を選択し、右クリック > Remove)

作成したリソースを確認します。
(ProjectタブのAssets/Resourcesを選択、リソース化したSphPlayerを選択)

リソース化が出来ていればこんな感じなってます。



⑩プレイヤー画面の処理の作成

1.シーンの選択
プレイ画面のシーンを選択します。
(ProjectタブのAssets/Secenesを選択し、作成した「PlayScene」を選択)

2.スクリプトの作成
プレイヤー画面で実行するスクリプトを作成します。
(ProjectタブのAssets/Scriptを選択し、右クリック > create > C# script を実行 名前を「PlayManager」で作成)

3.スクリプトのアタッチ
作成したスクリプトを実行する空オブジェクト「PlayManager」を作成します。
(Hierarchyタブを選択し、右クリック > Create Empty で 「Game Object」が作成されるので名前を「PlayManager」に変更)

作成したオブジェクト「PlayManager」を選択し、スクリプト「PlayManager」をアタッチします。
(HierarchyタブのPlayManagerを選択し、Inspectorの「Add Component」ボタン押下 > Scripts > PlayManager(追加したいファイル) を選択)
※⑥の3.と同じ形です。

4.スクリプトに実行プログラムコードを記載
作成したスクリプト「PlayerManager」をエディターで下記のようにコードを記載します。

using UnityEngine;
using UnityEngine.SceneManagement;

public class PlayManager : MonoBehaviour
{
    private GameObject playerPrefab = null;     // プレイヤーのリソース(プレハブ)
    private GameObject player;                  // 自プレイヤー情報
    private const float KEY_MOVEMENT = 0.5f;    // 移動ボタン1回クリックでの移動量

    // Start is called before the first frame update
    void Start()
    {
        // 自プレイヤーの作成
        player = MakePlayer(Vector3.zero, UserLoginData.userName);
    }

    /// <summary>
    /// 上ボタン押下時の処理
    /// </summary>
    public void OnClickUpButton()
    {
        player.transform.Translate(0, 0, KEY_MOVEMENT);
    }

    /// <summary>
    /// 下ボタン押下時の処理
    /// </summary>
    public void OnClickDownButton()
    {
        player.transform.Translate(0, 0, -1 * KEY_MOVEMENT);
    }

    /// <summary>
    /// 左ボタン押下時の処理
    /// </summary>
    public void OnClickLeftButton()
    {
        player.transform.Translate(-1 * KEY_MOVEMENT, 0, 0);
    }

    /// <summary>
    /// 右ボタン押下時の処理
    /// </summary>
    public void OnClickRightButton()
    {
        player.transform.Translate(KEY_MOVEMENT, 0, 0);
    }

    /// <summary>
    /// 退室ボタン押下時の処理
    /// </summary>
    public void OnClickExitButton()
    {
        // タイトルシーンに戻る
        SceneManager.LoadScene("TitleScene");
    }

    /// <summary>
    /// プレイヤーを作成
    /// </summary>
    /// <param name="pos"></param>
    /// <param name="name"></param>
    private GameObject MakePlayer(Vector3 pos, string name)
    {
        // プレイヤーのリソース(プレハブ)を取得 ※初回のみ
        playerPrefab = playerPrefab ?? (GameObject)Resources.Load("SphPlayer");

        // プレイヤーを生成
        var player = (GameObject)Instantiate(playerPrefab, pos, Quaternion.identity);

        // プレイヤーのネームプレートの設定
        var otherNameText = player.transform.Find("TxtUserName").gameObject;
        otherNameText.GetComponent<TextMesh>().text = name;

        return player;
    }
}

処理の簡単な説明をすると下記のようになります

・「Start」
プレイ画面のシーン実行時に1度だけ実行されるメソッドです。
ここではログインしたプレイヤー(玉)を表示します。

・「OnClickUpButton」、「OnClickDownButton」、「OnClickLeftButton」、「OnClickRightButton」
画面の各方向キーを押した時にそれぞれ実行されるメソッドです。
自プレイヤーを指定方向キーに座標を移動させます。

・「OnClickExitButton」
退室ボタンを押下時に実行されるメソッドです。
タイトル画面へ遷移しています。

・「MakePlayer」
プレイヤー作成時に実行されるメソッドです。
プレイヤーとなるオブジェクト(⑨で作成したリソースのプレイヤープレハブ)の名前を設定し、画面上に作成、作成したオブジェクト情報を返却します。

5.スクリプトのアタッチ
作成したスクリプトのメソッドを、それぞれのボタン押下時に実行するように、各ボタンにアタッチします。

5-1.上「↑」ボタンへのアタッチします。
下記の手順で上ボタンへのアタッチします。

5-1-1.上ボタンへのアタッチ 手順①
Hierarchyタブで「BtnUp」を選択、上ボタンのInspector内の「On Click」の「+」ボタンを押下、「On Click」に3つのテキストを表示させます。

5-1-2.上ボタンへのアタッチ 手順②
オブジェクトを指定する部分(None(Object)と記載されているテキストボックス)に「Hierarchy」タブの「PlayManager」をドラッグ&ドロウしてアタッチします。

5-1-3.上ボタンへのアタッチ 手順③
メソッドを指定する部分(No Functionと記載されているセレクトボックス)を選択 > PlayManager > OnClickUpButton を選択
※基本的には⑥の5と同じような操作となります。

5-2. 下、左右、退室ボタンへのアタッチ
他のボタンも同様に下記のようにアタッチします。

5-2-1.下ボタンへのアタッチ
5-1と同様の方法で下ボタンに、「OnClickDownButton」メソッドをアタッチ

5-2-2.左ボタンへのアタッチ
5-1と同様の方法で左ボタンに、「OnClickLeftButton」メソッドをアタッチ

5-2-3.右ボタンへのアタッチ
5-1と同様の方法で右ボタンに、「OnClickRightButton」メソッドをアタッチ

5-2-4.退室ボタンへのアタッチ
5-1と同様の方法で退室ボタンに、「OnClickExitButton」メソッドをアタッチ

⑪ビルド設定

まだマルチ処理の同期はしていませんが、この状態で一旦動作チェックします。

この時点で、一通りの処理である、タイトル画面から、プレイ画面への遷移、プレイ画面での自プレイヤーの表示、操作までできるようになります。
また退出、アプリ終了の画面遷移もできるようになります。

1.シーンの選択
プレイ画面のシーンを選択します。
(ProjectタブのAssets/Secenesを選択し、作成した「TitleScene」を選択)

2.ビルドの設定 その①
ビルドするシーンを設定します。
内容は実行する2つのシーン「タイトル画面」と「プレイ画面」を設定します。
(メニューのFile > Build Settings を選択し、設定画面の上部の「Scenes In Build」に実行する二つのシーン「TitleScnene」、「PlayScene」を設定します。設定画面が表示されたら、ProjectタブのAssets/Scenesを選択し、「TitleScnene」と「PlayScene」をそれぞれ「Scenes In Build」の部分にドラッグ&ドロウします)
※注意としては、リストの上から順にビルドするようなので、上に「TitleScnene」、下に「PlayScene」を入れる形にしてください。

設定するとこんな感じです。



3.ビルドの設定 その②
ビルドのPlayer Settingの設定を行います。
内容は実行時の表示画面の大きさを設定します。
(ビルド設定画面の「Player Settings…」ボタンを押下し、下記のの項目を編集)

Fullscreen Mode
    Windowed
Default Screen Width
    700
Default Screen Height
    500

設定するとこんな感じです。



設定が終えたら設定画面を閉じてください。

4.ビルド&実行
画面上部の再生「▶」ボタンを押下します。

ビルドされ、実行されるので、「Game」タブ上で操作して動作に異常がないか確認します。

下図のように、ログインしたユーザー名のプレイヤーが操作できます。

ここまで出来れば次はサーバーの構築に入ります。

次回:Unity初心者がawsサーバーとWebSocketを使ってのリアルタイム同期通信について学ぶ②
https://www.aska-ltd.jp/jp/blog/102

T, M

System engineer

Unity初心者がawsサーバーとWebSocketを使ってのリアルタイム同期通信について学ぶ①_下書き

お気軽に
お問い合わせください。

お問い合わせ