Here is the ECS nav agent authoring mono behavior:
// ManagedStateInfoComp.cs
public class ManagedStateInfoComp : IComponentData {
public RVOAgent rvoSettings;
public PathRequestSettings pathfindingSettings;
public bool enableLocalAvoidance;
public bool enableGravity;
}
// NavAgentAuthoring.cs
using Pathfinding;
using Pathfinding.ECS;
using Pathfinding.ECS.RVO;
using Pathfinding.PID;
using Pathfinding.Util;
using Unity.Entities;
using Unity.Mathematics;
using UnityEngine;
using AutoRepathPolicy = Pathfinding.ECS.AutoRepathPolicy;
namespace TheGame.ECS {
public class NavAgentAuthoring : MonoBehaviour {
[SerializeField] private AgentCylinderShape shape = new() {
height = 2,
radius = 0.5f,
};
[SerializeField] private MovementSettings movement = new() {
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] private ManagedState managedState = new() {
rvoSettings = RVOAgent.Default,
enableLocalAvoidance = false,
pathfindingSettings = PathRequestSettings.Default,
};
public class Baker : Baker<NavAgentAuthoring> {
public override void Bake(NavAgentAuthoring authoring) {
var entity = GetEntity(TransformUsageFlags.Dynamic);
var pos = authoring.transform.position;
AddComponent(entity, new MovementState {
followerState = new PIDMovement.PersistentState {
maxDesiredWallDistance = 0,
},
nextCorner = pos,
endOfPath = pos,
closestOnNavmesh = new float3(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity),
hierarchicalNodeIndex = -1,
remainingDistanceToEndOfPart = float.PositiveInfinity,
reachedDestination = false,
reachedEndOfPath = false,
reachedDestinationAndOrientation = false,
reachedEndOfPathAndOrientation = false,
pathTracerVersion = 0,
});
AddComponent(entity, new AgentMovementPlane {
value = new NativeMovementPlane(SimpleMovementPlane.XZPlane),
});
AddComponent(entity, new DestinationPoint {
destination = new float3(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity),
});
AddComponent(entity, authoring.movement);
AddComponentObject(entity, new ManagedStateInfoComp {
pathfindingSettings = authoring.managedState.pathfindingSettings,
enableGravity = authoring.managedState.enableGravity,
enableLocalAvoidance = authoring.managedState.enableLocalAvoidance,
});
AddComponent(entity, new MovementStatistics {
estimatedVelocity = float3.zero,
lastPosition = pos,
});
AddComponent(entity, authoring.shape);
AddComponent(entity, new SimulateMovement());
AddComponent(entity, new SimulateMovementControl());
AddComponent(entity, new SimulateMovementFinalize());
AddComponent(entity, new SearchState());
AddComponent(entity, new ResolvedMovement());
AddComponent(entity, new MovementControl());
AddSharedComponent(entity, new AgentMovementPlaneSource {
value = MovementPlaneSource.Graph
});
AddComponent(entity, new AutoRepathPolicy {
mode = Pathfinding.AutoRepathPolicy.Mode.Dynamic,
period = 1
});
}
}
}
}
// NavAgentInitSystem.cs
using Pathfinding;
using Pathfinding.ECS;
using Unity.Collections;
using Unity.Entities;
namespace TheGame.ECS {
/*
* A system to initialize ManagedState for entities with ManagedStateInfoComp
* ManagedStateInfoComp is removed once the ManagedState is initialized
*
* ManagedStated is used by the A* pathfinding project
*/
[UpdateInGroup(typeof(InitializationSystemGroup))]
public partial struct NavAgentInitSystem : ISystem {
public void OnCreate(ref SystemState state) {
state.RequireForUpdate<EndInitializationEntityCommandBufferSystem.Singleton>();
}
public void OnUpdate(ref SystemState state) {
if (AstarPath.active == null) {
return;
}
var ecb = SystemAPI.GetSingleton<EndInitializationEntityCommandBufferSystem.Singleton>().CreateCommandBuffer(state.WorldUnmanaged);
foreach (var (s, entity) in SystemAPI.Query<ManagedStateInfoComp>().WithEntityAccess()) {
var managed = new ManagedState {
pathTracer = new PathTracer(Allocator.Persistent),
rvoSettings = s.rvoSettings,
pathfindingSettings = s.pathfindingSettings,
enableLocalAvoidance = s.enableLocalAvoidance,
enableGravity = s.enableGravity,
};
ecb.RemoveComponent<ManagedStateInfoComp>(entity);
ecb.AddComponent(entity, managed);
}
}
}
}