City サンプルで使われている群衆制御フレームワーク(Mass Framework) の知見を共有したいと思います。
情報量が膨大なので記事を分割し、本稿では Mass Framework のセットアップや簡単なサンプルの作成方法のみを扱います。
動作環境
Unreal Engine 5.4 / 5.5 / 5.6
Visual Studio 2022
※MSVC v143 – VS 2022 C++ x64/x86 ビルドツール v14.38-17.8
Windows 11 Home
本稿で扱う内容
- 前置き
- Mass Framework は Epic が主張するほど軽いのか?
- Mass Framework は何の問題を解決するのか?
- Mass Framework でアクターを表示するまでの作業の流れ
読みたい方だけ以下のスポイラーを展開してご確認ください。
目安としては、エンジンコードを読み解き、目的に合わせて改造できるレベルです。
Mass Framework 自体は高速です。消費するメモリは固定で、わずかです(調節できます)。
ただし、これは画面に表示するアクターを考慮していません。
パフォーマンス上、問題になるのは Mass Framework を使って表示するアクターの方です。
Mass Framework は UE が持つキャラクター制御の仕組みを使うことを想定しています。
とは言え、この仕組みでパフォーマンスを損なうことなくカメラ内に表示できるのは、せいぜい10体程度です。
これは Mass Framework の問題ではありません。
これはアクターの最適化問題です。
Mass Framework は大量のパラメータを固定の消費メモリで高速に計算するためのフレームワークです。
群衆制御システムと言われていますが、それは表面的なものです。
Mass Framework の用途としては、以下が考えられます。
1. City サンプルみたいなことをやりたい。
2. オブジェクトやアクター単位で処理したいわけではなく、全てのアクターが持っているトランスフォームや物理パラメータだけをまとめて高速に処理したい。
まず、敷設したレーンに沿って歩き回れるようにします。
プラグインを有効化
↓
Unreal Engine を再起動
↓
Mass 用キャラクター作成
↓
State Tree 作成
↓
Mass Entity Config 作成
↓
ZoneShape でレーンを作成
↓
Mass Spawner 設置
ここまでで必要最小限の動きができるので、これに機能を追加して行きます。
回避行動
衝突を避けるように移動する。
以下のプラグインを有効にして、UE エディタを再起動します。
- MassAI
- MassCrowd
- MassEntity
5.5 以降は不要です。
*Build.cs にモジュールを追加すれば使えます。 - MassGameplay
- ZoneGraph
- ZoneGraph Annotations
1. 以下のコードをプロジェクトに追加する。
// MassCharacter.h #pragma once #include "Components/CapsuleComponent.h" #include "GameFramework/Character.h" #include "GameFramework/CharacterMovementComponent.h" #include "MassCharacter.generated.h" UCLASS() class AMassCharacter : public ACharacter { GENERATED_BODY() public: AMassCharacter() { GetCapsuleComponent()->InitCapsuleSize(42.f, 96.0f); bUseControllerRotationPitch = false; bUseControllerRotationYaw = false; bUseControllerRotationRoll = false; GetCharacterMovement()->bOrientRotationToMovement = true; GetCharacterMovement()->RotationRate = FRotator(0.0f, 500.0f, 0.0f); GetCharacterMovement()->JumpZVelocity = 700.f; GetCharacterMovement()->AirControl = 0.35f; GetCharacterMovement()->MaxWalkSpeed = 500.f; GetCharacterMovement()->MinAnalogWalkSpeed = 20.f; GetCharacterMovement()->BrakingDecelerationWalking = 2000.f; GetCharacterMovement()->BrakingDecelerationFalling = 1500.0f; } };
2. BP_ThirdPersonCharacter を複製する。
3. 2 の親クラスを 1 に変更する。
4. ABP_Manny を複製する。
5. 4 を 2 に割り当てる。
6. 2 に MassAgent コンポーネントを追加する。
7. 6 の「詳細」で以下の設定を追加する。

