Prevent FollowerEntity snapping to graph surface

Hi Aron, I’m trying to get the FollowerEntity working with physics for simulating buoyancy. There seems to be a particular problem, when the entity get’s below the graph surface. It starts jittering all around, apparently the gravity trying to pull it down and some other force tries to snap it back to the graph surface. I didn’t see a setting how to deactivate this snapping for FollowerEntities (like constrainInsideGraph?). Any idea, what can be done here?

Here the long story, if it matters:
I baked the FollowerEntity to pure ECS and using the new ECS Unity.Physics package, handling gravity, buoyancy and movement forces. I deactivated the SimulateMovementFinalize component, as you suggested in another post, to let physics handle the movement of the entity. This generally works fine as long as the entity is above or on the same level as the navmesh surface. But when the ocean waves create a valley and the boat would be pulled by gravity below the the navmesh graph surface, it starts flickering around, as if something in the pathfinding tries to snap it back up. If pathfinding is deactivated, this does not happen, so it’s definitely due to some system interacting.
Here an image to illustrate the problem:

I realized it’s not really dependent on physics or gravity.

Even using the normal FollowerEntity Gameobject without any physics and deactivating gravity on it, snaps it to the navmesh surface if it is below the surface. While the FollowerEntity has no problem floating some distance above the navmesh (gravity deactivated), as soon as one tries to place it below it, it snaps it upwards.

I don’t know if this behavior is intended or a bug, but in the first case it should be optional. If the agent can be able to float above the navmesh, it should also be able to float below it (at least if gravity is deactivated).


This is working as designed. The relevant function is JobControl.ClampToNavmesh.
I have done this because this typically happens when an agent has fallen off the world or some other strange thing.

For this use case, I would actually recommend that you set ai.updatePosition = false; ai.updateRotation = false; and then every frame you can get the agent’s internal position and rotation and modify it based on boyancy and maybe even rotate the ship to follow the waves:

void LateUpdate () {
    transform.position = ai.position + boyancyDelta;
    transform.rotation = ai.rotation; // Optionally modify rotation too

Thanks Aron, but I’m not using GameObjects, I’m using the entities directly so just skipping the transform update won’t work.

I understand the reason for calling ClampToNavmesh, but I keep thinking that it should be optional or tied to gravity being enabled. If there is no gravity, agents also should not fall from the navmesh theoretically. For safety reasons and to not break other peoples projects, an additional parameter could be introduced though:
Either a simple boolean (ClampToNavmesh yes/no) or a float with a distance check (Clamp if distance to Navmesh < - 10f) would be highly appreciated.

If I have a look at the ClampToNavmesh function:
JobControl->ClampToNavmesh, this line:
currentElevation = math.max(currentElevation, clampedElevation - shape.height * 0.4f);
seems to be responsible for the y axis min clamping.

Maybe instead of hard coding this to shape.height, some more options for controlling this behavior could be introduced?
For example something like:

public struct ClampingOptions{
public bool ClampToSurface; //default true - controls if general clamping should be applied
public bool ClampYAxisToSurface; //default true - controls if Y Axis clamping should be applied
public float ClampYAxisMinDistance; //default 0.4f * shape.height - controls how far the entity can be below the surface until it snaps up again

Sorry for being annoying, it’s just this issue keeps me stuck at some point :wink: