【UE5.6】Mass Framework で大量の NPC を制御する。導入編【C++】

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 Traffic で車両を制御する
  • ステートツリーで歩行と待機を切り替える
  • スマートオブジェクトを使う
  • 任意のオブジェクトを障害物にする
  • 歩行速度を調節する
  • テンプレート切り替え時にモーションが繋がるようにする
  • NavMesh で移動させる(要5.6)
  • タグの使い方
  • Mass Framework で制御しない NPC との連携
  • Mass Framework のプロジェクト設定
  • Mass Framework のプロセッサーを置き換える
  • Mass Framework の設計
  • Mass Crowd のチューニング(最適化)
  • Mass Traffic のプロジェクト設定
  • Mass Traffic のチューニング(最適化)

前置き

読みたい方だけ以下のスポイラーを展開してご確認ください。

Mass Framework を扱う上での注意点
Mass Framework は現在 β よりも前の体験版(Experimental)の段階にある機能です。
多数のバグを抱えている可能性があり(実際かなりバグがあります)、機能も分かりにくく、ドキュメントもほとんどありません。
お手本になるものは City サンプルやネット上のいくつかの短い記事と英語のチュートリアル動画しかなく、それらにない機能は自力で実装する必要があります。
バグに遭遇した場合も、自力で Mass Framework 用プラグインのコードを修正するか、プラグイン側にあるコードを自前のプロジェクトにコピーして置き換える必要があります。
エンジンのマイナーバージョンが更新されると、これまで動作していたものが動作しなくなることがあります。
Mass Framework でスポーンしたアクターを制御するステートツリーにエバリュエーターやタスクを追加する場合、C++ で作る必要があるため、エンジニア以外が扱うのは、かなりハードルが高いです。
参考資料、信頼性・安定性、機能の充実度、扱いやすさ、いずれも不十分ですので、Mass Framework を商業ベースで使うのは時期尚早です。
商業ベースに乗せるには年単位の研究が必要です。
本稿は問題が起きたときに自力で解決できるエンジニアが対象です。
目安としては、エンジンコードを読み解き、目的に合わせて改造できるレベルです。

Mass Framework だけでも膨大な情報量になるので、コードで分からないことがあれば、その都度、AI に聞くか、Google Gemini などの Deep Research を活用することをお勧めします。

Mass Framework は Epic が主張するほど軽いのか?

Mass Framework 自体は高速です。消費するメモリは固定で、わずかです(調節できます)。
ただし、これは画面に表示するアクターを考慮していません。
パフォーマンス上、問題になるのは Mass Framework を使って表示するアクターの方です。

Mass Framework は UE が持つキャラクター制御の仕組みを使うことを想定しています。
とは言え、この仕組みでパフォーマンスを損なうことなくカメラ内に表示できるのは、せいぜい10体程度です。
これは Mass Framework の問題ではありません。
これはアクターの最適化問題です。

より詳しい説明
従って、画面にアクターを何百体、何千体も表示したいような場合、以下の最適化技術が必要です。

達成すべきこと
  • 画面にアクターを数百体~数千体表示する。
達成するべきことの条件として考えられるもの
  • マルチプラットフォーム対応
     ※PS5 や Xbox Series S などのゲーム機で動作する(まだマシ)。
     ※Switch で動作する(非常に難しい)。
  • 8K または 4K 解像度、最低でもフル HD
     ※8K や 4K 対応するなら TSR 必須。
  • FPS 60 か 30
     ※8K はハイエンド GPU でも FPS 60 は無理。
     ※現行のゲーム機ではフル HD でも無理。
  • VRAM を含めて 8GB 程度のメモリ消費
     ※レベル内に表示する全てのデータを含む。
     ※非同期ロードで一時的に使うキャッシュも含む(見落としがち)。

※他にも、TSR を使うか、VSM を使うか、Lumen を使うか、Nanite を使うか、レイトレースを使うかなどによって条件が増えます。
※それぞれに合った最適化方法があるので、非常に手間がかかる。

この技術がないなら、Mass Framework を使っても何の解決にもならないです。
色んな人と話をしましたが、ここを勘違いしている人が多いというか、
一人の例外もなく勘違いしています。

Mass Framework は何の問題を解決するのか?