Agent Feet Location Sync(エージェントの足の位置同期) ⇒ Actor to Mass
Agent Movement Sync(エージェント移動同期) ⇒ Mass to Actor
8. 2 の CharacterMovement コンポーネントを選択し、詳細 > キャラクタ移動(回転設定) の Orient Rotation to Movement にチェックを入れる。
下記の画像通りに作成します。
※タップまたはクリックすると大きいサイズで表示します。
画像内のステートツリーは、Mass用キャラクターを移動させるのに最低限必要な設定です。
下記の画像通りに作成します。
- StateTree に前項で作成したステートツリーを指定します。
- 群衆ビジュアライゼーションを下記の画像通りに設定します。
※タップまたはクリックすると大きいサイズで表示します。
- 「Validate Entity Config」ボタンを押して、問題がないことを確認します。
※ボタンは一番上にあります。
Mass用キャラクターが移動するレーンをゾーン形状(ZoneShape)で作成します。
作業に取り掛かる前に、レーンの編集に必要な設定を行い、作業しやすいよう、いくつかの設定を変更します。
- プロジェクト設定 > エンジン – Zone Graph を下記画像の通りに設定する。
最低限、Mass用キャラクターが移動するレーンの設定(赤枠で囲った箇所)を追加しないと、レーンを作成できません。「編集中に Zone Graph を作成」をチェックすることで、ゾーン形状(ZoneShape) を編集する度にビルドする手間を省けます。 - レベルビューポート > 表示 > デベロッパー > Zone Graph をチェックする。
※タップまたはクリックすると大きいサイズで表示します。
この設定を行わないとレベルエディタでゾーン形状が見えないので、編集時はチェックする必要があります。
チェックしても正しく表示されない場合もあるので、そのときは、レベルをロードし直すと改善することがあります。
※以前のバージョンでは、手動で追加する必要がありました。
操作が分かりにくいので、詳しく順を追って説明します。
真ん中の白い線を左クリックするとオレンジ色になります。
この状態にすることで、ゾーン形状を変形させることができます。
とりあえず、横長にしたいのでゾーン形状の両端についている白い四角を移動して、横長になるよう調節します。
だいたい、こんな感じ。
レーンを環状に変形させるため、レーンの両端に制御点を追加して、┏┓ ←このような形に変形させます。
真ん中の白い線を「右クリック」してポップアップメニューから「ここに点を追加」を選択します。
最低でも新しく2つの点を追加する必要があります。
点を2つ追加しました。
両端の点を動かせば、追加した点の位置で折れ曲がります。
両端の点を動かすと、こんな感じになります。
ゾーン形状を追加し、┗┛ ←このような形に変形させ、2つのゾーン形状を接続します。
下のゾーン形状を接続可能な形状に変形しました。
まだ2つのゾーン形状は接続していません。
他のゾーン形状と接続できる点を選択すると、レベルビューポートの上部に黄色いテキストで操作説明が表示されます。
Cキーを押しながら点を移動し、接続先の点の近くへ移動します。
このとき、接続先の点が緑色で強調表示されます。
この状態でマウスボタンを離すと、強調表示された点にスナップして接続されます。
片側が接続されました。
もう片方も同様の操作を行い接続します。
2つのゾーン形状を接続しました。
アウトライナーで2つのゾーン形状を選択し、「詳細」のレーンプロファイルとタグの設定を変更します。
レーンプロファイルとタグは、プロジェクト設定 > エンジン – Zone Graph で追加したものを指定します。
Mass用キャラクターがレーンをグルグル周回するように移動させるには、最低でも2つのゾーン形状を組み合わせる必要があります。
ゾーン形状ひとつでは周回してくれません。
理由は分かりませんが、そういう仕組みのようです。
ゾーン形状がひとつしかない場合、Mass用キャラクターがレーンの終端まで移動すると、そこで折り返し、レーンの対向車線を移動します。
レーンの両端が接続していても、終端で折り返してしまいます。
例えば、↑の画像のようなゾーン形状ひとつを環状に繋げた場合、以下のような挙動になります。
レーン (ゾーン形状) に指定するタグを変更したときに、この問題と遭遇して悩むことがあります。
レーンを周回するかどうかは、ステートツリーの設定が影響しています。
レーンが途中で途切れていたり、ひとつのレーンを環状に繋げても周回してくれません。
ステートツリー側の設定方法は、State Tree 作成 をご確認ください。
ステートツリーに追加したタスクの「ZG 徘徊ターゲットの検索」>「許可されている注釈タグ」(以後、ステートツリー側のタグと表記します)が周回するかどうかに影響します。
周回させるには、以下のどちらかの設定を行う必要があります。
1. タグをひとつも指定しない(上記画像の通り)。
2. レーン側のタグと一致させる。
全てのレーンにおいて周回して欲しいなら、1 の設定を行うのが楽です。
あるレーンでは周回させたいけど、別のレーンでは周回して欲しくない場合は、2 の設定を行います。
↑の画像はゾーン形状(レーン)側のタグ設定です。レーンには複数のタグを指定できます。
レーン側のタグは以下の二か所の設定が評価の対象になります。
1. ゾーン形状 > 詳細 > ゾーン > レーンプロファイル
2. ゾーン形状 > 詳細 > ゾーン > タグ
2 を指定しない場合、1 とステートツリー側のタグで評価が行われます。
ステートツリー側のタグと、レーン側のタグとで評価を行い、両者の条件が一致する場合に周回します。
ステートツリー側のタグが未指定の場合は、レーン側のタグがどのような設定であっても一致します。
この場合、レーンのタグかレーンプロファイルに「Test」が指定されていて、「Default」が指定されて「いない」場合に周回します。
Mass Framework 用キャラクターをスポーンするには、Mass Spawner を使います。
「Massスポナー」をレベル内に設置します。
※タップまたはクリックすると大きいサイズで表示します。
レベルに配置した「Massスポナー」の「詳細」を、下記の画像のように設定します。
個数 | スポーンする Mass Framework 用キャラクターの個体数を入力します。 最適化していないキャラクターはとてつもなく重いので、最初は5体くらいから始めるのが良いです。 |
エンティティコンフィグ(MEC) | 「Mass Entity Config 作成」で作った Mass Framework 用データアセットを指定します。 |
エンティティコンフィグ > 比率 | MEC は複数指定することができます。 その際、どの MEC をどれくらいの比率でスポーンするか?を指定します。 [0] 1.0 / [1] 2.0 を指定した場合、[1] の方が2倍スポーンするようになります。 |
ジェネレータインスタンス | Mass Framework 用キャラクターをスポーンする場合は、「ZoneGraph スポーンポイントジェネレータ」だけ動作します。 |
タグフィルタ | どのレーンにスポーンするかを指定します。 任意のタグに複数のタグを指定した場合、OR で判定されます。 すべてのタグは AND で、非タグに指定したレーンには絶対にスポーンしません。 非タグを指定しない場合、スポーンしないはずのレーンにスポーンすることがあります。 |
最小ギャップ 最大ギャップ |
ややこしいので後述します。 |
ランダム選択シード | スポーン位置を決める乱数のシードを指定します。 毎回同じ位置にスポーンしたい場合に指定します。 |
ジェネレータインスタンス > 比率 | ジェネレータインスタンスを複数指定した場合、どのジェネレータをどれくらい使うか?を指定します。 |
プレイ開始時に自動スポーン | プレイ開始後、任意のタイミングでスポーンさせたい場合はチェックを外します。 チェックするとスポナーの BeginPlay でスポーンします。 |
スポーニングカウントスケール | この値を乗算した個数をスポーンするようになります。 2.0 を指定した場合、2倍スポーンします。 この値は常に 1.0 にしておくのがお勧めです。 使うとしても、スポーン数の調整中に倍率で個数を変えたいような状況で一時的に使い、個数が決まったら 1.0 に戻すという使い方が良いです。 この項目は下の方にあるので気づきにくく、一番上にある「個数」だけ見れば分かるようにしておく方が間違いが減りますし、調整する項目が減るので楽です。 |
設計図をオーバーライド | 日本語訳が間違っていて、説明の中にある「構成図(Schematics)」のことです。 使い道は不明です。 |
Annotation / Avoidance / 回避行動 / 衝突回避 の必要性については、↓を見ていただければ一発で分かると思います。
他の Mass 用キャラクターが目詰まりを起こしていても、そのまま直進しようとしますが、直進できるスペースがないため、その場で止まってしまいます。
これを起きにくくさせるために回避行動が必要になります。
起きにくくなるだけで、限度はあります。
MassEntityConfig に「特性」をふたつ追加します(上図の赤枠内)。
- 回避(Avoidance)
- ナビゲーションオブスタクル(Navigation Obstacle)
衝突を避けるように移動しているのが分かると思います。