mcpField
U
ue-physics-collision

ue-physics-collision

github.com/quodsoler開発4191.2k 回インストール4 週間前に更新
リポジトリ

ue-physics-collision について

Unreal Engine 5.8 開発者向けの物理・コリジョンスキルです。クエリ、コリジョンイベント、剛体、Chaos の設定を、現行ヘッダーに基づいて解説します。

主な機能

  1. 01コリジョンチャンネルとプロファイル
  2. 02トレース、スイープ、オーバーラップクエリ
  3. 03FHitResult のヒット情報
  4. 04コリジョンとウェイクイベント
  5. 05剛体、力、物理マテリアル
  6. 06Chaos ソルバーとネットワーク物理

活用シーン

  1. 01オブジェクトとトレースチャンネルの設定
  2. 02ヒット、インタラクション、範囲判定の実装
  3. 03コンポーネントの重なりや衝突への対応
  4. 04剛体の動きと物理パラメーターの設定

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/quodsoler/unreal-engine-skills --skill ue-physics-collision

インストール後、Claude Code で/ue-physics-collisionを入力して読み込まれたか確認します。

同梱ファイルreferences/collision-channel-setup.mdreferences/trace-patterns.md

詳細

UE の物理とコリジョン

対象エンジン:UE 5.8。以下の API は 5.8 のヘッダーで検証済みです。古い形式は「非推奨 — 使用しないでください」に記載しています。

コリジョンと物理は Engine モジュール(UPrimitiveComponent、UWorld クエリ、FHitResult、UCollisionProfile)と PhysicsCore モジュール(FCollisionShape、UPhysicalMaterial、FBodyInstanceCore、ECollisionTraceFlag、EPhysicalSurface)にあります。シミュレーター自体は Chaos(Chaos/ChaosSolverEngine モジュール)です。破壊機能では GeometryCollectionEngine と FieldSystemEngine も追加されます。ほとんどのゲームプレイコードで必要なのは、Build.cs の "Engine" と "PhysicsCore" だけです。

コンテキスト

.agents/ue-project-context.md が存在する場合は読み込んでください(モジュール名、規約、有効なプラグイン、GAS/ネットワーク設定)。存在しなくても処理を中止しないでください。

リクエストとコードベースから該当する領域を特定してください。異なるコードになる可能性のある解釈が 2 つある場合に限り、質問してください。

リクエストの内容…参照先
チャネル、プロファイル、DefaultEngine.ini、応答コリジョンチャネルとプロファイル
ライントレース、スイープ、オーバーラップクエリ、非同期トレーストレース、スイープ、オーバーラップクエリ
クエリがヒットした対象の情報の読み取りFHitResult
OnComponentHit、OnComponentBeginOverlap、ウェイク/スリープコリジョンイベント
剛体、インパルス、力、質量、減衰、スリープ物理ボディと力
ジョイント、ラジアルフォースフィールド、ラグドール拘束、ラジアルフォース、ラグドール
摩擦、反発係数、サーフェスタイプ物理マテリアル
ソルバー設定、サブステップ、CVar、物理スレッドのティックChaos ソルバーと非同期物理
レプリケートされた物理、再シミュレーション、予測補間ネットワーク物理

コリジョンチャネルとプロファイル

ECollisionChannel(Engine/EngineTypes.h:1098)には、エンジンチャネルが 8 個、非表示のエンジンスロットが 6 個、ゲーム用スロットが 50 個あります(合計 64 個。ECC_GameTraceChannel50 は :1168):

ECC_WorldStatic, ECC_WorldDynamic, ECC_Pawn, ECC_PhysicsBody,
ECC_Vehicle, ECC_Destructible                 // object channels (what a component IS)
ECC_Visibility, ECC_Camera                    // trace channels (what a query LOOKS FOR)
ECC_GameTraceChannel1 ... ECC_GameTraceChannel50  // project slots, either kind
  • オブジェクトチャネル — すべてのコンポーネントが 1 つだけ持ち、SetCollisionObjectType で設定します。*ByObjectType クエリで照合されます。
  • トレースチャネル — オブジェクトタイプにはなりません。クエリで *ByChannel に渡し、各コンポーネントのそのチャネルに対する応答に応じてブロック/オーバーラップ/無視が決まります。
  • ECollisionResponse(Engine/EngineTypes.h:1346):ECR_Ignore、ECR_Overlap、ECR_Block。
  • ECollisionEnabled::Type(Engine/EngineTypes.h:1805):NoCollision、QueryOnly、PhysicsOnly、QueryAndPhysics、ProbeOnly、QueryAndProbe。
#include "Components/PrimitiveComponent.h"

