Path/road forming to terrain mesh

I want to implement a way for the player to place (or drag out) a path/road onto a terrain or an undulating mesh. I want the path to stick to the terrain almost as if it was painted on it and still have it as an interactable object (the player should be able to click on it). The path should not deform the terrain, just follow its shape.

I’ve been experimenting with this for a while and ended up with a solution where vertices for both the terrain mesh and the path mesh are aligned to a grid (this grid is also in practice the terrain resolution). The idea is that as long as the height is the same at the grid points the path should align to the terrain. All path vertices that are outside of the grid are set to the same height as the terrain at that point. Although this sort of works, the path still clips through the terrain sometimes, especially at steep slopes.

I’m doubting my implementation is the best way to do this. Does anybody have a suggestion on how to make a path like this? I’m attaching an image of what I have in mind (sort of, I don’t need to have shapes like the path edge, it should just be flat). Thanks!

Unity’s terrain uses dynamic mesh creation as well as (I believe) some type of tweening or bezier-ish filter to generate vertices that lie between the actual heightmap values and give a nice smoothed look. Unless your road does the same, or has enough height slop above the ground, I think that might explain why the terrain comes through for you.

Plus when things are very close you can get an artifact called Z-fighting.

Thank you, that makes sense. However, I am not using Unity Terrain. Instead, I am generating my own mesh, with vertices set to every grid step and setting the vertices y-pos to make hills and such.

Perhaps it is Z fighting… does it get worse the farther you get away from the road / terrain overlay?

No, it is not z-fighting either. The path mesh gets under the terrain mesh if the terrain is steep or very uneven. I think what I am really asking is if my implementation makes sense. I am doubting it is the best way to do this.

As @Kurt-Dekker suggested it may be Z fighting - this is solved somewhat by using an offset from the surface (i.e. if your surface is at 40.0f, your matching path y should be at 40.05f - or whatever is imperceptible for the distance you’re viewing it from without looking like it’s floating above it). There’s also the situation where you might have vertices of the terrain between the points of your path that are higher than both, so for example each side is perfectly aligned, but in the middle there’s part of the terrain that’s slightly higher than both sides are. This is more complicated to solve, requiring either A) more vertices between them / sideways across the path, causing noticeable issues with smoothing of normals making it look less like a path and more like painted terrain if do that because the “flatness” is variable, B) you’ll need to come up with a solution that won’t work well in real time / you’ll have to generate the path in the editor, because you’ll need to sample height at a higher resolution across it and then calculate necessary height for each side in order to make sure the problematic point between them won’t be higher, or C) having sides to your path like the image has - since it obscures the view and your path can easily have a much greater offset to solve this without needing more vertices or more processing. Most likely you’ll find that C is the realistic approach - having a thickness to the path you can increase until there’s nothing sticking through, with sides extending down from the edges of the path to/into the terrain.

If you are only putting road vertices where you have your terrain vertices, and you are always offsetting upwards, your implementation makes sense.

Keep in mind though that the steeper the slope, the less that axis-aligned gap gets, as a function of (I think) the cosine of the slope angle. I might have that term wrong, but obviously it gets closer together, and you do indicate above that is precisely where you are seeing the problem.

Another way to isolate if it is z fighting is to move the near clip plane of the camera much further away than the default 0.3… that will drastically increase effective bitdepth resolution for your Z buffer. Try perhaps setting the camera clip planes to 10, 1000 and seeing if you see the issue. Obviously this means you must be at least 10m above the ground, but just for testing it will prove the z-fighting issue.

Thank you for your help! I’ll try to refine the solution I have at the moment to see if I can make it perform better. I will check how much z-fighting is causing issues.

Do you know if it is possible to generate a decal from a mesh and paint it on a surface in Unity? I’ve been thinking if that would be a solution as well.

Anything is possible; it’s a case of is it practical to engineer, support, and will it be performant enough. I have not done anything with decals beyond bullet holes, so you would be the person best suited to investigation.