Newly duplicated geometry in the editor isn't traceable until the level is reloaded

Summary

In UE 5.8, actors added to a level after it loads (duplicate, paste, drag-in) are invisible to editor-world scene queries (LineTraceSingleByChannel etc.) until the map is reloaded, even though their physics bodies exist and are valid — breaking any editor tooling that traces against level geometry.

What Type of Bug are you experiencing?

Editor

Steps to Reproduce

  1. Create or open a level containing a static mesh actor (e.g. any engine cube/floor mesh with default BlockAll/QueryAndPhysics collision). Save and reopen the level.
  2. In the editor (no PIE), run a line trace against the editor world on the Visibility channel through that actor — e.g. via an Editor Utility Blueprint or Python. It hits, as expected.
  3. Duplicate the actor (Alt-drag or Ctrl+D) and move the duplicate aside.
  4. Trace through the duplicate the same way.
  5. Actual: the trace passes straight through the duplicate (no hit; or it hits whatever is behind it). Expected: it hits the duplicate.
  6. Save and reload the map → the same trace now hits the duplicate.

Expected Result

newly duplicated assets added into the level editor should be traceable. I suspect this will impact other level editor plugins that might trace against scene geometry.

Observed Result

Additional observations (from debugging an editor plugin that traces)

The affected actors’ physics state looks completely healthy at the component level. Logged at the moment a trace passed through such an actor:

  • UPrimitiveComponent::IsPhysicsStateCreated() = true
  • IsAsyncPhysicsStateCreated() = true
  • FBodyInstance::IsValidBodyInstance() = true
  • GetCollisionEnabled() = QueryAndPhysics
  • FBodyInstance::GetPhysicsScene() == the traced world’s FPhysScene (pointer-identical)
  • Same world for actor and trace

So the body exists, is valid, and is registered in the very scene being queried — the defect is at the scene-query/acceleration-structure or shape-query-flag level.

Also observed:

  • PIE is unaffected — a character collides with the duplicates normally (PIE world re-creates physics state on init).
  • FChaosScene::Flush() does not cure it (called on the editor scene from the game thread; it pushes dirty proxies, FlushSpatialAcceleration, and copies the structure — the actor stays query-invisible).
  • FPhysScene_Chaos::ProcessAsyncPhysicsStateJobs(true) does not cure it (queue is already empty by the time it runs; GetSolver() is valid).
  • UPrimitiveComponent::RecreatePhysicsState() cures it permanently for that component (followed by a Flush). This is presumably why a map reload fixes everything: load creates physics state through the synchronous path.

Suspected mechanism (for triage; unverified)

The 5.6+ async physics-state creation machinery looks involved:

  • Chaos::CVars::bEnableAsyncInitBody (p.Chaos.EnableAsyncInitBody, registered in Runtime/Experimental/Chaos/Private/Chaos/AsyncInitBodyHelper.cpp) gates FPhysScene_Chaos::SupportsAsyncPhysicsStateCreation().
  • The async job queue (FPhysScene_AsyncPhysicsStateJobQueue) is pumped from level streaming (ULevel) — an interactive editor session appears to have no equivalent pump.
  • Bodies created through this path in an editor world end up flagged IsAsyncPhysicsStateCreated() == true yet never become visible to scene queries; the synchronous path (used at load, and by RecreatePhysicsState) produces query-visible bodies.

Note: the cvar’s code default is false and it is not set in our engine/project config, yet duplicated actors on a stock 5.8.1 launcher install still take the async-flagged path — so either something enables it internally in 5.8, or the flag’s semantics differ from its name.

Impact

Any editor tooling that line-traces or sweeps against the editor world silently fails for actors placed since the level loaded: editor-mode plugins, snapping/measurement tools, procedural placement utilities, editor utility blueprints. The failure is especially confusing because traces can hit whatever is behind the new actor, producing wrong results rather than obvious misses.

Workarounds found

  • Per component: RecreatePhysicsState() on the affected UPrimitiveComponent, then FChaosScene::Flush() — restores query visibility permanently for that component.
  • Whole map: save and reload the level.

Affects Versions

5.8

Platform(s)

Windows