ue-physics-collision について
Unreal Engine 5.8 開発者向けの物理・コリジョンスキルです。クエリ、コリジョンイベント、剛体、Chaos の設定を、現行ヘッダーに基づいて解説します。
主な機能
- 01コリジョンチャンネルとプロファイル
- 02トレース、スイープ、オーバーラップクエリ
- 03FHitResult のヒット情報
- 04コリジョンとウェイクイベント
- 05剛体、力、物理マテリアル
- 06Chaos ソルバーとネットワーク物理
活用シーン
- 01オブジェクトとトレースチャンネルの設定
- 02ヒット、インタラクション、範囲判定の実装
- 03コンポーネントの重なりや衝突への対応
- 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 に記載されています。
| デリゲート | パラメーター |
|---|---|
FComponentHitSignature | UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit |
FComponentBeginOverlapSignature | UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult |
FComponentEndOverlapSignature | UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex |
FComponentWakeSignature/FComponentSleepSignature | UPrimitiveComponent* WakingComponent(SleepingComponent)、FName BoneName |
FActorBeginOverlapSignature/FActorEndOverlapSignature | AActor* OverlappedActor, AActor* OtherActor |
FActorHitSignature | AActor* 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] にあります。
| 設定 | ヘッダー | 説明 |
|---|---|---|
DefaultGravityZ | PhysicsSettingsCore.h:25 | ワールドの重力。デフォルトは -980 です |
BounceThresholdVelocity | :79 | この値を下回ると、反発係数は適用されません |
MaxDepenetrationVelocity | :95 | 押し出し速度の上限です。0 は無制限です |
bSimulateSkeletalMeshOnDedicatedServer | :114 | オフにすると、サーバーでラグドールの負荷を抑えられます |
DefaultShapeComplexity | :119 | プロジェクト全体に適用される ECollisionTraceFlag です |
SolverOptions | :123 | FChaosSolverConfiguration |
bSubstepping / MaxSubstepDeltaTime / MaxSubsteps | PhysicsSettings.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.Actor | Hit.GetActor() / Hit.GetHitObjectHandle() | Actor メンバーはありません。HitObjectHandle は Engine/HitResult.h:127 にあります |
Comp->bGenerateOverlapEvents = true | Comp->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.ObjectTypesToQuery | GetObjectTypesToQuery() / 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->DestructibleDamageThresholdScale | Geometry Collection のダメージしきい値 | _DEPRECATED に改名。PhysicalMaterials/PhysicalMaterial.h:170 で UE_DEPRECATED(5.3) |
FChaosQueryFilterData / FQueryFilterData | ChaosInterface::FSceneQueryCommonParams | PhysicsInterfaceTypesCore.h:410 / ChaosInterfaceWrapperCore.h:35 で UE_DEPRECATED(5.8) |
ICollisionQueryFilterCallbackBase | ICollisionQueryFilterCallback | CollisionQueryFilterCallbackCore.h:63 で UE_DEPRECATED(5.8) |
GetQueryFilterData() / GetSimulationFilterData() | GetCombinedShapeFilterData() | ChaosInterfaceWrapperCore.h:98 で UE_DEPRECATED(5.7) |
BodySetup->ChaosTriMeshes | BodySetup->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、レプリケーション条件、RPCue-ai-navigation— 知覚トレース、ナビメッシュクエリ、UNavigationSystemV1ue-procedural-generation— 実行時に生成されるメッシュのコリジョン設定- その他の関連スキル:
ue-testing-debugging、ue-gameplay-framework、ue-mover