PUN Classic (v1)、PUN 2、Boltはメンテナンスモードとなっております。Unity2022についてはPUN 2でサポートいたしますが、新機能が追加されることはありません。お客様のPUNプロジェクトおよびBoltプロジェクトが停止することはなく、将来にわたってパフォーマンス性能が落ちることはありません。 今後の新しいプロジェクトについては、Photon FusionまたはQuantumへ切り替えていただくようよろしくお願いいたします。

Bolt 106 - アニメーション

Boltはネットワーク上のMecanimアニメーションの複製をサポートしています。この章では、ネットワーク上で適切にアニメーションを動かす方法を詳細に見ていきましょう。

最初に、モデルとアニメーションが含まれているパッケージをダウンロードしてください。アセットストアからのUnityの'Stealth' サンプルから取得できます。または、アセットストアから'Stealth'パッケージをダウンロードし、そのキャラクターを自身でエクスポートするか、以下のパッケージをダウンロードすることもできます:

ここから先は上記のパッケージをダウンロードしたものとして進みます。パッケージをTutorialプロジェクトにインポートしてください。
新しいフォルダRobotを作成し、関連するすべてのファイルをドラッグします。

Setup example package
サンプルパッケージの設定

Tutorial/Robot/Done/DonePrefabs/char_robotGuardプレハブを見つけ、それをTutorial/Prefabs'のフォルダにドラッグしてRobotとリネームしてください。

Use the Robot Prefab
Robotプレハブを使用

Bolt Assetsのウィンドウを開いて新たな状態を作成し、RobotStateと名前をつけてください。状態の作成と名前の設定が完了したら、その状態のImport Mecanim Parameters設定を開きます。

Create new Robot State
新しいRobot Stateの作成

Robot のMecanimコントローラーをスロットにドラッグすると、Tutorial/Robot/DoneAnimations/DoneEnemyAnimatorに表示されるようになります。

Import Robot animator
Robotアニメーターをインポート

Importボタンをクリックします。

Click import Import to proceed
Importをクリックし、進む

BoltはMecanimコントローラー内の全てのパラメーターを、状態に自動的にインポートします。

Imported mecanim properties
インポートされたMecanimプロパティ

アニメーションコントローラーからパラメータをインポートした後、新たな設定(Mecanim (State Wide))が状態上に開きます。これにより、アニメーター値の変更にanimator.SetFloatやanimator.SetBoolといった通常のMecanimメソッドを用いるか、 Boltの状態プロパティを用いるかを選択できます。

Boltを、アニメーションコントローラーに関するパラメータ設定の一標準的なMecanimの方法を使用する既存のゲームに追加する場合には、デフォルトのUsing Animator Methods設定のままにしておくのが最適です。新たなゲームをBoltでビルドする場合には、この後行うとおりUsing Bolt Propertiesオプションを選択してください。

Change Animator Methods to Bolt Properties
AnimatorメソッドをBoltプロパティに変更

インポートで追加された全てのパラメーターが、Using Bolt Propertiesに変更されることを確認してください。また、Mecanimの値の減衰時間を制御する追加オプションが得られます。任意でBoltを Mixed Mode で稼働することもできます。このモードでは、いくつかのプロパティがUsing Animator Methodsに設定されており、またいくつかはUsing Bolt Propertiesに設定されています。発生する可能性のある混乱を防ぐため、これは用いないことを一般に推奨しています。

最後に、TransformプロパティをRobotStateに追加します。以前にCubeStateに対して行ったのと同じ要領です。

  1. 最上部の'New Property'をクリックします。
  2. 作成したプロパティの名前を'Transform'と設定します。
  3. プロパティのタイプを'Transform'と設定します。
  4. Smoothing Algorithm'を'Interpolation'に設定します。
Robot Transform Asset
RobotのTransform Asset

先に進む前に、Mecanimパラメータに関する設定も行っておきましょう。まず、ShotAimWeight パラメータに対するネットワーク複製を無効にしてください。これらはアニメーション内のカーブによりコントロールされ、ユーザーによる直接的な制御を受けないためです。これらのパラメータを例の中で実際に用いることはありませんが、これらを無効にしないと、Bolt がそれらを設定しようとする際にMecanimからエラーが発生します。

無効にするには2つの方法があります。最も簡単なのは、取り除いてしまうことです。もう1つは、Mecanim設定をUsing Animator Methodsに設定し、ReplicationLocalに設定することです。こうすることで、Boltは値をカーブから出力し、それをプロパティに放出しますが、ネットワーク上には何も送信しません。

Disable some Robot State properties
Robot Stateプロパティの無効化

設定が必要な2つ目のオプションは、SpeedAngularSpeedのプロパティのDamping Timeです。これをどちらも、0.1 に設定してください。

Change Damping Time
Damping Timeの変更

重要: ロボットキャラクターの状態について設定を完了したら、先に進む前にBoltをコンパイルするのを忘れないでください。

ここで、RobotプレハブをBolt Entityとして設定しましょう。Tutorial/Prefabsフォルダのプレハブを選択し、Bolt Entity のコンポーネントを追加してください。

Add Bolt Entity to Robot Prefab
Bolt EntityをRobotプレハブに追加

Bolt EntityコンポーネントのState設定をIRobotStateに変更し、Boltを再度コンパイルしてRobotプレハブを選択してください。

Set State and Compile Bolt
状態を設定し、Boltをコンパイル

ワールド内でロボットをスポーンする前に、 Boltに古いCubeのものではなく、新たなRobotプレハブのインスタンスを作成させる必要があります。NetworkCallbacks スクリプトでBoltNetwork.Instantiateコールを変更し、BoltPrefabs.Robotを参照してください。

C#

// ...

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.Robot, spawnPosition, Quaternion.identity);
}

// ...

ゲームを作成し2つのインスタンスを開始すると、以下のような画面を確認できます。また、Boltは続くエラーのレポートを送信します。このエラーは、Boltに対して用いたい'Animator'を適切に割り当てることができていないために起こります。

You have not assigned a mecanim animator to the state on Robot(Clone), but you have properties set to use mecanim.
First Gameplay with Robot Prefab
Robot Prefabでの最初のゲームプレイ

新たなC#スクリプトであるRobotBehaviourTutorial/Scriptsフォルダ内に作成し、CubeBehaviourのときと同様にデフォルトのUnityメソッドを削除し、クラスをBolt.EntityBehaviour<IRobotState>から継承してください。

C#

using System.Collections;
using UnityEngine;

public class RobotBehaviour : Bolt.EntityBehaviour<IRobotState>
{

}

Attached メソッドをオーバーライドし、 Transform プロパティを設定して Bolt が用いる状態にアニメーターを割り当てます。
変換は、CubeTransform プロパティに行ったように、state.SetTransforms(state.Transform, transform)に割り当てられます。アニメーターの割り当ては、state.SetAnimator の呼び出しと、プレハブからの既存のAnimator コンポーネントへの受け渡しによって行われます。

また、自身がオーナーの場合には'root motion'のみが用いられていることを確認してください。これは、自身がオーナーでない場合、それにより適用されるモーションが1つのエンティティを見ている全てのリモートピア上で重複するためです。entity.isOwnerstate.Animator.applyRootMotionプロパティに割り当ててください。

C#

using UnityEngine;
using System.Collections;

public class RobotBehaviour : Bolt.EntityBehaviour<IRobotState>
{
    public override void Attached()
    {
        state.SetTransforms(state.Transform, transform);
        state.SetAnimator(GetComponent<Animator>());

        state.Animator.applyRootMotion = entity.isOwner;
    }
}

また、作成したばかりのRobotBehaviour コンポーネントも、実際のRobot プレハブに割り当ててください。

Add Robot Behavior to Robot Prefab
Robot BehaviorをRobot Prefabに追加

この時点でゲームをビルドし開始すると、ロボットが立っている状態になりますが、警告は表示されません。最後に、ルートモーションを制御するためのコードを追加する必要があります。もう一度RobotBehaviourを開き、SimulateOwnerメソッドを実装してください。このメソッドにおけるコードは、最初は複雑に見えるかもしれませんが、実際には非常にシンプルです。

  1. Wが下のとき、スピードを加速させる(最大+1.5)
  2. Wが下になって いない とき、スピードを0まで減速させる
  3. Aが下になっているとき、角速度をマイナスにする(最大-1
  4. Dが下になっているとき、角速度をプラスにする(最大+1
  5. ADも下に なっていない とき、角速度を0に向けて移動する

C#

// ...

public override void SimulateOwner()
{
    var speed = state.Speed;
    var angularSpeed = state.AngularSpeed;

    if (Input.GetKey(KeyCode.W))
    {
        speed += 0.025f;
    }
    else
    {
        speed -= 0.025f;
    }

    if (Input.GetKey(KeyCode.A))
    {
        angularSpeed -= 0.025f;
    }
    else if (Input.GetKey(KeyCode.D))
    {
        angularSpeed += 0.025f;
    }
    else
    {
        if (angularSpeed < 0)
        {
            angularSpeed += 0.025f;
            angularSpeed = Mathf.Clamp(angularSpeed, -1f, 0);
        }
        else if (angularSpeed > 0)
        {
            angularSpeed -= 0.025f;
            angularSpeed = Mathf.Clamp(angularSpeed, 0, +1f);
        }
    }

    state.Speed = Mathf.Clamp(speed, 0f, 1.5f);
    state.AngularSpeed = Mathf.Clamp(angularSpeed, -1f, +1f);
}

// ...

メソッドの開始時に、state.Speedstate.AngularSpeedを読み込み、それらを2つのローカルの変数に保存します。その方が作業が簡単なためです。メソッドの終了時、それを状態に再度割り当ててspeed0.0 から 1.5fの間に、angularSpeed-1から+1の間に固定してください。

ゲームを再度ビルドすると、WADキーを使ってロボットのキャラクターと共に動き回ることができます。
以下に結果のデモを表示します。

Robot gameplay
Robotのゲームプレイ

以上で、「はじめに」チュートリアルが完了しました。次に、高度なチュートリアルに進み、Boltの強力な機能をさらに詳しく習得しましょう。

Back to top