Mass Framework は大量のパラメータを固定の消費メモリで高速に計算するためのフレームワークです。
群衆制御システムと言われていますが、それは表面的なものです。

Mass Framework の用途としては、以下が考えられます。

1. City サンプルみたいなことをやりたい。
2. オブジェクトやアクター単位で処理したいわけではなく、全てのアクターが持っているトランスフォームや物理パラメータだけをまとめて高速に処理したい。

より詳しい説明
何故、高速に処理できるのか?

連続したアドレスのメモリ空間を確保するので、同じ種類 (Transform など) の大量のパラメータを高速に処理できます。
コンピューターのメモリは物理的なチップの中に並んでいますが、全てのアドレスを同じ時間でアクセスできるわけではありません。
コンピューターにとっては1ミリメートルでも広大な距離なので、CPU から離れた位置にあるアドレスにアクセスすると、近い位置にあるアドレスと比べて遅くなります。
そのため、まとめて処理したいデータを連続して並んでいるアドレスに確保することで、メモリへのアクセスが高速になります。
Mass Framework は、このアクセス時間のロスが起きにくいデータ駆動設計 (DDD) で作られているので、同じ種類の大量のパラメータをまとめて処理するのに適しています。

Mass Framework はどのタイミングで処理されるのか?

物理処理の前、後、フレームの最後…など、特定のタイミングで処理することができます。

Mass Framework はマルチスレッドに対応しているか?

物理パラメータにアクセスしないなら、GameThread 以外の別スレッドで実行させることができます。
例えば、Chaos の制御は GameThread で行う必要があるので、Chaos にアクセスするなら GameThread 以外で処理することはできません。
どうしてもやりたいなら、少し面倒な仕組みが必要になります。
そういった制限がないなら、プロセッサーのパラメータひとつを変更するだけで、GameThread 以外で処理させることができます。

City Sample にもこっそり入っていますが、収穫できる植物が育つまでのタイマー計算は Mass Framework に向いていると思います。細かくゾーニングしているワールドなら、現在のゾーンだけ処理すれば良いですが、オープンワールドだと管理する収穫物の数も膨大になります。
他にもやれそうなことは沢山ありますが、例えば、NPC の自立行動のスケジュール管理処理(朝起きて何をする、何時にどこへ行くなど)をさせたり、もし簡単な大気シミュレーションを内部で行っているなら、その計算をさせても良いと思います。
とは言え、なんでもかんでも Mass Framework でやれば良いということにはならないです。
細かくチューニングしないと Mass Framework がボトルネックになってしまいます。

アクターの負荷軽減については、オクトツリーによる高速カリング、LOD によるアクターの切り替えと、LOD によって Tick 呼び出し頻度を調節する機能があります。

LOD によるアクターの切り替えは、以下の 4 種類に対応しています。

1. CharacterMovementComponent を使った高度な物理制御用アクターを表示。
2. CharacterMovement を使わない単純な物理制御用アクターを表示。
3. アクターを使わず StaticMesh のみ表示。
4. 表示もしないし制御もしない。

Mass Framework でアクターを表示するまでの作業の流れ

まず、敷設したレーンに沿って歩き回れるようにします。

プラグインを有効化

Unreal Engine を再起動

Mass 用キャラクター作成

State Tree 作成

Mass Entity Config 作成

ZoneShape でレーンを作成

Mass Spawner 設置

ここまでで必要最小限の動きができるので、これに機能を追加して行きます。

車の制御をしないなら、City サンプルは不要です。
追加機能のサンプル

回避行動
衝突を避けるように移動する。

プラグインを有効化

以下のプラグインを有効にして、UE エディタを再起動します。

  • MassAI
  • MassCrowd
  • MassEntity
    5.5 以降は不要です。
    *Build.cs にモジュールを追加すれば使えます。
  • MassGameplay
  • ZoneGraph
  • ZoneGraph Annotations
車を制御しないなら Traffic プラグインは不要です。

Mass 用キャラクター作成

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 Framework が管理している MassEntiry の位置は別物です。

まず、Agent Movement Sync(エージェント移動同期) を Mass to Actor に設定することで、Mass Framework で計算した位置に、キャラクターが移動するようになります。
この設定がないと、キャラクターは移動しません。
Both Ways でも動作しますが、二重に同期を取るのでブルブル震えながら移動するようになり、動作が不自然になります。

キャラクターは CharacterMovement の Velocity によって移動するため、Mass Framework 側で想定している移動先と、実際にキャラクターが移動した位置にズれが生じることがあります。
また、キャラクター同士の衝突によって位置ズれが起きます。
そのため、Agent Feet Location Sync(エージェントの足の位置同期) を Actor to Mass に設定することで、キャラクターの移動した位置が Mass Framework に反映されるようになり、位置ズレが修正されます。
この設定がなくてもキャラクターは移動しますが、キャラクター同士の衝突などによって位置がズれても、そのズれた位置が Mass Framework 側に反映されなくなります。
本来ならその位置ズれによってキャラクター同士の進行方向に隙間ができて、その隙間を通れるようになる場合があるのですが、Mass Framework 側にズれた位置情報が伝わらなくなると、衝突した位置でキャラクター同士が進行を妨害し合い、目詰まりを起こしやすくなります。
回避行動を追加することで、かなり緩和できますが、この設定とセットで対応するのがお勧めです。

State Tree 作成

下記の画像通りに作成します。
※タップまたはクリックすると大きいサイズで表示します。

画像内のステートツリーは、Mass用キャラクターを移動させるのに最低限必要な設定です。

Mass Entity Config 作成

下記の画像通りに作成します。

  • StateTree に前項で作成したステートツリーを指定します。
  • 群衆ビジュアライゼーションを下記の画像通りに設定します。
    ※タップまたはクリックすると大きいサイズで表示します。

    群衆ビジュアライゼーションの LOD 設定について
    群衆ビジュアライゼーションでは、カメラからの距離によって、以下の切り替えができます。

    • 高解像度キャラクター
    • 低解像度キャラクター
    • スタティックメッシュ

    高解像度用キャラクターと低解像度キャラクターには、ACharacter を継承した C++ のクラスか、キャラクターを親クラスに設定したブループリントを指定します。
    ※親は APawn でも構いませんが、移動用のフラグメントを使う場合、UCharactorMovementCompornent が必要になります。

    対応している LOD は以下の4種類あります。

    • High
    • Medium
    • Low
    • Off

    どの距離がどの LOD に対応するかは、群衆ビジュアライゼーション > LODParams > ベースLOD距離(Base LODDistance) と 表示LOD距離(Visible LODDistance) で設定できます。
    どの LOD のときに何体のキャラクターを表示するかは、LOD最大数(LODMax Count) で設定できます。

    4 種類の LOD 設定で足りない場合は C++ で新しいビジュアライゼーションクラスを作成して、群衆ビジュアライゼーションと置き換える必要があります。
    ただし、4 種類の LOD 設定をあっちこっちで参照しているので、かなり手間がかかります。
  • 「Validate Entity Config」ボタンを押して、問題がないことを確認します。
    ※ボタンは一番上にあります。

ゾーン形状(ZoneShape) でレーンを作成

Mass用キャラクターが移動するレーンをゾーン形状(ZoneShape)で作成します。
作業に取り掛かる前に、レーンの編集に必要な設定を行い、作業しやすいよう、いくつかの設定を変更します。

  1. プロジェクト設定 > エンジン – Zone Graph を下記画像の通りに設定する。

    最低限、Mass用キャラクターが移動するレーンの設定(赤枠で囲った箇所)を追加しないと、レーンを作成できません。

    「編集中に Zone Graph を作成」をチェックすることで、ゾーン形状(ZoneShape) を編集する度にビルドする手間を省けます。
  2. レベルビューポート > 表示 > デベロッパー > Zone Graph をチェックする。
    ※タップまたはクリックすると大きいサイズで表示します。

    この設定を行わないとレベルエディタでゾーン形状が見えないので、編集時はチェックする必要があります。
    チェックしても正しく表示されない場合もあるので、そのときは、レベルをロードし直すと改善することがあります。

アクタを配置からゾーン形状を床にドラッグ&ドロップ

※タップまたはクリックすると大きいサイズで表示します。