MyMesh->SetCollisionProfileName(TEXT("BlockAllDynamic"));   // preferred: one call sets everything
MyMesh->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
MyMesh->SetCollisionObjectType(ECC_PhysicsBody);
MyMesh->SetCollisionResponseToAllChannels(ECR_Block);
MyMesh->SetCollisionResponseToChannel(ECC_Pawn, ECR_Overlap);
MyMesh->SetCollisionResponseToChannel(ECC_Camera, ECR_Ignore);

FCollisionResponseContainer Responses(ECR_Ignore);
Responses.SetResponse(ECC_Visibility, ECR_Block);
MyMesh->SetCollisionResponseToChannels(Responses);

SetCollisionProfileName はすべての手動設定の応答を上書きするため、最初にプロファイルを適用し、その後にチャネルごとのオーバーライドを設定してください。

Config/BaseEngine.ini の [/Script/Engine.CollisionProfile] には、エンジンのプロファイルとして NoCollision、BlockAll、OverlapAll、BlockAllDynamic、OverlapAllDynamic、IgnoreOnlyPawn、OverlapOnlyPawn、Pawn、Spectator、CharacterMesh、PhysicsActor、Destructible、InvisibleWall、InvisibleWallDynamic、Trigger、Ragdoll、Vehicle、UI、WaterBodyCollision が用意されています。

カスタムチャネルとプロファイルは設定ファイルのみで定義でき、実行時に作成する API はありません:

[/Script/Engine.CollisionProfile]
+DefaultChannelResponses=(Channel=ECC_GameTraceChannel1,DefaultResponse=ECR_Block,bTraceType=True,bStaticObject=False,Name="Weapon")
+DefaultChannelResponses=(Channel=ECC_GameTraceChannel2,DefaultResponse=ECR_Block,bTraceType=False,bStaticObject=False,Name="Interactable")
+Profiles=(Name="MyInteractable",CollisionEnabled=QueryAndPhysics,ObjectTypeName="Interactable",CustomResponses=((Channel="Weapon",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Block)),HelpMessage="Interactable props")
+EditProfiles=(Name="Pawn",CustomResponses=((Channel="Weapon",Response=ECR_Block)))

bTraceType=True はトレースチャネルを、False はオブジェクトチャネルを宣言します。+Profiles= はプロファイル全体を追加または置換します。+EditProfiles= は既存のプロファイルの応答のみを更新します(Engine/CollisionProfile.h:160-190)。UCollisionProfile::Get() はテーブルを読み込み、UCollisionProfile::LoadProfileConfig(bool bForceInit)(Engine/CollisionProfile.h:237)は設定変更後に再読み込みします。

プロファイル一式、ini のリファレンス、デバッグ用チェックリストについては、collision-channel-setup.md を参照してください。

トレーススイープとオーバーラップクエリ

すべてのワールドクエリは UWorld の const メンバーです(Engine/World.h:2128-2441)。各ファミリーには Test/Single/Multi 形式があります。

サフィックス選択基準追加パラメーター
ByChannelクエリ側のトレースチャンネルと各コンポーネントのレスポンスECollisionChannel TraceChannel、省略可能な FCollisionResponseParams
ByObjectType対象コンポーネントのオブジェクトチャンネルconst FCollisionObjectQueryParams&
ByProfile名前付きプロファイルに保存されたチャンネルとレスポンスFName ProfileName
#include "Engine/World.h"
#include "Engine/HitResult.h"
#include "CollisionQueryParams.h"
#include "CollisionShape.h"

FCollisionQueryParams Params(TEXT("MyWeaponTrace"), /*bTraceComplex=*/false, GetOwner());
Params.bReturnPhysicalMaterial = true;   // fills Hit.PhysMaterial
Params.bReturnFaceIndex        = false;  // fills Hit.FaceIndex; expensive
Params.bIgnoreTouches          = true;   // discard ECR_Overlap results (bIgnoreBlocks is the inverse)
Params.bFindInitialOverlaps    = true;   // report shapes already overlapping at Start
Params.MobilityType            = EQueryMobilityType::Any;  // Any | Static | Dynamic
Params.AddIgnoredActor(GetOwner());
Params.AddIgnoredComponent(MyMesh.Get());   // .Get(): a TObjectPtr member is ambiguous (CollisionQueryParams.h:267-269)

FHitResult Hit;
GetWorld()->LineTraceSingleByChannel(Hit, Start, End, ECC_Visibility, Params);

TArray<FHitResult> Hits;
GetWorld()->LineTraceMultiByChannel(Hits, Start, End, ECC_GameTraceChannel1, Params);

FCollisionObjectQueryParams ObjParams(ECC_Pawn);
ObjParams.AddObjectTypesToQuery(ECC_PhysicsBody);
GetWorld()->LineTraceSingleByObjectType(Hit, Start, End, ObjParams, Params);

