| 執筆バージョン: Unreal Engine 4.24 
 | 
はじめに
キャラクター同士の衝突回避を実現するためにUnrealEngineではCrowdManager(※1)とAvoidanceManagerというものがあります。

プロジェクト設定からも確認できるCrowdManagerとは違い,エディター上ではどこらかも存在を確認するこができないAvoidanceManager…
今回はそんな自分で探さない限り知り得ないであろうAvoidanceManagerについて紹介したいと思います。
特徴
AvoidanceManagerは衝突回避アルゴリズムであるRVO(Reciprocal Velocity Obstacles)(※2)をUEで使用するためのクラスで
以下の2種類のComponent内で使用されています
- CharacterMovementComponent
- WheeledVehicleMovementComponent
2つのComponentの基本的な使用方法、処理の流れはだいたい同じなため以降はCharacterMovementComponentでの使用を想定しての説明になります。
特徴
- ブループリントのみで動作可能
- 使用するまでのセットアップが簡単(CharacterMovementComponent,WheeledVehicleMovementComponentであればすぐ使用できる)
- 調整項目数が少ないため習熟コストが低い
- キャラクター以外でも対応がさせやすい(UMovementComponentにIRVOAvoidanceInterfaceを継承させることでAvoidanceManagerに登録可能)
- ゲームプレイ中にブループリントから機能のオンオフ、回避動作相手の変更などができる
気になる点
- 回避動作にNavMeshが考慮されないため領域外に出ることがある
↓はNavMeshギリギリの位置にある目標ポイントに向かうときにグレイマンが常にグリーンマンの回避方向に妨害し続けた結果NavMesh外に移動してしまったグリーンマン…
その後、彼が動くことはありませんでした…

使用方法
使用するための手順は非常にシンプルで
- CharacterMovementComponentのUseRVOAvoidanceにチェックを入れる
- CharacterMovementComponentのSetAvoidanceEnabledを使用し有効にする
 
  
のいずれかで使用可能です。
CharacterMovementComponentで公開されている変数情報
次にブループリント上で公開されてる変数まとめました。(それとよくわからなかった変数の日本語訳を画像で…)
| 変数名 | 説明 | 
| bUseRVOAvoidance | RVOを使用した回避処理を動作させる(サーバー上でのみ動作) クライアント環境では強制的にComponentの登録処理時、Falseに変更される | 
| AvoidanceConsiderationRadius | 回避処理をしだす範囲を指定します。 AvoidanceManagerではIRVOAvoidanceInterfaceのGetRVOAvoidanceOrigin(※2)から位置を取得しそこからの距離(高さは無視された2D距離)に回避対象者がいれば回避処理が継続されます。 | 
| AvoidanceWeight | 回避時の重み付け。0.0以上1.0未満を指定する(1以上を指定すると回避処理されなくなるため注意) 
 | 
| AvoidanceUID | RVO機能を有効にしたMovementComponentを識別するためのユニークなID。 AvoidanceManagerに登録される際にIDがセットされます。 (登録されたとき1からではなく0から使用されるため最初のComponentのみ登録されてたかの確認がとれないので注意) 
 | 
| AvoidanceGroup | 自身が属する回避グループ。 
 | 
| GroupsToAvoid | 回避動作をするべきグループ。デフォルトですべてのグループにチェックされてます。 チェックを外すことで回避動作をしなくすることもできますが次の項目で設定するほうが わかりやすいかと思います。 
 | 
| GroupsToIgnore | 回避動作を無視するグループ。ここにチェックしたグループが回避動作の範囲内に来ても何もしなくなります。 
 | 
処理の流れ
UCharacterMovementComponentのbUseRVOAvoidanceがTrueにした場合
- UCharacterMovementComponentのOnRegisterでNetModeのチェックが入りサーバーなら2に進み、クライアントだった場合強制的にbUseRVOAvoidanceがFalseになり終了
- UCharacterMovementComponentのSetUpdatedComponentでbUseRVOAvoidanceがTrueの場合、AvoidanceManagerのRegisterMovementComponentでManagerに登録される
- UCharacterMovementComponentのCalcVelocityでVelocityの計算がされるとき最後にCalcAvoidanceVelocityで回避動作するかの条件判定がされ回避が必要になった場合ここでVelocityが上書きされる
- CalcAvoidanceVelocityで回避が必要ではなかった場合UpdateDefaultAvoidanceが処理される
BP上から設定可能なもの