エディタの言語が日本語の場合、「アクタを配置」で検索しないと出てきません。
アウトライナーに Zone Graph Data がない場合、ゾーン形状をレベルに追加することで、自動的に Zone Graph Data も追加されます。
※以前のバージョンでは、手動で追加する必要がありました。
ゾーン形状を編集

操作が分かりにくいので、詳しく順を追って説明します。


真ん中の白い線を左クリックするとオレンジ色になります。
この状態にすることで、ゾーン形状を変形させることができます。


とりあえず、横長にしたいのでゾーン形状の両端についている白い四角を移動して、横長になるよう調節します。


だいたい、こんな感じ。

あまり壁に寄せてしまうと、Mass用キャラクターを大量にスポーンしたときに壁際で目詰まりを起こして大渋滞が起きます。


レーンを環状に変形させるため、レーンの両端に制御点を追加して、┏┓ ←このような形に変形させます。
真ん中の白い線を「右クリック」してポップアップメニューから「ここに点を追加」を選択します。
最低でも新しく2つの点を追加する必要があります。


点を2つ追加しました。
両端の点を動かせば、追加した点の位置で折れ曲がります。


両端の点を動かすと、こんな感じになります。


ゾーン形状を追加し、┗┛ ←このような形に変形させ、2つのゾーン形状を接続します。


下のゾーン形状を接続可能な形状に変形しました。
まだ2つのゾーン形状は接続していません。

※タップまたはクリックすると大きいサイズで表示します。

他のゾーン形状と接続できる点を選択すると、レベルビューポートの上部に黄色いテキストで操作説明が表示されます。
Cキーを押しながら点を移動し、接続先の点の近くへ移動します。
このとき、接続先の点が緑色で強調表示されます。
この状態でマウスボタンを離すと、強調表示された点にスナップして接続されます。


片側が接続されました。
もう片方も同様の操作を行い接続します。


2つのゾーン形状を接続しました。


アウトライナーで2つのゾーン形状を選択し、「詳細」のレーンプロファイルとタグの設定を変更します。
レーンプロファイルとタグは、プロジェクト設定 > エンジン – Zone Graph で追加したものを指定します。

レーンをグルグル周回させるのに最低限必要なゾーン形状

Mass用キャラクターがレーンをグルグル周回するように移動させるには、最低でも2つのゾーン形状を組み合わせる必要があります。
ゾーン形状ひとつでは周回してくれません。
理由は分かりませんが、そういう仕組みのようです。

ゾーン形状がひとつしかない場合、Mass用キャラクターがレーンの終端まで移動すると、そこで折り返し、レーンの対向車線を移動します。
レーンの両端が接続していても、終端で折り返してしまいます。

※タップまたはクリックすると大きいサイズで表示します。

例えば、↑の画像のようなゾーン形状ひとつを環状に繋げた場合、以下のような挙動になります。

レーンの繋ぎ目で止まってしまう場合の対処法


レーン (ゾーン形状) に指定するタグを変更したときに、この問題と遭遇して悩むことがあります。
レーンを周回するかどうかは、ステートツリーの設定が影響しています。

既に書きましたが、まず大前提として、ふたつ以上のレーンを繋げて周回可能な経路を作る必要があります。
レーンが途中で途切れていたり、ひとつのレーンを環状に繋げても周回してくれません。
ステートツリー側の設定

ステートツリー側の設定方法は、State Tree 作成 をご確認ください。


ステートツリーに追加したタスクの「ZG 徘徊ターゲットの検索」>「許可されている注釈タグ」(以後、ステートツリー側のタグと表記します)が周回するかどうかに影響します。
周回させるには、以下のどちらかの設定を行う必要があります。

1. タグをひとつも指定しない(上記画像の通り)。
2. レーン側のタグと一致させる。

全てのレーンにおいて周回して欲しいなら、1 の設定を行うのが楽です。
あるレーンでは周回させたいけど、別のレーンでは周回して欲しくない場合は、2 の設定を行います。

レーン側の設定


↑の画像はゾーン形状(レーン)側のタグ設定です。レーンには複数のタグを指定できます。

レーン側のタグは以下の二か所の設定が評価の対象になります。

1. ゾーン形状 > 詳細 > ゾーン > レーンプロファイル
2. ゾーン形状 > 詳細 > ゾーン > タグ