GetWorld()->LineTraceSingleByProfile(Hit, Start, End, TEXT("BlockAll"), Params);

const bool bAnythingThere = GetWorld()->LineTraceTestByChannel(Start, End, ECC_Visibility, Params);

TraceTag は最初のコンストラクター引数で、コンソールの TraceTagAll/名前付きタグのデバッグ描画にも使用されます。

スイープでは回転と FCollisionShape を指定します(PhysicsCore/Public/CollisionShape.h:284-316)。

const FCollisionShape Sphere  = FCollisionShape::MakeSphere(30.f);                  // radius
const FCollisionShape Box     = FCollisionShape::MakeBox(FVector(50.f, 30.f, 80.f));// half-extents
const FCollisionShape Capsule = FCollisionShape::MakeCapsule(34.f, 88.f);           // radius, half-height

GetWorld()->SweepSingleByChannel(Hit, Start, End, FQuat::Identity, ECC_Pawn, Capsule, Params);
GetWorld()->SweepMultiByChannel(Hits, Start, End, FQuat::Identity, ECC_Pawn, Sphere, Params);
GetWorld()->SweepSingleByObjectType(Hit, Start, End, FQuat::Identity, ObjParams, Box, Params);
GetWorld()->SweepSingleByProfile(Hit, Start, End, FQuat::Identity, TEXT("Pawn"), Capsule, Params);

GetCapsuleHalfHeight() には端の半径が含まれます。GetCapsuleAxisHalfLength() はシャフト部分のみです。

オーバーラップは静止した形状テストであり、FOverlapResult を返します(Engine/OverlapResult.h:12)。

#include "Engine/OverlapResult.h"

TArray<FOverlapResult> Overlaps;
GetWorld()->OverlapMultiByObjectType(Overlaps, Center, FQuat::Identity,
    FCollisionObjectQueryParams(ECC_Pawn), FCollisionShape::MakeSphere(500.f), Params);
GetWorld()->OverlapMultiByChannel(Overlaps, Center, FQuat::Identity, ECC_Pawn,
    FCollisionShape::MakeSphere(500.f), Params);

const bool bBlocked = GetWorld()->OverlapAnyTestByChannel(Center, FQuat::Identity,
    ECC_WorldStatic, FCollisionShape::MakeBox(FVector(40.f)), Params);

for (const FOverlapResult& Result : Overlaps)
{
    AActor* Actor = Result.GetActor();
    UPrimitiveComponent* Comp = Result.GetComponent();
}

OverlapAnyTestByChannel は最初のブロックまたはタッチで停止します。OverlapBlockingTestByChannel はタッチを無視します。クエリの目的が「自分のコンポーネントがすでに何と接触しているか」である場合は、ワールドクエリではなく UPrimitiveComponent::GetOverlappingActors または ComponentOverlapComponent を使用してください。

非同期トレースは今フレームにキューへ追加され、次のフレームに読み取れます(Engine/World.h:2522、WorldCollision.h:148)。

#include "WorldCollision.h"

// EAsyncTraceType: Test | Single | Multi
FTraceHandle Handle = GetWorld()->AsyncLineTraceByChannel(
    EAsyncTraceType::Single, Start, End, ECC_Visibility, Params);

FTraceDatum Datum;
if (GetWorld()->QueryTraceData(Handle, Datum) && Datum.OutHits.Num() > 0)
{
    const FHitResult& First = Datum.OutHits[0];
}

FTraceDelegate*(DECLARE_DELEGATE_TwoParams(FTraceDelegate, const FTraceHandle&, FTraceDatum&))を渡すと、バッチの完了時にコールバックが呼び出されます。

ヒットスキャン、近接スイープ、インタラクション、接地チェック、範囲攻撃、視線確認、非同期センサーのパターンに加え、Blueprint レイヤーの UKismetSystemLibrary ラッパーとパフォーマンスに関するガイダンスについては、trace-patterns.md を参照してください。

FHitResult

Engine/HitResult.h。Actor はメンバーではなくなっています。アクセサーを介してアクターにアクセスします。

Hit.bBlockingHit;        // :107  false for a touch-only result
Hit.bStartPenetrating;   // :116  query began already overlapping; PenetrationDepth :91
Hit.Time;                // :33   0..1 along Start->End;  Distance :37 in cm
Hit.Location;            // :45   where the swept shape's origin ended up
Hit.ImpactPoint;         // :53   surface contact point
Hit.Normal;              // :61   normal opposing movement at Location
Hit.ImpactNormal;        // :69   geometric surface normal at ImpactPoint
Hit.TraceStart;          // :76;  TraceEnd :83
Hit.Item;                // :99   instance index (ISM/HISM); ElementIndex :103 shape index
Hit.FaceIndex;           // :26   needs Params.bReturnFaceIndex
Hit.BoneName;            // :141  bone hit;  MyBoneName :145 our own bone
Hit.PhysMaterial;        // :123  TWeakObjectPtr, needs bReturnPhysicalMaterial

