Trace for Objects - BlockingHit is always true

If you perform a trace for objects and a hit is received, BlockingHit is True even if the actor that was hit blocks nothing.

For example, if you do a “Sphere Trace For Objects” inside a TriggerVolume, and you include WorldDynamic in Object Types, it will return a hit on the TriggerVolume actor as expected, but BlockingHit will be True, even though TriggerVolume doesn’t block anything in it’s collision properties:

[Here’s a test map][2] in 4.17 for reproducing that.

You can use TraceForChannel against the “Visibility” channel for most things, but sometimes you need to Trace For Objects so it would be great if this flag worked (unless I’m misunderstanding what BlockingHit means).

Hi there,

It’s possible that the trace is hitting a component on the object it is originating from. Are there any meshes attached to the trigger volume? Try checking the “Ignore Self” flag on the trace and see if that does it. Alternatively, you can make an array and plug in any actors you want to ignore in the Actors to Ignore pin.

Another thing to try is to pull the hit actor pin from the hit result, get the name and print it. That should at least tell you what it is hitting.

I hope this helps!

Thanks for the time, but it only returns one hit and that is the TriggerVolume (besides, the above example map is tracing from a level blueprint, there is no Self to hit).

I’m fairly certain it’s either a bug, a misunderstanding of the BlockingHit flag, or possibly that return flag was intentionally disabled as an optimisation

Gotcha. I opened up your map in 4.17 and here’s what i did to get it working. The volume is in fact triggering the trace because it’s tracing for WorldDynamic, which is the default collision preset for trigger, and the Trace is not originating a from the volume itself, so i plugged the pin for the trigger volume in the level blueprint into Actors to Ignore, and now I’m getting false for bBlockingHit

Alternatively, changing the object type in the trigger volume’s collision settings to anything other than world static or world dynamic seems to do the trick.

Thanks for your time again, but I think I should clarify the bug a bit more.

The reason you get BlockingHit returning false with your modifications is because the trace doesn’t hit anything at all.

The trace is meant to return a hit with the TriggerVolume (because it’s a WorldDynamic object, and we’re tracing for WorldDynamic objects), but BlockingHit should be false, because it’s not a Blocking Hit… (but it’s still a hit). The volume doesn’t block anything, but it overlaps and can still be queried with a trace.

Say you want to do a multi-trace against a bunch of WorldDynamic objects, but you want to do different things depending on whether they’re blocking hits or not. You might be able to get around it for each case by using TraceForChannel, and/or adding a custom collision channel for your project, but that is more complex, time consuming and error prone. I’ve run into this a couple of times on different projects now so figured it’s worth bringing up, because if all hits on a particular TraceForObjects call are going to be blocking, or all hits are non-blocking, then the flag seems pointless.

Ran into this myself and haven’t found anyone answering this. Object traces don’t have a notion of overlap vs blocking. It kinda makes sense, what would it check? It seems like it would be object response, but remember that’s how other objects respond to it. So it’s not the same as trace channels. Here’s the relevant code in CollisionQueryFilterCallback.cpp

const uint32 ShapeBit = ECC_TO_BITFIELD(ShapeChannel);
	if (QueryType == ECollisionQuery::ObjectQuery)
	{
		const int32 MultiTrace = (int32)QuerierChannel;
		// do I belong to one of objects of interest?
		if (ShapeBit & QueryFilter.Word1)
		{
			if (bPreFilter)	//In the case of an object query we actually want to return all object types (or first in single case). So in PreFilter we have to trick physx by not blocking in the multi case, and blocking in the single case.
			{

				return MultiTrace ? ECollisionQueryHitType::Touch: ECollisionQueryHitType::Block;
			}
			else
			{
				return ECollisionQueryHitType::Block;	//In the case where an object query is being resolved for the user we just return a block because object query doesn't have the concept of overlap at all and block seems more natural
			}
		}
	}

In other words, object traces will always return hitresults with IsBlocking set to true.

Not that the behaviour is exclusive, but the blocking/non blocking is a purview of the trace by channel system.

Thats because in theory the object trace will return any object in its path.

The channel system will not flag a hit on an object who’s settings are such as not to flag the hit.

Open the trace object blueprint node in visual studio or any c++ editor to read how the code handles things.
Potentially, you could copy over the function to your own plugin and make modifications to add a working block result that matches the collision settings (by just testing the settings before assinging the bool).

Note:
The hit result is a standard steucture, so it contains parameters which may not necessarily be set in the code that gets you that return value.
That is likely what is going on here.

I’d suggest just merging your own custom version of the 2 traces to use in BP as you need…