Claude
Skills
Sign in
Back

ue-physics-collision

Included with Lifetime
$97 forever

Use when implementing collision detection, trace queries, physics simulation, or physical interactions in Unreal Engine. Triggers on: 'collision', 'trace', 'LineTrace', 'line trace', 'overlap', 'physics', 'hit result', 'sweep', 'collision channel', 'physics body', 'Chaos', 'raytrace', 'OnHit', 'OnBeginOverlap'. See related skills for component architecture and AI navigation.

Design

What this skill does


# UE Physics & Collision

You are an expert in Unreal Engine's physics and collision systems, including collision channels, trace queries, collision events, physics bodies, and the Chaos physics engine.

---

## Step 1: Read Project Context

Read `.agents/ue-project-context.md` to confirm:
- UE version (Chaos is the default physics backend from UE 5.0; PhysX was deprecated)
- Which modules need `"PhysicsCore"` and `"Engine"` in their `Build.cs`
- Whether the project uses skeletal meshes with physics assets, or primarily static mesh collision
- Dedicated server targets (affects whether physics simulation should run server-side)

---

## Step 2: Identify the Need

Ask which area applies if not stated:
1. **Collision setup** — channels, profiles, responses on components
2. **Trace queries** — line traces, sweeps, overlap queries for gameplay logic
3. **Collision events** — OnComponentHit, OnBeginOverlap, OnEndOverlap delegates
4. **Physics simulation** — rigid body sim, forces, impulses, damping, constraints
5. **Physical materials** — friction, restitution, surface type detection

---

## Collision Channels & Profiles

### ECollisionChannel — built-in channels

```cpp
ECC_WorldStatic, ECC_WorldDynamic, ECC_Pawn, ECC_PhysicsBody,
ECC_Vehicle, ECC_Destructible               // object channels (what an object IS)
ECC_Visibility, ECC_Camera                  // trace channels (used for queries)
// Custom: ECC_GameTraceChannel1..ECC_GameTraceChannel18
```

**Responses**: `ECR_Ignore` / `ECR_Overlap` (events, no block) / `ECR_Block` (physical block + events).

**Built-in profiles**: `BlockAll`, `BlockAllDynamic`, `OverlapAll`, `OverlapAllDynamic`, `Pawn`, `PhysicsActor`, `NoCollision`.

### Setting Collision in C++

```cpp
MyMesh->SetCollisionProfileName(TEXT("BlockAll"));        // preferred — sets all at once
MyMesh->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
// ECollisionEnabled: NoCollision | QueryOnly | PhysicsOnly | QueryAndPhysics
MyMesh->SetCollisionObjectType(ECC_PhysicsBody);
MyMesh->SetCollisionResponseToAllChannels(ECR_Block);
MyMesh->SetCollisionResponseToChannel(ECC_Pawn, ECR_Overlap);
MyMesh->SetCollisionResponseToChannel(ECC_Camera, ECR_Ignore);
```

### Object Type Channels vs Trace Channels

**Object type channels** describe what an actor IS (Pawn, WorldDynamic, Vehicle). Every component has exactly one object type. **Trace channels** are used for queries — they define what a trace is LOOKING FOR (Visibility, Camera, Weapon). This distinction determines which query function to use: `ByObjectType` matches the target's object type channel; `ByChannel` uses the querier's trace channel and checks responses. Most gameplay traces use trace channels (`ECC_Visibility`, custom `Weapon`); overlap queries for "find all pawns" use object type (`ECC_Pawn`).

### Custom Channels — DefaultEngine.ini

```ini
[/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="Interactable",CollisionEnabled=QueryAndPhysics,ObjectTypeName="Interactable",CustomResponses=((Channel="Weapon",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Block)))
```

`bTraceType=True` = trace channel; `bTraceType=False` = object type channel. They use separate query functions.

See `references/collision-channel-setup.md` for full profile examples.

---

## Trace Queries

### FCollisionQueryParams

```cpp
FCollisionQueryParams Params;
Params.TraceTag                = TEXT("WeaponTrace"); // for profiling/debug
Params.bTraceComplex           = false;  // false=simple hull (fast); true=per-poly (expensive)
Params.bReturnPhysicalMaterial = true;   // populates Hit.PhysMaterial
Params.bReturnFaceIndex        = false;  // expensive, only when needed
Params.AddIgnoredActor(this);
Params.AddIgnoredComponent(MyComp);
```