AActor* HitActor = Hit.GetActor();                 // :211
UPrimitiveComponent* HitComp = Hit.GetComponent(); // :227
FActorInstanceHandle Handle = Hit.GetHitObjectHandle(); // :216, lightweight instances

Multi クエリでは、ブロッキングヒットになれるのは最後の要素のみです。それ以前の要素はすべてタッチです。

コリジョンイベント

デリゲートはスパースな動的マルチキャストです。そのため、ハンドラーはデリゲートと完全に一致するパラメーターリストを持つ UFUNCTION() として ヘッダーファイル内で 宣言する必要があります。そうしないと、実行時に AddDynamic のバインドが失敗します。シグネチャは Components/PrimitiveComponent.h:274-282 および GameFramework/Actor.h:194-196 に記載されています。

デリゲートパラメーター
FComponentHitSignatureUPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit
FComponentBeginOverlapSignatureUPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult
FComponentEndOverlapSignatureUPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex
FComponentWakeSignature/FComponentSleepSignatureUPrimitiveComponent* WakingComponent(SleepingComponent)、FName BoneName
FActorBeginOverlapSignature/FActorEndOverlapSignatureAActor* OverlappedActor, AActor* OtherActor
FActorHitSignatureAActor* SelfActor, AActor* OtherActor, FVector NormalImpulse, const FHitResult& Hit
// MyPickup.h
#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Engine/HitResult.h"
#include "MyPickup.generated.h"

UCLASS()
class MYGAME_API AMyPickup : public AActor
{
	GENERATED_BODY()

public:
	AMyPickup();

protected:
	virtual void BeginPlay() override;

	UPROPERTY(VisibleAnywhere, Category = "Collision")
	TObjectPtr<class USphereComponent> Trigger;

	UPROPERTY(VisibleAnywhere, Category = "Collision")
	TObjectPtr<class UStaticMeshComponent> Mesh;

	UFUNCTION()
	void OnBeginOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
		UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);

	UFUNCTION()
	void OnEndOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
		UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);

	UFUNCTION()
	void OnHit(UPrimitiveComponent* HitComponent, AActor* OtherActor,
		UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit);
};
// MyPickup.cpp
#include "MyPickup.h"
#include "Components/SphereComponent.h"
#include "Components/StaticMeshComponent.h"

AMyPickup::AMyPickup()
{
	Trigger = CreateDefaultSubobject<USphereComponent>(TEXT("Trigger"));
	SetRootComponent(Trigger);
	Trigger->SetSphereRadius(120.f);
	Trigger->SetCollisionProfileName(TEXT("OverlapAllDynamic"));
	Trigger->SetGenerateOverlapEvents(true);

	Mesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh"));
	Mesh->SetupAttachment(Trigger);
	Mesh->SetCollisionProfileName(TEXT("PhysicsActor"));
	Mesh->SetSimulatePhysics(true);
	Mesh->SetNotifyRigidBodyCollision(true);   // "Simulation Generates Hit Events"
}

void AMyPickup::BeginPlay()
{
	Super::BeginPlay();

	Trigger->OnComponentBeginOverlap.AddDynamic(this, &AMyPickup::OnBeginOverlap);
	Trigger->OnComponentEndOverlap.AddDynamic(this, &AMyPickup::OnEndOverlap);
	Mesh->OnComponentHit.AddDynamic(this, &AMyPickup::OnHit);
}

void AMyPickup::OnBeginOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
	UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
	if (OtherActor && OtherActor != this)
	{
		Destroy();
	}
}

void AMyPickup::OnEndOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
	UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{
}

void AMyPickup::OnHit(UPrimitiveComponent* HitComponent, AActor* OtherActor,
	UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit)
{
	const float ImpactStrength = NormalImpulse.Size();
}

要件:オーバーラップを発生させるには、少なくとも片方で ECR_Overlap が設定され、ペアが ECR_Ignore ではなく、両方 のコンポーネントで SetGenerateOverlapEvents(true) が設定されている必要があります(bGenerateOverlapEvents は private です。Components/PrimitiveComponent.h:429)。シミュレーションヒットには、両方で ECR_Block が設定され、QueryAndPhysics または PhysicsOnly が選択され、シミュレーション中のコンポーネントで SetNotifyRigidBodyCollision(true) が設定されている必要があります。このフラグがなくても、スイープ移動(SetActorLocation(..., true)、ムーブメントコンポーネント)はブロッキングヒット時に OnComponentHit を発生させます(PrimitiveComponent.cpp:3540-3550)。OnComponentWake/OnComponentSleep には、ボディで bGenerateWakeEvents が必要です(PhysicsCore/Public/BodyInstanceCore.h:59)。

