Stick to the ground

Terrain correlation is always a pain. I’m receiving object locations from various external sources and there is an offset of a few metres. Each source has a slightly different height map meaning some objects appear as flying on top of the ground and others are under the ground.

Is there a way to force my objects to appear on the ground no matter the elevation?

Thanks,

I had a similar problem. I ended up using the LineTraceForObjects function.

You start with your object’s position, then you shoot a ray downward until you hit the ground, then you take that location and set it to your object’s location.

There’s an additional complication with this, because the earth tiles load in different LOD’s depending on how far away you are. This affects collisions also. This means that your object could be on the ground in one LOD, but not in the ground on another LOD. I’m not sure if there’s a way to handle this without checking every frame, but that’s what I had to do. I was able to get very reliable results using this. You just need to make sure you handle the case when the tile is completely removed because of camera culling.

The Cesium plugin has a bug right now, so the world’s collision is hard coding itself to WorldDynamic, so change that to WorldStatic when the plugin updates.

1 Like

Thanks for your reply. The same can be achieve from C++

TArray<TEnumAsByte<EObjectTypeQuery>> TraceObjects;
				TraceObjects.Add(UEngineTypes::ConvertToObjectType(ECC_WorldStatic));//add your object types here.
				TraceObjects.Add(UEngineTypes::ConvertToObjectType(ECC_WorldDynamic));//add your object types here.
				    FHitResult FirstHit(ForceInit);
    				TArray<AActor*> ActorsToIgnore;
    				ActorsToIgnore.Add(NULL);

    				if (UKismetSystemLibrary::LineTraceSingleForObjects(Engine->GetWorld(), startPos, FVector(0,0,-20000000), TraceObjects, false, ActorsToIgnore, EDrawDebugTrace::Persistent, FirstHit, false))
    				{
    					//collision detected
    				}

I tested it and it works well.

1 Like

Hey @jplebel, when I try to do SphereTraceSingleForObjects, I only get collision hits from static meshes I have placed into the level and none from Cesium landscape. However, if I run the blueprint equivalent function, it works on the Cesium landscape. I believe that the function is probably run before the landscape is loaded up on Play.

Had to add a timer in C++ to call the function after 3 seconds, thus the Cesium Landscape is loaded by them and it runs.
Code:
FTimerHandle handle;
float Delay = 3;
bool Loop = false;
GetWorldTimerManager().SetTimer(handle, this, &MyClass::MuFunction,Delay ,Loop);