### World-Level Trace Functions (C++) — from `WorldCollision.h` via `UWorld`

```cpp
FHitResult Hit;
// By trace channel
GetWorld()->LineTraceSingleByChannel(Hit, Start, End, ECC_Visibility, Params);
GetWorld()->LineTraceMultiByChannel(Hits, Start, End, ECC_Visibility, Params);
// By object type
FCollisionObjectQueryParams ObjParams(ECC_PhysicsBody);
ObjParams.AddObjectTypesToQuery(ECC_WorldDynamic);
GetWorld()->LineTraceSingleByObjectType(Hit, Start, End, ObjParams, Params);
// By profile
GetWorld()->LineTraceSingleByProfile(Hit, Start, End, TEXT("BlockAll"), Params);
```

### Sweep Queries — FCollisionShape (from `CollisionShape.h`)

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

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

### Overlap Queries

```cpp
TArray<FOverlapResult> Overlaps;
GetWorld()->OverlapMultiByObjectType(Overlaps, Center, FQuat::Identity,
    FCollisionObjectQueryParams(ECC_Pawn), FCollisionShape::MakeSphere(500.f), Params);
for (const FOverlapResult& R : Overlaps) { AActor* A = R.GetActor(); }

// By trace channel (uses channel responses, not object type matching):
GetWorld()->OverlapMultiByChannel(
    Overlaps, Center, FQuat::Identity, ECC_Pawn,
    FCollisionShape::MakeSphere(Radius), QueryParams);
```

### FHitResult — Key Fields

```cpp
Hit.bBlockingHit;          // true if blocking
Hit.ImpactPoint;           // world space contact point
Hit.ImpactNormal;          // surface normal
Hit.Distance;              // from Start to impact
Hit.BoneName;              // skeletal mesh bone
Hit.GetActor();
Hit.GetComponent();
// Physical material (requires bReturnPhysicalMaterial=true):
if (UPhysicalMaterial* M = Hit.PhysMaterial.Get())
    EPhysicalSurface S = UPhysicalMaterial::DetermineSurfaceType(M);
```

### Blueprint-Layer Traces (UKismetSystemLibrary)

```cpp
#include "Kismet/KismetSystemLibrary.h"
TArray<AActor*> Ignore = { this };
// LineTrace with debug draw (ETraceTypeQuery maps to ECollisionChannel)
UKismetSystemLibrary::LineTraceSingle(this, Start, End,
    ETraceTypeQuery::TraceTypeQuery1, false, Ignore, EDrawDebugTrace::ForDuration, Hit, true);
// SphereTrace
UKismetSystemLibrary::SphereTraceSingle(this, Start, End, 50.f,
    ETraceTypeQuery::TraceTypeQuery1, false, Ignore, EDrawDebugTrace::ForOneFrame, Hit, true);
// By profile
UKismetSystemLibrary::LineTraceSingleByProfile(this, Start, End,
    TEXT("BlockAll"), false, Ignore, EDrawDebugTrace::None, Hit, true);
```

### Async Traces

```cpp
FTraceHandle Handle = GetWorld()->AsyncLineTraceByChannel(
    EAsyncTraceType::Single, Start, End, ECC_Visibility, Params);
// Read next frame:
FTraceDatum Datum;
if (GetWorld()->QueryTraceData(Handle, Datum) && Datum.OutHits.Num() > 0)
    FHitResult& Hit = Datum.OutHits[0];
```

### Debug Visualization

```cpp
#if ENABLE_DRAW_DEBUG
DrawDebugLine(GetWorld(), Start, End, FColor::Red, false, 2.f);
DrawDebugSphere(GetWorld(), HitResult.ImpactPoint, 10.f, 12, FColor::Green, false, 2.f);
#endif
```

`DrawDebugLine` / `DrawDebugSphere` are from `DrawDebugHelpers.h`. Wrap in `ENABLE_DRAW_DEBUG` so they compile out in shipping builds. The bool param is `bPersistentLines`; the float param is `LifeTime` in seconds.

See `references/trace-patterns.md` for full gameplay patterns (hitscan, melee sweep, AoE, ground detection, async sensors).

---

## Collision Events

Delegate declarations from `PrimitiveComponent.h`:
- `OnComponentHit` — `(HitComp, OtherActor, Oth

Related in Design