物理ボディと力

MyMesh->SetSimulatePhysics(true);                          // PrimitiveComponent.h:1661
MyMesh->SetEnableGravity(true);                            // :2801
MyMesh->SetMassOverrideInKg(NAME_None, 50.f, true);        // :2857;  GetMass() :2861
MyMesh->SetLinearDamping(0.1f);                            // :2825;  SetAngularDamping :2833
MyMesh->SetUseCCD(true);                                   // :2894 swept collision for fast bodies
MyMesh->SetConstraintMode(EDOFMode::XYPlane);              // :1682 lock to a plane
const bool bSimulating = MyMesh->IsSimulatingPhysics();    // :2644

MyMesh->AddImpulse(FVector(0.f, 0.f, 1000.f), NAME_None, /*bVelChange=*/false);  // :1692
MyMesh->AddImpulseAtLocation(FVector(500.f, 0.f, 0.f), Hit.ImpactPoint);         // :1725 adds spin
MyMesh->AddRadialImpulse(Center, 500.f, 2000.f, RIF_Linear, /*bVelChange=*/false); // :1748
MyMesh->AddForce(FVector(0.f, 0.f, 9800.f), NAME_None, /*bAccelChange=*/false);  // :1759 every tick
MyMesh->AddRadialForce(Center, 500.f, 3000.f, RIF_Constant, false);              // :1793

MyMesh->SetPhysicsLinearVelocity(FVector(0.f, 0.f, 300.f));  // :1825 teleports velocity; use sparingly
const FVector Velocity = MyMesh->GetPhysicsLinearVelocity(); // :1832
MyMesh->WakeRigidBody();                                     // :1938;  PutRigidBodyToSleep() :1945

bVelChange=true / bAccelChange=true は質量を無視します。ERadialImpulseFalloff は RIF_Constant または RIF_Linear です(PhysicsCore/Public/Chaos/ChaosEngineInterface.h:90)。

MyMesh->GetBodyInstance() でボディにアクセスできます。FBodyInstanceCore のフラグ(PhysicsCore/Public/BodyInstanceCore.h):bSimulatePhysics(:30)、bOverrideMass(:35)、bEnableGravity(:39)、bUpdateKinematicFromSimulation(:43)、bAutoWeld(:51)、bStartAwake(:55)、bGenerateWakeEvents(:59)。FBodyInstance には bUseCCD(:418)、bNotifyRigidBodyCollision(:440)、LinearDamping(:629)、MassScale(:645)、InertiaTensorScale(:653)、SleepFamily(:410)、CustomSleepThresholdMultiplier(:696)が追加されます。ESleepFamily(Chaos/ChaosEngineInterface.h:101)は Normal、Sensitive、Custom のいずれかです。乗数が参照されるのは Custom の場合のみです。

コリジョンの複雑さは ECollisionTraceFlag(PhysicsCore/Public/BodySetupEnums.h:13-20)で設定します:CTF_UseDefault、CTF_UseSimpleAndComplex、CTF_UseSimpleAsComplex、CTF_UseComplexAsSimple。Complex-as-simple のボディはシミュレーションできません。

コンストレイント、ラジアルフォース、ラグドール

UPhysicsConstraintComponent(PhysicsEngine/PhysicsConstraintComponent.h:24)は FConstraintInstance(:73)をラップします。これは Physics Asset が各ジョイントに保存するものと同じ構造体です。

#include "PhysicsEngine/PhysicsConstraintComponent.h"

UPhysicsConstraintComponent* Joint = NewObject<UPhysicsConstraintComponent>(this);
Joint->SetupAttachment(RootComponent);
Joint->RegisterComponent();
Joint->SetConstrainedComponents(MeshA, NAME_None, MeshB, NAME_None);  // :134
Joint->SetLinearXLimit(ELinearConstraintMotion::LCM_Locked, 0.f);     // :270
Joint->SetAngularSwing1Limit(EAngularConstraintMotion::ACM_Limited, 45.f); // :291
Joint->SetAngularTwistLimit(EAngularConstraintMotion::ACM_Free, 0.f);      // :305
Joint->SetAngularVelocityDriveTwistAndSwing(true, false);             // :199
Joint->SetAngularDriveParams(500.f, 50.f, 0.f);                       // :262
Joint->SetDisableCollision(true);                                     // :374
Joint->BreakConstraint();                                             // :142

