Collision and Trace Contract
Collision configuration in UE5 has a property that makes it unusually easy to get wrong: it is global, shared, and mostly invisible from the code that depends on it. A query in one file behaves the way it does because of a channel definition in project settings and a response set on a component in a different asset. None of the three references the others, and all three have to agree.
The consequences are the two complaints that dominate hit-detection debugging — "the trace returns nothing" and "the trace hits things it should not" — and both are usually correct code running against a configuration nobody wrote down.
The second failure is worse and quieter: a fast object passing through thin geometry, which is not a configuration problem at all but a query-type problem, and which reproduces only at speed.
Settle the hit contract first
- Define what a hit means for each interaction before choosing an API. What is being asked, what may answer, and what the answer authorizes. A trace is a question; most trace bugs are a well-formed answer to the wrong question.
- Write down the channel semantics. Two different kinds of channel exist and they
answer different questions — an object channel says what a thing is, a trace channel
says what a query is looking for. Confusing them is the single most common
configuration error. See
references/channel-semantics.md. - Never reuse a general-purpose channel for a gameplay decision. Visibility and camera channels exist, are always available, and mean something else. Borrowing one couples your hit logic to rendering and camera concerns permanently.
- Treat the response matrix as shared state with an owner. Every channel added is a column every existing object must have an opinion about. Changing one response can alter behavior in systems that never mention it.
- Choose the query type from speed and size, not from convenience. A line has zero
thickness and objects move in discrete steps; both facts produce misses that look like
configuration bugs. See
references/query-selection.md. - Name one system as the hit authority for each interaction. Two systems independently
querying will eventually disagree, and the disagreement surfaces as an intermittent
gameplay inconsistency. See
references/hit-authority.md.
Load only what applies:
references/channel-semantics.md— object vs. trace channels, defining project channels, and the response matrix as a shared resource.references/query-selection.md— line, sweep, and overlap; tunnelling; complex vs. simple geometry; multi-hit handling.references/hit-authority.md— one decider per interaction, and reconciling systems that need to know about the same hit.
Required answer format
When this skill fires, return:
- Interaction table — interaction | what is asked | who may answer | what the answer authorizes.
- Channels — every channel used, its type (object or trace), its project meaning, and its default response.
- Matrix changes — any response altered, and which existing systems that affects.
- Query choice — line / sweep / overlap per interaction, with the speed and size that justified it, including the computed per-step displacement.
- Hit authority — the single system deciding each interaction, and how others learn.
- Not verified — channels or responses you could not confirm in project settings.
Hard rules
- Never make a gameplay decision on a general-purpose visibility or camera channel. Define a project channel with a written meaning.
- A channel without a documented meaning does not exist as far as this project is concerned. Record it in the project context file or do not add it.
- Never use a line trace for an object whose per-step displacement exceeds the thickness of what it must not pass through. Compute the displacement; do not estimate it by eye.
- Both sides must agree. A response is a pair — changing one component's response to a channel without checking the other side produces an interaction that works in one direction only.
- Adding a channel is a project-wide change requiring a stated default for existing objects. It is never a local edit, however local the motivating bug was.
- One authority per interaction. Other systems observe the result; they do not re-query and form their own opinion.
Verification
Displacement check. For every fast-moving object, compute speed × step_size and compare
it to the thinnest geometry it must not pass through. If displacement exceeds thickness, a
line trace will miss — not intermittently, but whenever the step lands wrong. This is
arithmetic, not a test, and it is the cheapest bug prevention in this skill.
Matrix snapshot. Keep the collision settings under version control and diff them on every change. A response flipped by accident is invisible in a code review and produces a bug in a system that was not touched.
Query census. Periodically list every query in the codebase with its channel and type. Two queries asking the same question with different channels is a contract violation that has not caused a visible bug yet.
Seeded hit-count assertion. In a seeded headless run
(ue5-deterministic-sim-tests), assert that hit counts and hit identities are stable across
runs. Collision non-determinism usually means multi-hit results are being consumed in an
unstable order.
Scope
This skill covers what counts as a hit and how it is asked for. It does not cover physical response after contact — impulses, restitution, constraints — nor damage or effect application, which begins after the hit is decided.
It does not cover networked hit validation, where the question becomes which machine's answer counts. That is a different problem built on top of this one.