I’m experimenting with the turn-based system allowing simultaneous movement, and for some reason if two units go to move into the same space on the same frame, I cannot get them to adhere to the single node blockers.
Here is the code that places a blocker at the next point on the vector path (if it is not already occupied by another blocker), and for some reason this isn’t working if two units 1-tile away want to move into the same place. Any insight is greatly appreciated!
IEnumerator MoveAlongPath(Pathfinding.Examples.TurnBasedAICustom unit, ABPath path, float speed, Animator animator)
{
if (path.error || path.vectorPath.Count == 0)
{
Debug.Log("empty path");
throw new System.ArgumentException("Cannot follow an empty path");
}
Vector3 currentPoint = path.vectorPath[0];
// Very simple movement, just interpolate using a catmull rom spline
float distanceAlongSegment = 0;
for (int i = 0; i < path.vectorPath.Count - 1; i++)
{
unit.targetNode = path.path[i];
var p0 = path.vectorPath[Mathf.Max(i - 1, 0)]; // makes sure the point is at least 0
// Start of current segment
var p1 = path.vectorPath[i]; // current point
// End of current segment
var p2 = path.vectorPath[i + 1]; // next point
var p3 = path.vectorPath[Mathf.Min(i + 2, path.vectorPath.Count - 1)]; // point after that but not more than the last point
if(!patrolling && CheckIfPlayerInAttackRange())
{
currentPoint = p1;
break;
}
GraphNode nextNode = AstarPath.active.GetNearest(p2).node;
if (unit.blockManager.NodeContainsAnyExcept(nextNode, new List<SingleNodeBlockerCustom>() { unit.blocker }))
{
Debug.Log("NODE DETECTED MOVE INTERUPPTED!@");
currentPoint = p1;
break;
}
unit.targetNode = nextNode;
currentPoint = p2;
unit.blocker.BlockAt(p2);
var segmentLength = Vector3.Distance(p1, p2);
Vector3 direction = p2 - p1;
Quaternion toRotation = Quaternion.LookRotation(direction, Vector3.up);
while (distanceAlongSegment < segmentLength)
{
var interpolatedPoint = AstarSplines.CatmullRom(p0, p1, p2, p3, distanceAlongSegment / segmentLength);
unit.transform.position = interpolatedPoint;
yield return null;
distanceAlongSegment += Time.deltaTime * speed;
unit.transform.rotation = Quaternion.Lerp(unit.transform.rotation, toRotation, 8 * Time.deltaTime);
}
distanceAlongSegment -= segmentLength; // removes last segment distance while leaving spline overshoot in place
}
unit.transform.position = currentPoint; // firmly plants the unit at final point
animator.SetBool("Move", false); // set move animation to false
}