コンソールコマンド
コンソールコマンドとして使用できるものは2種類あります。
使用時の注意点としてRVO機能はServer上でのみ処理されるためDebug表示もServerでのみ確認可能になっています
| AvoidanceSystemToggle | Avoidanceのシステムをオンオフする | 
| AvoidanceDisplayAll | Avoidanceのデバック表示 
 ↑のような感じでAvoidanceManagerに登録される対象者に青い線が表示され実際回避処理がされる間は 赤い線に変わり足元に回避した方向が表示されます。 | 
Engine.ini で設定できる項目
		
		
			
			
			
			
				
					
				|  | [/Script/Engine.AvoidanceManager] DeltaTimeToPredict=0.5 | 
				
			 
		 
|  | デフォルト値 | 説明 | 
| DefaultTimeToLive | 1.5 | RVO機能をオフにしてからAvoidanceManager内で完全に使用されなくなるまでの時間の猶予 | 
| LockTimeAfterAvoid | 0.2 | 回避処理がされVelocityが設定された後、再度計算し直されるまでの時間 (UCharacterMovementComponentではSetAvoidanceVelocityLockで設定し時間が経過するまで同じVelocityで動作し続けます) | 
| LockTimeAfterClean | 0.001 | 回避処理されなかったときの再度計算し直されるまでの時間。基本は毎フレームになる時間を指定。 またキャラクター同時が接触した場合などもこれが指定されすぐ再計算されるようにしてる模様 | 
| DeltaTimeToPredict | 0.5 | 衝突回避をする速度を求めるための予測時間 | 
| ArtificialRadiusExpansion | 1.5 | オブジェクトの半径に掛けられる係数(CharacterならGetScaledCapsuleRadius *ArtificialRadiusExpansionが実際計算で使用される半径のサイズ) | 
| HeightCheckMargin | 10.0 | 回避対象オブジェクトとの許容可能な高さ 対象オブジェクトとのZ値の差分が「対象オブジェクトの高さ+自分の高さ+HeightCheckMargin」を超えているならスルーされる(UCharacterMovementComponentの場合はカプセルの半分サイズを高さとして使用されてます) | 
プロジェクト専用に拡張する場合
Engin.iniにAvoidanceManagerを指定することができるためプロジェクト用AvoidanceManagerを登録することは可能です。
		
		
			
			
			
			
				
					
				|  | [/Script/Engine.Engine] AvoidanceManagerClassName=/Script/Engine.AvoidanceManager | 
				
			 
		 
なのでずがこのAvoidanceManagerの関数はほぼvirtualがなかったりで有用ではないかもしれません…
Velocityを調整したい場合はUCharacterMovementComponentに限っては変数「bUseRVOPostProcess」をTrueにすることで関数「PostProcessAvoidanceVelocity」が使用できるのでこれを使用すればエンジン修正せずVelocityの調整が可能かと思います。
 
 
簡単ではありますがAvoidanceManagerについての紹介は以上となります、また機会があればCrowdManagerとの比較などやってみたいと思います。
少しでも皆様の開発に役立てばと思います。
ここまで読んでいただきありがとうございました。
 
※1
CrowdManagerの特徴や使用方法などはこちらを参考にさせていただきました。
https://qiita.com/EGJ-Ken_Kuwano/items/120901d259467568e4f7
※2
RVOに関しては以下のものを参考にさせていただきました。
https://qiita.com/Dv7Pavilion/items/5ef3cc4e95463027219a
※3
CharacterMovementComponentの場合、すでにIRVOAvoidanceInterfaceを継承しておりGetRVOAvoidanceOriginで返している位置は
キャラクターのカプセルの足元位置を返すようにしています。