UE5.6.1以降Vehicleと軽量な物理オブジェクトとの衝突でVehicleが減速してしまう

この質問は、以下のスレッドに関連して作成されました: [Content removed]

<br/>

[問題について]

UE5.5.4時点では、Vehicleの物理アセットとスケルタルメッシュのCCDを有効にした状態で、上記スレッドで提示いただいた「軽量な物理オブジェクトとの衝突時にVehicleのCCDを無効化する処理」により減速を抑制できていましたが、UE5.6.1へバージョンアップ後は、Vehicleで以前と同様の減速が発生するようになりました。

<br/>

また、バージョンアップにより関連がありそうな変更を無効化する下記デバッグコマンドも試しましたが、Vehicleの減速は抑制されませんでした。

・p.Chaos.Bugs.MidPhaseModifierConvexOptimizerFix false

・p.Chaos.Bugs.ResetTOIFix false

<br/>

こちらの挙動の原因や改善方法などあれば教えて頂けますとありがたいです。

<br/>

[添付した動画に関して]

軽量な物理オブジェクトとの衝突時にVehicleのCCDを無効化する処理を加えた上で撮影した動画になります。動画に使用されているVehicleのCCDは有効な状態です。

・UE5_5_4_Demo.mp4:UE5.5.4で添付したプロジェクトを起動し、撮影したもの。UE5.6.1でもこの挙動を再現したい。

・UE5_6_1_Deceleration_Demo.mp4:UE5.6.1で添付したプロジェクトを起動し、撮影したもの。UE5.5.4と設定は同じ

<br/>

こちらもご確認いただけますとありがたいです。

よろしくお願いします。

再現手順
[検証方法]

TestHitDecelMapを開き再生することで検証を開始します。

検証の条件を変更する場合はマップに配置されたBP_TestManagerを編集します。

TestManager>TestEnv以下のパラメータを編集することで検証の条件が変化します。パラメータは下記の通りです。

・Name :検証に用いるアクタの名前

・LaneLocationY :検証用アクタの検証開始位置のY軸のオフセット

・BotClass :衝突の検証に用いるアクタ(Vehicle)

・BotInitLocationX :BotClassで指定したアクタの検証開始位置のX軸のオフセット

・BotInitLocationZ :BotClassで指定したアクタの検証開始位置のZ軸のオフセット

・BotEndLocationX :BotClassで指定したアクタのX座標が指定値を超えた場合に検証をリセットする

・BotLocationRandomRangeY:BotClassで指定したアクタのY座標を指定値の範囲(-指定値~+指定値)で検証開始時にランダムにずらす

・PropClass :衝突の検証に用いるアクタ(軽量な物理オブジェクト)

・PropLocationOffsetX :PropClassで指定したアクタの検証開始位置のX軸のオフセット

・PropLocationZ :PropClassで指定したアクタの検証開始位置のZ軸のオフセット

基本的には BP_WheeledVehiclePawn と BP_WheeledVehiclePawn_DisableCCD の切り替えのために BotClass のみ変更して検証を行います。

その他のパラメータは微調整用です。

[追加/変更したアセット]

Map

・TestHitDecelMap:検証に使用したマップ。Template_Defaultをコピーして作成。

GameMode

・BP_TestHitDecel_GMB:TestHitDecelMapで使用しているゲームモード。

PhysicsAssets

・SportsCar_PhysicsAsset:すべてのCCD機能を有効化。

・SportsCar_PhysicsAsset_DisableCCD:SportsCar_PhysicsAssetからコピー。CCDの機能を無効化したPhysicsAsset。

SkeletalMeshes

・SKM_SportsCar_DisableCCD:SKM_SportsCarからコピー。SportsCar_PhysicsAsset_DisableCCDをPhysicsAssetとしてセットしたSkeletalMesh。

StaticMeshes

・SM_BoxProp:エンジンのモデリング機能で生成した見た目通りのコリジョンを持つシンプルなBox。

Blueprints

・BP_Observer:カメラを持つだけのポーン。撮影用。

・BP_PropBase:Vehicleと衝突した時に自身の物理、コリジョン、見た目を無効化する機能を持つアクタ。

・BP_PropBox:BP_PropBaseを継承したアクタ。軽量(1kg)の物理オブジェクト。

・BP_TestManager:TestManagerを継承したアクタ。テスト管理用のアクタ。検証に用いるVehicleや衝突用の物理オブジェクトを指定する。

・BP_WheeledVehiclePawn:WheeledVehiclePawnを継承。SkeletalMeshにSKM_SportsCarを設定。このBPのCCDは有効化。160km/hまでAddForceする機能やデバッグ表示の機能を持つ。回転は全てロック。

・BP_WheeledVehiclePawn_DisableCCD:BP_WheeledVehiclePawnからコピー。SkeletalMeshをSKM_SportsCar_DisableCCDに変更。このBPのCCDは無効化。

[ChaosVehiclePluginについて]

ChaosVehiclePluginはエンジンに搭載されているものをプロジェクト以下のPlugins以下にコピーして編集し、使用しています。

変更点は軽量な物理オブジェクトに衝突した際にVehicleのCCDを無効化する対応の追加のみです。

エンジンのバージョンに応じて下記zipに格納されているChaosVehiclePluginに差し替えます。

・ChaosVehiclesPluginForEngine55_DisableCCD_archive.zip:UE5.5.4で使用

・ChaosVehiclesPluginForEngine56_DisableCCD_archive.zip:UE5.6.1で使用

デフォルトで使用されているChaosVehiclePluginはChaosVehiclesPluginForEngine56_DisableCCD_archive.zipに格納されていたものを使用しています。

[補足]​

添付したパッケージはUE5.5.4のVehicleテンプレートから作成しました。​

TestManagerはC++で実装しており、下記に保存しています。

TestHitDecel_Vehicle\Source\TestHitDecel_Vehicle\TestManager.cpp

TestHitDecel_Vehicle\Source\TestHitDecel_Vehicle\TestManager.h

検証の自動化の為に​AddForceによる加速後を行っていますが、スロットル入力による加速後であっても減速は発生しました。

再現プロジェクトのご用意ありがとうございます。

特定のMidPhaseのCCDを無効化するコールバックが正しく動作していない問題を確認しました。

動作を確認するとコールバックを処理したあとのNarrowPhaseでCCDが有効になっているコリジョンが生成されてしまっているようです。

原因としては新規に追加されたMidPhaseはNarrowPhaseが終わった後にはじめてMidPhaseのコールバックで列挙されるようになるためのようです。

以下のワークアラウンドが機能しました。お手数ですが適用してご確認いただけますでしょうか

//CollisionConstraintAllocator.h
 
			template<typename TLambda>
			void VisitMidPhases(const TLambda& Visitor)
			{
				ProcessNewItems(); //追加
				for (FParticlePairMidPhasePtr& MidPhase : ParticlePairMidPhases)
				{
					if (Visitor(*MidPhase) == ECollisionVisitorResult::Stop)
					{
						return;
					}
				}
			}

このコードを追加するとVisitMidPhaseを行うタイミングで新規に追加されたMidPhaseが列挙されるようになります。

以下のコードはVisitMidPhasesを使ってMidPhaseをイテレートする一例です。

	Accessor.VisitMidPhases( [&VehicleHandle, &NumOposite](Chaos::FMidPhaseModifier& MidPhase)
		{
			const Chaos::FGeometryParticleHandle* OtherHandle = MidPhase.GetOtherParticle(VehicleHandle);
			if (OtherHandle == nullptr )
			{
				return;
			}
			auto OtherRigid = OtherHandle->CastToRigidParticle();
			if (OtherRigid == nullptr)
			{
				return;
			}
			// 相手の質量が一定以下の場合はCCDを無効化(1.1fなのは誤差で質量が1.0が設定されている場合でも無効化されないことがあったため)  
			if (OtherRigid->M() <= 1.1f)
			{
//				UE_LOG(LogChaos, Log, TEXT("MidPhaseModifier %d>%d %s <--> %s"), VehicleHandle->GetHandleIdx(), OtherHandle->GetHandleIdx(), *VehicleHandle->GetDebugName(), *OtherHandle->GetDebugName());
				MidPhase.DisableCCD();
			}
		});

ご回答頂きありがとうございます。

提示頂いたコードの追加と、軽量な物理オブジェクトとの衝突時に Vehicle の CCD を無効化する処理を VisitMidPhases で行うように置き換えたところ、Vehicle の挙動が改善されたことが確認できました。

ご提示いただいたコードの追加や変更に関して懸念点などありましたら、ご教授頂けますとありがたいです。

よろしくお願い致します。

ご確認ありがとうございます。改善が見られた件承知しました。

本件はバグと判断されるためバグデータベースに登録を行います、しかし少々立て込んでいるためもう少し時間をいただければと思います。

懸念点としては​ProcessNewItemsが複数回呼ばれることとなることですが、本来のタイミングのProcessNewItem呼び出しの際には追加された新規配列要素は空になっているはずなのでオーバーヘッドは最小限に抑えられるはずです。

懸念点に関して共有いただきありがとうございます。

本件の修正が適用されるUEのバージョンに関してこちらでも把握したいので、バグデータベースへ登録されましたら関連ページなど共有いただけますとありがたいです。

よろしくお願い致します。

UE-356364 Not all MidPhases are enumerated in TSimCallbackObject::OnMidPhaseModification

としてバグ登録させていただきました。

数営業日ののちに https://issues.unrealengine.com/ に公開され検索できるようになるはずです。

ご対応いただきありがとうございます。

https://issues.unrealengine.com/issue/UE-356364

こちらのリンクから本件の修正に関するWebページを確認することができました。