Determining "wall", "floor" and "ceiling" based on a slope angle and direction of normals?

How would you go about tracing into the world and determining where the hit is on the “floor”, a “wall” or “ceiling” ?

For example if the surface is either flat or up to a 35 deg. slope, it would be considered a “floor”, if the slope is at more than 35 deg. - “wall” and I am guessing if surface normal is -Z (regardless of the slope) it would be “ceiling”.


You cannot do one point normal. Because if you hit something like pipe or some decorations, normal of single point may be totally different than average normal of mesh.
You could instead do multiple normal traces (for eg 4x4 grid, and 16 traces), then get average vector of it.
Or trace location of 3 points on surface of mesh, then make cross product of any 2 vectors made from that 3 points. This will tell you what is normal to surface mede by those 3 points.

Then for guessing angle between that normal and UP direction do DOT product. It will give you cosinus of angle between those 2 directions.

The idea is to ignore any and all decorations. Only “world” surfaces should be valid surfaces (I am guessing I could use physics material type to filter that). So any pipes, chairs, tables, etc. should be ignored.

Then do line trace for collision only, not for visible chanel. And make all meshes with proper collision.
Thinking of it even if you do very clean collision and later you or your level designer will stack up few random rocks, you will get same undesired “random normal” effect.

Just imagine placing 9 of exactly same cubes in one spot with random rotation. You will get spikes that may have normal pointing into half of sphere.

Why would I get it, if only actual floor would have physical surface type, and rocks won’t ? Isn’t there a way to filter trace hit by physics material type ? Add new surface type to the material used on the floor and then do something like if (type == “solid” ), but in BP ? This way when trace hit the rocks, it would just ignore them since they don’t have surface type “solid”.

This kind of surface type I am talking about: Add a Surface Type | Unreal Engine Documentation

Yes you can filter hit results by physics material.

But later you or your level designer will want to add more shapes everywhere. Line trace will get only what is on top it will not go trough those shapes down to your physics material. Well theoretically you can do multi line trace there to get deeper, but that means levels need double geometry everywhere. It kind of doubles work needed to make levels, and in return you get a bit less code in one function.

Oohh, I see. So there is no way to trace all the way through ?

Not quite understanding, sorry. Why would I need to double geometry ?

About double geometry:
moment you add more detailed geometry, normal at some random point above “flat” ground may be quite random. Imagine you dropped some M&Ms on flat desk. Now what happens if you try to see direction of normal to desk surface if you choose side of candy? That normal will not be facing up, it will face to the side and be normal of that M&M candy not normal of a desk. Now if you make hovercraft that uses single normal, it would just do barrel roll above each candy.

With single line trace you need to trace only DESK surface. but what if you made wall just of M&Ms, and there would be no flat surface behind it? Every single normal you check would point in random direction from half of sphere.

So your choices are:

  • do 3 points tracing, use my idea of cross product from 3 location.
  • do single line trace, use normal. But make double geometry and trace only to “flat” surfaces.
  • or do just single line trace and have errors with normal.

I get it about M&Ms, but still don’t get “double geometry”.

Here is what I am thinking (never mind MS Painter):

Can we do such trace in UE4 (that penetrates all objects on its way) ? If we can, then this is what I am thinking - trace, filter hits by physics surface type, then do dot product on hit #3 (since M&Ms will be filtered out as they don’t have any physics surface type defined, hit #1 and hit #2 will be dismissed).

Is it not possible?

Instead of a physics material, use a custom line trace channel, set to ignore by default. On the meshes you want to check block this trace channel.

Is “multi line trace” what youre looking for?

Is it more straight forward than with physics surface type?

How do I create custom line trace channel ?

Do you mean to check “block this trace channel” for the meshes I need trace to hit on? (floors basically)

Yes, I think that’s what I need. Thanks!

Just need to figure out how to filter trace hits by either physics surface type of by what FrederickD said.

Theres a version that returns an array of hit objects. I guess just run a “find” (or I guess a custom forEach) for the object class you need at pull out its hit location.

Actually, I don’t even need to do multitrace. If I get a hit on something that isn’t floor, then automatically it’s INVALID. So if I hit M$Ms candy, then it’s not floor, thus INVALID.

I probably should also check if there is enough room around where trace hits (needs to be larger than player’s bounds).

To set up a custom trace channel see collision tab in project settings, then you will find it in the collision settings for your actor, and you can choose this custom channel in your line trace node.

Thanks, I’ll check it out.

The reason I wanted to use material surface type is that if I have a trail on a terrain, I’d want to only get valid hits on that trail. I am not sure it would be possible with custom trace channel for whole mesh.

Btw, does trace hit returns world location ? Hmm… I see that Break Trace Results node has Location. Gotta be the world location, right ?

Yup. It returns null if no hit was registered though so make sure to take that into consideration when building your code.

Break hit result node returns the physical material so that works together with line traces too.

It might still be buggy (see here, and here) with landscapes though, would need to test.

I think that’s a bit over my head right now :slight_smile: I am just starting messing with UE4 :slight_smile: