Pathfinding seeker
Implementation for Pathfinding.Seeker
. (A* Pathfinding Project)
namespace MyProject {
[AddComponentMenu("")]
[RequireComponent(typeof(VelocityStat))]
public class Seeker : GameEntityAspect {
public override string IconPath => "MyProject_SeekerIcon";
public override string EditorTitle => base.EditorTitle + (Target != null ? " -> " + Target.name : "");
[Tooltip("Targeted object")] public Transform Target;
[Tooltip("Refresh delay of the path")] public float RefreshDelay = 1f;
[Tooltip("Final distance to the target")] public float TargetDistance = 0.5f;
[Tooltip("Size of the pathfinding grid")] public float GridSize = 1f;
Pathfinding.Seeker _seeker;
Vector3 _lastTargetPosition = Vector3.zero;
Vector3 _direction = Vector3.zero;
Pathfinding.Path _path = null;
int _pathfindingIndex = 0;
Vector3 _cursor = Vector3.zero;
void Start() {
// add pathfinding components if not found
_seeker = gameObject.GetOrAddComponent<Pathfinding.Seeker>();
_seeker.pathCallback = OnPathComplete;
gameObject.GetOrAddComponent<Pathfinding.SimpleSmoothModifier>();
// cursor is the intermediate position of the object
_cursor = transform.position;
// start coroutines
StartCoroutine(UpdateRoutine());
StartCoroutine(DirectionRoutine());
}
// update positions
void Update() {
// ignore path if the target distance < GridSize * 2
if (Target != null) {
var dist = Vector3.Distance(_cursor, Target.position);
if (dist < GridSize * 2f) {
if (dist > TargetDistance) {
_direction = (Target.position - _cursor).normalized;
}
else {
_direction = Vector3.zero;
}
}
}
// move the cursor position
if (_direction != Vector3.zero) {
_cursor += (_direction * (GetComponent<VelocityStat>().Value * Time.deltaTime));
}
// lerp between this object and the cursor
transform.position = Vector3.Lerp(transform.position, _cursor, 0.1f);
}
// update path
void OnPathComplete(Pathfinding.Path path) {
if (!path.error) {
_pathfindingIndex = 1; // because 0 is origin
_path = path;
}
else {
_path = null;
}
}
// update the cursor direction
IEnumerator DirectionRoutine() {
while (true) {
if (_path != null) {
if (_pathfindingIndex >= _path.vectorPath.Count) {
_path = null;
continue;
}
var d1 = Vector3.Distance(_cursor, _path.vectorPath[_pathfindingIndex]);
if (d1 < 1f) {
++_pathfindingIndex;
continue;
}
_direction = (_path.vectorPath[_pathfindingIndex] - _cursor).normalized;
}
else {
_direction = (Target.position - _cursor).normalized;
}
yield return new WaitForSeconds(0.1f);
}
}
// update path routine
IEnumerator UpdateRoutine() {
bool started = false;
while (true) {
if (Target != null) {
if (!started || Vector3.Distance(_lastTargetPosition, Target.position) > GridSize) {
started = true;
_seeker.StartPath(_direction != Vector3.zero ? _cursor : transform.position, Target.position);
_lastTargetPosition = Target.position;
}
}
yield return new WaitForSeconds(RefreshDelay);
}
}
}
}