モーション列挙型は ELinearConstraintMotion(LCM_Free、LCM_Limited、LCM_Locked)と EAngularConstraintMotion(ACM_Free、ACM_Limited、ACM_Locked)です。エディターのプリセットは、これらを組み合わせたものにすぎません。Fixed は6軸すべてをロックし、Hinge は角度軸を1つ解放し、Prismatic は線形軸を1つ解放し、Ball-and-Socket はすべての角度軸を解放します。URadialForceComponent(PhysicsEngine/RadialForceComponent.h:16)は、爆発や吸引にすぐ使えるコンポーネントです。設定項目は Radius、Falloff、ImpulseStrength、bImpulseVelChange、bIgnoreOwningActor、ForceStrength です。単発の力を加えるには FireImpulse()(:50)を使い、対象を絞り込むには AddObjectTypeToAffect(EObjectTypeQuery)(:54)を使います。

ラグドールは、スケルタルメッシュの Physics Asset(UPhysicsAsset::SkeletalBodySetups、ConstraintSetup — PhysicsEngine/PhysicsAsset.h:213-220)を通じて動作します。

GetMesh()->SetCollisionProfileName(TEXT("Ragdoll"));
GetMesh()->SetAllBodiesSimulatePhysics(true);                  // SkeletalMeshComponent.h:2344
GetMesh()->SetAllBodiesBelowSimulatePhysics(TEXT("spine_01"), true); // :2376 partial ragdoll
GetMesh()->SetPhysicsBlendWeight(1.f);                         // :2353 blend animation <-> sim

物理マテリアル

PhysicsCore/Public/PhysicalMaterials/PhysicalMaterial.h:103。

float Friction;                 // :115 kinetic;  StaticFriction :119
float Restitution;              // :131 0 dead, 1 elastic
float Density;                  // :147 g/cm^3, drives mass from shape volume
float SleepLinearVelocityThreshold;   // :151;  SleepAngularVelocityThreshold :155
int32 SleepCounterThreshold;          // :159;  RaiseMassToPower :167
TEnumAsByte<EPhysicalSurface> SurfaceType;  // :181
// FrictionCombineMode / RestitutionCombineMode are EFrictionCombineMode::Type and only
// apply when bOverrideFrictionCombineMode / bOverrideRestitutionCombineMode is set.

MyMesh->SetPhysMaterialOverride(MyPhysMaterial);   // PrimitiveComponent.h:3008

if (UPhysicalMaterial* PhysMat = Hit.PhysMaterial.Get())   // needs bReturnPhysicalMaterial
{
	const EPhysicalSurface Surface = UPhysicalMaterial::DetermineSurfaceType(PhysMat); // :242
}

EPhysicalSurface(PhysicsCore/Public/Chaos/ChaosEngineInterface.h:20)は、SurfaceType_Default と SurfaceType1..SurfaceType62 で構成され、名前は Project Settings > Physics で設定します。

Chaos ソルバーと非同期物理

5.8 で唯一の物理バックエンドは Chaos です。FChaosScene (PhysicsCore/Public/Chaos/ChaosScene.h:84) がソルバーを所有し、SetUpForFrame (:141)、StartFrame (:140)、EndFrame (:142) によって駆動されます。WaitPhysScenes (:122) は結果を待機します。

プロジェクト設定は UPhysicsSettings / UPhysicsSettingsCore の [/Script/Engine.PhysicsSettings] にあります。

設定ヘッダー説明
DefaultGravityZPhysicsSettingsCore.h:25ワールドの重力。デフォルトは -980 です
BounceThresholdVelocity:79この値を下回ると、反発係数は適用されません
MaxDepenetrationVelocity:95押し出し速度の上限です。0 は無制限です
bSimulateSkeletalMeshOnDedicatedServer:114オフにすると、サーバーでラグドールの負荷を抑えられます
DefaultShapeComplexity:119プロジェクト全体に適用される ECollisionTraceFlag です
SolverOptions:123FChaosSolverConfiguration
bSubstepping / MaxSubstepDeltaTime / MaxSubstepsPhysicsSettings.h:325,341,345小さく高速なボディのトンネリングやジッターを防ぎます
bTickPhysicsAsync / AsyncFixedTimeStepSize:333,337物理スレッドの固定レート
PhysicsPrediction:267再シミュレーションを有効化する FPhysicsPredictionSettings

FChaosSolverConfiguration (Chaos/Public/ChaosSolverConfiguration.h:51) では、PositionIterations、VelocityIterations、ProjectionIterations、CollisionMarginFraction、CollisionCullDistance、CollisionMaxPushOutVelocity を設定できます。

5.8 に存在する診断用 CVar:

p.Chaos.DebugDraw.Enabled 1                              ChaosDebugDrawComponent.cpp:29
p.Chaos.DebugDraw.Radius 3000 / p.Chaos.DebugDraw.MaxLines 20000   capture limits
p.Chaos.Solver.Iterations.Position|Velocity|Projection   PBDRigidsSolver.cpp:337,340,343
p.Chaos.Solver.Deterministic :346   p.Chaos.Solver.UseCCD :406 (global CCD switch)
p.Chaos.DedicatedThreadEnabled                           ChaosSolversModule.cpp:23

bTickPhysicsAsync が有効な場合、ソルバーと同期して実行する必要があるゲームプレイコードには、Tick ではなく非同期ティックを使用します。アクターのコンストラクターで bAsyncPhysicsTickEnabled を設定するか(protected、GameFramework/Actor.h:699)、コンポーネントで SetAsyncPhysicsTickEnabled(true) を呼び出し(ActorComponent.h:1435。Components/ActorComponent.h:407 のコンポーネントフィールドは private です)、AsyncPhysicsTickActor(float DeltaTime, float SimTime) (Actor.h:2930) または AsyncPhysicsTickComponent(float DeltaTime, float SimTime) (ActorComponent.h:985) をオーバーライドします。境界を越えて入力を渡すには UAsyncPhysicsInputComponent (Engine/Public/Physics/AsyncPhysicsInputComponent.h:10) を使用します。

FBodyInstance の下層では、ボディは Chaos::FPhysicsObject として参照されます。UPrimitiveComponent は IPhysicsComponent を実装し、GetPhysicsObjectById、GetPhysicsObjectByName、GetAllPhysicsObjects (Components/PrimitiveComponent.h:3248-3250) を提供します。FHitResult::PhysicsObject と PhysicsObjectOwner (Engine/HitResult.h:134-137) は、アクターが所有していない場合に、クエリが何にヒットしたかを識別します。

ネットワーク物理

物理シミュレーションはサーバー上で実行されます。ヒットイベントとオーバーラップイベントはシミュレーションが実行される場所で発生するため、アクターもローカルでシミュレーションするか、結果をレプリケートしない限り、クライアントには表示されません。

  • AActor::SetPhysicsReplicationMode(EPhysicsReplicationMode) / GetPhysicsReplicationMode() (GameFramework/Actor.h:924,928) で、Default、PredictiveInterpolation、Resimulation、None (Engine/EngineTypes.h:3614) を選択します。
  • Resimulation には Project Settings > Physics > Physics Prediction (UPhysicsSettings::PhysicsPrediction) が必要です。PredictiveInterpolation はこの設定がなくても動作しますが、有効にすると最も良好に機能します (Engine/EngineTypes.h:3619-3629)。
  • UNetworkPhysicsComponent (Engine/Public/Physics/NetworkPhysicsComponent.h:2290) は物理スレッド上で入力と状態の履歴を記録し、クライアントが過去の状態を修正したうえで再シミュレーションできるようにします。
  • 予測を行わないアクターのトランスフォーム同期には、引き続き bReplicateMovement / FRepMovement が使われます。

レプリケーションのルール、条件、RPC の設計については ue-networking-replication を参照してください。このスキルでは、選択する物理モードのみを扱います。

モジュール依存関係

// MyGame.Build.cs
PublicDependencyModuleNames.AddRange(new string[] {
	"Core", "CoreUObject",
	"Engine",       // UPrimitiveComponent, FHitResult, UWorld queries, UCollisionProfile
	"PhysicsCore",  // FCollisionShape, UPhysicalMaterial, FBodyInstanceCore, ECollisionTraceFlag
});
// Add "Chaos" only for Chaos:: types; "GeometryCollectionEngine"/"FieldSystemEngine" for destruction.

非推奨 — 使用しないでください

