we are using ECS, wrote our own baker
using Pathfinding.ECS;
using Pathfinding.ECS.RVO;
using Pathfinding.PID;
using Pathfinding.RVO;
using Unity.Collections;
using Unity.Entities;
using Unity.Mathematics;
using Unity.Transforms;
using UnityEngine;
using DestinationPoint = Pathfinding.ECS.DestinationPoint;
using MovementControl = Pathfinding.ECS.MovementControl;
public struct FollowerEntityBody : IComponentData {
public float velocity;
public float remainingDistance;
public float3 previousPosition;
}
public class FollowerEntityAuthoring : MonoBehaviour {
[SerializeField] AgentCylinderShape shape = new AgentCylinderShape {
height = 2,
radius = 0.5f,
};
[SerializeField] MovementSettings movement = new MovementSettings {
follower = new PIDMovement {
rotationSpeed = 600,
speed = 5,
maxRotationSpeed = 720,
maxOnSpotRotationSpeed = 720,
slowdownTime = 0.5f,
desiredWallDistance = 0.5f,
allowRotatingOnSpot = true,
leadInRadiusWhenApproachingDestination = 1f,
},
stopDistance = 0.2f,
rotationSmoothing = 0f,
groundMask = -1,
isStopped = false,
};
[SerializeField] OrientationMode orientation = OrientationMode.ZAxisForward;
[SerializeField] MovementPlaneSource movementPlane = MovementPlaneSource.Graph;
[SerializeField] public ManagedState managedState = new ManagedState {
enableLocalAvoidance = false,
pathfindingSettings = PathRequestSettings.Default,
};
[SerializeField] Pathfinding.ECS.AutoRepathPolicy autoRepath = Pathfinding.ECS.AutoRepathPolicy.Default;
public PhysicsScene physicsScene;
public class Baker : Baker<FollowerEntityAuthoring> {
public override void Bake(FollowerEntityAuthoring authoring) {
Entity entity = GetEntity(TransformUsageFlags.Dynamic);
float3 pos = authoring.transform.position;
quaternion rot = authoring.transform.rotation;
if (authoring.orientation == OrientationMode.YAxisForward)
rot = math.mul(rot, SyncTransformsToEntitiesSystem.YAxisForwardToZAxisForward);
AddComponent(entity, new FollowerEntityBody());
AddComponent(entity, new MovementState(pos));
AddComponent(entity, new AgentMovementPlane(rot));
AddComponent(entity, authoring.managedState.rvoSettings);
AddComponent(entity, new DestinationPoint {
destination = new float3(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity)
});
var autoRepath = authoring.autoRepath;
autoRepath.Reset();
AddComponent(entity, autoRepath);
AddComponent(entity, authoring.movement);
AddComponent(entity, new MovementStatistics {
estimatedVelocity = float3.zero,
lastPosition = pos
});
AddComponent(entity, authoring.shape);
AddComponent(entity, new GravityState());
SetComponentEnabled<GravityState>(entity, authoring.managedState.enableGravity);
if (authoring.orientation == OrientationMode.YAxisForward)
AddComponent<OrientationYAxisForward>(entity);
AddComponent(entity, new ReadyToTraverseOffMeshLink());
SetComponentEnabled<ReadyToTraverseOffMeshLink>(entity, false);
AddSharedComponent(entity, new AgentMovementPlaneSource { value = authoring.movementPlane });
AddSharedComponent(entity, new PhysicsSceneRef { physicsScene = authoring.physicsScene });
AddComponent(entity, new MovementControl { });
AddComponent(entity, new SearchState { });
AddComponent(entity, new ResolvedMovement { });
AddComponent(entity, new SimulateMovement { });
AddComponent(entity, new SimulateMovementRepair { });
AddComponent(entity, new SimulateMovementControl { });
AddComponent(entity, new SimulateMovementFinalize { });
AddComponent(entity, new ManagedStateInit { });
ResolvedMovement resolvedMovement = default;
MovementControl movementControl = default;
AgentMovementPlane movementPlane = new AgentMovementPlane(rot);
ResetControl(ref resolvedMovement, ref movementControl, ref movementPlane, pos, rot, pos);
SetComponent(entity, movementPlane);
SetComponent(entity, resolvedMovement);
SetComponent(entity, movementControl);
AddComponentObject(entity, authoring.managedState);
}
static void ResetControl(ref ResolvedMovement resolvedMovement, ref MovementControl controlOutput,
ref AgentMovementPlane movementPlane, float3 position, quaternion rotation, float3 endOfPath) {
resolvedMovement.targetPoint = position;
resolvedMovement.speed = 0;
resolvedMovement.targetRotation = resolvedMovement.targetRotationHint = controlOutput.targetRotation =
controlOutput.targetRotationHint = movementPlane.value.ToPlane(rotation);
controlOutput.endOfPath = endOfPath;
controlOutput.speed = 0f;
controlOutput.targetPoint = position;
}
}
}
public struct ManagedStateInit : IComponentData {
}
[UpdateInGroup(typeof(DroneUpdateGroup))]
public partial struct ManagedStateSetupSystem : ISystem {
void OnUpdate(ref SystemState state) {
var world = World.DefaultGameObjectInjectionWorld;
NativeList<Entity> removeEntities = new NativeList<Entity>(Allocator.Temp);
foreach (var (managedState, entity) in SystemAPI.Query<ManagedState>().WithAny<ManagedStateInit>()
.WithEntityAccess()) {
//The path tracer gets disposed in the authoring component we need to create it
if (!managedState.pathTracer.isCreated) {
managedState.pathTracer = new PathTracer(Allocator.Persistent);
world.EntityManager.SetComponentData(entity, managedState);
}
removeEntities.Add(entity);
}
//Clear the init tag
world.EntityManager.RemoveComponent(removeEntities.AsArray(), typeof(ManagedStateInit));
removeEntities.Dispose();
}
}
[UpdateInGroup(typeof(DroneUpdateGroup))]
public partial struct FollowerEntityBodySystem : ISystem {
void OnUpdate(ref SystemState state) {
foreach (var (followerEntityBody, entity) in SystemAPI.Query<RefRW<FollowerEntityBody>>().WithEntityAccess()) {
var position = SystemAPI.GetComponent<LocalToWorld>(entity).Position;
followerEntityBody.ValueRW.remainingDistance = math.distance(SystemAPI.GetComponent<MovementState>(entity).endOfPath, position);
followerEntityBody.ValueRW.velocity = math.distance(position, followerEntityBody.ValueRW.previousPosition) / Time.deltaTime;
followerEntityBody.ValueRW.previousPosition = position;
}
}
}
command code:
ref MovementSettings movementSettings,
ref DestinationPoint destinationPoint
---
movementSettings.isStopped = false;
destinationPoint.destination = destinationPosition;
some additional info: increasing the voxel size to 0.1 from 0.0666 seems to improve on this issue, i am not sure if i just got lucky because of that though.