SingleNodeBlocker not preventing simultaneous movement

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
}

Okay a clue I have found is that the internalblock function in BlockManager has a note that says: “Note: The node will not be blocked immediately. Instead the pathfinding threads will be paused and then the update will be applied. It is however guaranteed to be applied before the next path request is started.”

I am curious why it does not block nodes immediately, and how I might go about working around this limitation. Also, any other tips or advice in regards to blocking nodes in real time as a unit travels along a path would be greatly appreciated!

Is there any real danger in just executing the node block instantly without adding it to AstarPath.active.AddWorkItem?

Hi

Sorry for the late answer.
The SingleNodeBlocker is for turn based games, and those generally do not allow simultaneous movement.

If you want to execute a work item immediately you can use AstarPath.active.FlushWorkItems.
You should not execute the blocker outside a work item because it modifies data that the pathfinding threads might be accessing at the same time.