2 を指定しない場合、1 とステートツリー側のタグで評価が行われます。
ステートツリー側のタグと、レーン側のタグとで評価を行い、両者の条件が一致する場合に周回します。
ステートツリー側のタグが未指定の場合は、レーン側のタグがどのような設定であっても一致します。

何故タグを未指定の場合でも一致するのか?
タグの評価を FZoneGraphTagFilter::Pass() で行っていて、この関数の処理がそうなっているためです。
関数の説明がコメントで記載されていますが、コメントから推察すると意図した挙動(仕様)だということが分かります。

以下はコメントの日本語訳です。

AnyTags、AllTags、NotTags のいずれかが存在する場合、フィルタは通過します。
include または exclude タグを None に設定すると、そのチェックはスキップされます。

原文の時点で既に分かりにくいので、日本語に翻訳しても分かりにくいですが、コメントに記載されている「フィルタは通過します」と「チェックはスキップされます」はどちらも同じ結果 true を返します。
フィルタを通過しない、かつ、チェックもスキップされない場合、false を返します。
include は恐らく、メンバ変数の AnyTags, AllTags, NotTags のことで、exclude タグは引数に指定する Tags のことです。

タグを未設定の場合は None になるので、チェックはスキップされ true が返されます。

「何で None の時はチェックをスキップするのか?」は分かりません。
コードを見てもその理由を読み取ることができないので、それをコメントに書くべきです。
わざわざコメントに書いていることはコードを見れば分かることです。
コードが長くて複雑な場合、それをコメントで補足説明するのは良いと思いますが、関数の処理はたったの3行なので一目で読めます。
これは意味のないコメントです。

// Engine\Plugins\Runtime\ZoneGraph\Source\ZoneGraph\Public\ZoneGraphTypes.h
USTRUCT()
struct FZoneGraphTagFilter
{
  GENERATED_BODY()

  // Filter passes if any of the 'AnyTags', and all of the 'AllTags', and none of the 'NotTags' are present.
  // Setting include or exclude tags to None, will skip that particular check.
  bool Pass(const FZoneGraphTagMask Tags) const
  {
    return (AnyTags == FZoneGraphTagMask::None || Tags.ContainsAny(AnyTags))
      && (AllTags == FZoneGraphTagMask::None || Tags.ContainsAll(AllTags))
      && (NotTags == FZoneGraphTagMask::None || !Tags.ContainsAny(NotTags));
  }
タグの評価ルール


この場合、レーンのタグかレーンプロファイルに「Test」が指定されていて、「Default」が指定されて「いない」場合に周回します。

Mass Spawner 設置

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)」のことです。
使い道は不明です。
最小ギャップと最大ギャップの働き
まず、レーンを一本の線にして、その線のどこにスポーンするか?を、最小ギャップ~最大ギャップの範囲でランダムに決めます。
その位置を基準にして、周囲に複数のスポーン地点を決めます。
スポーン地点が決まったら、また同じように最小ギャップ~最大ギャップの範囲でランダムに位置を決め、前の位置と、今決めた位置を加算します。
この値がレーンの長さを超えた場合、今処理したレーンでのスポーンを終了します。
複数のレーンがある場合は、次のレーンで同じようにスポーン地点を決める処理を繰り返します。

従って、レーンの長さが MinGap より小さい場合はスポーンしなくなるので、レーンの長さによって MinGap と MaxGap の値を調節する必要があります。
ちなみに、UE の長さの単位はセンチメートル (cm) なので、100 だと 1 メートルになります。

回避行動の必要性

Annotation / Avoidance / 回避行動 / 衝突回避 の必要性については、↓を見ていただければ一発で分かると思います。

他の Mass 用キャラクターが目詰まりを起こしていても、そのまま直進しようとしますが、直進できるスペースがないため、その場で止まってしまいます。
これを起きにくくさせるために回避行動が必要になります。
起きにくくなるだけで、限度はあります。

回避行動の追加

MassEntityConfig に「特性」をふたつ追加します(上図の赤枠内)。

  • 回避(Avoidance)
  • ナビゲーションオブスタクル(Navigation Obstacle)


衝突を避けるように移動しているのが分かると思います。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です