Last weeks post, I demonstrated in videos the issues where the AI was not behaving as expected when traversing along the splines. The first thing I tried to do this week was to fix and improve how the AI moves along the splines.
In the above video, you can see an improvement in how the AI moves along the spline. The previous implementation for setting the movement of the AI was utilizing timelines and the ‘move to location’ node for the AI. The first problem with this approach was that the timeline ran in parallel, resulting in an issue with how the index value updated incorrectly and caused the AI to jump to the next node prematurely. The second issue was the attempt to use the ‘move to location’ node, which caused the AI to move in a weird-looking manner, as if they were almost running very slowly, almost in place, even though the character movement speed was correct. To address these issues, I implemented two key changes. Firstly, I utilized event tick and delta seconds to manually update the alpha value based on the duration calculated from the spline length and the character’s maximum walk speed. Secondly, instead of using the ‘move to location’ node, I opted for the ‘add movement input’ node. This allowed me to specify a precise direction by obtaining a direction vector from the actor’s current location to the next location, resulting in a significantly improved AI movement. Additionally, the AI’s speed now aligns with the character’s maximum walk speed, which is essential for the alpha calculation used for lerping along the splines.
This implementation also helps improve the AI’s ability to constantly move along the splines without stopping, recalculating, and then moving. However, as you can see in the video, the AI still exhibits some peculiar behavior at certain nodes when determining the next direction to move after reaching each node.
In the above video, you can see that the AI is now moving smoothly between all of the nodes along the splines.
To fix the previous issue where the AI would act weirdly when getting to a node, I adjusted the error tolerance value from 100 to 200. This makes it so the AI pathing is still fairly accurate along the spline and the AI no longer has that weird behavior. Additionally, I added a short delay at the last node of the path in order to allow the AI enough time to reach its final destination before it stopped the AI movement.
The next thing I focused on was switching the AI’s graph setup information from within its own class to obtaining it from the BP_Graph. By doing this, the graph is no longer directly inside the AI, but can be referenced by the AI for pathfinding. This approach benefits designers because they can now have multiple graphs that can be set up properly, allowing the AI to determine which graph it is currently in for accurate pathfinding updates.
If the player enters a different graph, it may make sense for the AI to select the target node as the one closest to that other graph and then switch to using that graph. Alternatively, the AI could switch to standard AI navigation using a Move To function to traverse between graphs if it gets too far from the player, who is in a different graph. The actual behavior for how this works depends on how good the AI’s behavior looks.
In the image above, you can see that BP_AICompanion has been updated to get the graph from the AISplineGraph of the Graph Actor that was selected from within the editor.
In addition to switching the graph information to be contained in the BP_SplineGraph, I updated the BP_SplineGraph construction script to automatically attach the splines and nodes to the BP_SplineGraph actor. The advantage of this approach is that they are all easily associated with the correct actor. However, the downside is that moving the BP_SplineGraph actor causes severe delay or lag inside the editor due to the looping through multiple TMaps.
After that, I focused on updating the AI pathfinding algorithm so that the target node is frequently the one closest to the player and start node is the one near the AI. Achieving this required a nearest neighbor search for the player. Since I wanted to save time, I utilized Unreal’s ‘find nearest actor’ node to find the node closest to the player or AI in an array of nodes. However, in a large-scale project, this wouldn’t be the ideal solution. Instead, it would be better to use a separate data structure such as a k-d tree, oct tree, or spatial hash grid. These data structures perform better with larger amounts of nodes as they significantly improve the runtime complexity for searching for the nearest neighbor.
The last thing I did for this week was add in the functionality for the AI to affect the weight of the spline edge. Whenever the AI walks on a spline, the weight is set to 1000, and then eventually resets to its original weight. This makes it so that the other AI can choose to path to a different direction instead. This helps prevent the AI from clumping up when walking along the graph. Unfortunately, the main problem with the current implementation is getting the AI path to update at the appropriate times. Currently if it updates too soon, you get weird behavior, but the same thing happens if the update is delayed too long. Ultimately, this would need to be iterated on in the future to improve it so that the AI traversal behaves better.
What’s Next?
Although I didn’t achieve my final goal, I’m very pleased with how this project has turned out. It has been an incredible learning experience and if I have additional time, I may continue to improve it. However, at this time, I don’t believe I will be doing more work with this project.