Racing game pathing AI

I’m having quite a bit of difficulty implementing a behavior tree/pathing system for a simple racing game, hoping to get some clarification or direction.

To start with, I have a blueprint called BP_Checkpoint that basically just contains a box bounds and a static mesh. This also contains a variable “Next Checkpoint” that is supposed to store the next checkpoint after it. So 1 -> 2. 2 -> 3, etc. The idea was that when an AI character reached a checkpoint, they could ask which is the next point they should start seeking towards.

I initially had trouble with this because if the Next Checkpoint variable was type “BP_Checkpoint”, my blueprints got screwed up when I hit play. Nodes involving “Set Next checkpoint” would rewire themselves and set “Self” to the next checkpoint, even if I was passing in a separate instance in the level. I resolved this by setting Next checkpoint to be an actor variable.

These are then linked and built in the level On Play. BP2 is set as BP1’s next, BP3 is set as BP2’s next and so forth. I know that these are being set correctly because I can draw a debug line from “self to next checkpoint” on box overlap and a line is drawn correctly to the next place.

Good. Done. Now, onto the AI?

Here is where I think things have gone terribly wrong for me. I tried reading through some of the AI/Behavior tree threads and I thought I had grasped them well, but I can’t figure out what has gone wrong:

I have a blackboard asset that contains a single key, which is an actor called “Destination”. This I use to determine where the AI should path to next.
I have a very simple behavior tree that just basically says “Have I reached my current check point? If so, get the next checkpoint, then move towards it.”

I had thought this would be simple enough to work initially just to get the AI character looping around the track.

Here is the Reached Checkpoint decorator:

The thought process being that I get my pawns current location and I get the current destination set in the blackboard, and if I’m within 100 units of it, return true and allow the “Select Location” task to be run. If false, then this behavior tree node should be ignored and the “Move To” task is run on the current destination.

Now for the Select Location task:

For this, it should be simple. Get the current checkpoint in the Destination key, cast it to a BP_Checkpoint and get the actor stored in Next Checkpoint. Then we just set the Destination key in the Blackboard to this new checkpoint.
On the next run of the behavior tree, the actor should call Reached Checkpoint, see that they are far away from the current destination (which is the new checkpoint we just selected) and fail that boolean and thus call Move To on that new checkpoint.

However what I am seeing is that the AI actor will run to the first checkpoint and stop. After some random time, between 1 to 10 seconds, they will move to the second checkpoint. Again after some random time, move to the third and so on and so forth until they finally loop the track.

Any ideas? I’m a bit stumped as to why they are pausing at each location. I’m also wondering if there is a better way to do this other than a fake linked list of checkpoints.

So, as an update, I ended up going this route:

The AI actors contain an event that is fired from the checkpoint they hit. In the checkpoint its just on overlap, cast to BPC_AI and then call reached. This way I can let the AI character blueprint determine what to do next, which is as simple as shown.

I really feel that this is a poor way to accomplish this and I’d like to figure out how to do it with behavior trees, because I think they would let me do far more unique things.