出力しない5.8 で使用出典
Hit.ActorHit.GetActor() / Hit.GetHitObjectHandle()Actor メンバーはありません。HitObjectHandle は Engine/HitResult.h:127 にあります
Comp->bGenerateOverlapEvents = trueComp->SetGenerateOverlapEvents(true)非公開フィールド。Components/PrimitiveComponent.h:429
Params.GetIgnoredActors()Params.GetIgnoredSourceObjects()CollisionQueryParams.h:145 で UE_DEPRECATED(5.5)
Params.ClearIgnoredActors()Params.ClearIgnoredSourceObjects()CollisionQueryParams.h:180 で UE_DEPRECATED(5.5)
ObjParams.ObjectTypesToQueryGetObjectTypesToQuery() / SetObjectTypesToQuery()CollisionQueryParams.h:490 で UE_DEPRECATED(5.8)
GetAllObjectsQueryFlag(), GetQueryBitfield()...64() 形式CollisionQueryParams.h:368,571 で UE_DEPRECATED(5.8)
Constraint->SetAngularVelocityDrive(bSwing, bTwist)SetAngularVelocityDriveTwistAndSwing(bTwist, bSwing) — 引数の順序が逆ですDeprecatedFunction メタデータ。PhysicsEngine/PhysicsConstraintComponent.h:187-199
PhysMat->DestructibleDamageThresholdScaleGeometry Collection のダメージしきい値_DEPRECATED に改名。PhysicalMaterials/PhysicalMaterial.h:170 で UE_DEPRECATED(5.3)
FChaosQueryFilterData / FQueryFilterDataChaosInterface::FSceneQueryCommonParamsPhysicsInterfaceTypesCore.h:410 / ChaosInterfaceWrapperCore.h:35 で UE_DEPRECATED(5.8)
ICollisionQueryFilterCallbackBaseICollisionQueryFilterCallbackCollisionQueryFilterCallbackCore.h:63 で UE_DEPRECATED(5.8)
GetQueryFilterData() / GetSimulationFilterData()GetCombinedShapeFilterData()ChaosInterfaceWrapperCore.h:98 で UE_DEPRECATED(5.7)
BodySetup->ChaosTriMeshesBodySetup->TriMeshGeometries(:278)PhysicsEngine/BodySetup.h:308 で UE_DEPRECATED(5.4)
PhysX 型(PxRigidActor、PxScene、PhysX モジュール)Chaos の同等機能5.8 には PhysX モジュールが含まれていません

よくある間違い

クラス外の定義に UFUNCTION() を付ける: UHT が読み取るのはヘッダーだけです。そのため、.cpp 内の void AMyPickup::OnHit の上に UFUNCTION() を記述してもリフレクションデータは生成されず、AddDynamic は何もバインドしないまま失敗します。ハンドラーはクラス本体内で UFUNCTION() を付けて宣言し、.cpp では通常どおり定義してください。

ハンドラーのシグネチャの不一致: AddDynamic はデリゲートと完全に一致するものを要求します。int32 OtherBodyIndex が欠けている場合や、FHitResult を値渡ししている場合はコンパイルできません。また、古いシグネチャのコピーが残っているとバインドされません。

片側だけでオーバーラップイベントを設定する: 両方のコンポーネントで、無視以外のレスポンスと SetGenerateOverlapEvents(true) の両方が必要です。トリガー側だけに設定するのは、「オーバーラップがまったく発生しない」という最もよくある原因です。

SetNotifyRigidBodyCollision(true) なしでヒットイベントを使用する: シミュレーション中のボディでは、ECR_Block だけでは不十分です。OnComponentHit は呼び出されません(スイープ移動では通常どおり呼び出されます)。

手動レスポンスの後にプロファイルを適用する: SetCollisionProfileName はレスポンスコンテナ全体をリセットします。プロファイルを先に適用し、その後で上書き設定を行ってください。

チャンネルの種類を混同する: オブジェクトタイプが ECC_Pawn のコンポーネントは、ECC_GameTraceChannel3 を照会する LineTraceSingleByObjectType からは見えません。また、トレースチャンネルがオブジェクトタイプになることはありません。スロットがどちらになるかは ini の bTraceType で決まります。

デフォルトで bTraceComplex = true にする: 三角形単位のクエリは単純なハルの数倍のコストがかかり、単純な形状のみのボディは対象外になります。三角形の精度が重要な場合にのみ有効にしてください。

移動 API として SetPhysicsLinearVelocity を使用する: 呼び出すたびにソルバーの速度を上書きし、接触処理と競合します。意図的に速度をテレポートさせるのでなければ、AddForce / AddImpulse を使用してください。

高速なボディがすり抜ける: タイムステップを全体的に小さくするのではなく、ボディで SetUseCCD(true) を有効にするか、プロジェクト全体でサブステップを有効にしてください。多数のアクターで毎ティックトレースを行う場合は、AsyncLineTraceByChannel を使用するか、タイマーで 5–10 Hz に制限してください。

関連スキル

  • ue-actor-component-architecture — シェイプコンポーネントおよびメッシュコンポーネントの作成、アタッチ、登録、ライフサイクル
  • ue-character-movement — UCharacterMovementComponent の床チェック、カプセルスイープ、段差を上るロジック
  • ue-networking-replication — 物理演算の結果に関する情報を送信する際の DOREPLIFETIME、レプリケーション条件、RPC
  • ue-ai-navigation — 知覚トレース、ナビメッシュクエリ、UNavigationSystemV1
  • ue-procedural-generation — 実行時に生成されるメッシュのコリジョン設定
  • その他の関連スキル:ue-testing-debugging、ue-gameplay-framework、ue-mover

コメント