Jumping AI – Jump Steering Behavior
Incorporating jumping into an AI unit’s behavior is something that may seem simple at first. And if all you need is for the AI to jump randomly here and there, then it may be quite simple. But let’s say that you have a series of gaps or pits in your game that an AI may need to cross. Maybe you’re working on a platformer where the AI needs to jump over gaps in order to attack the player. Or maybe you’re working on a shooter with different types of classes so your AI units carry different weights, or something like that. In circumstances where the AI needs to cross gaps/holes or jump over obstacles, then incorporating jumping in the form of a steering behavior may be the correct solution.
Jump Points and Landing Pads
Jumping AI is somewhat inherently difficult because of the margin for error – the AI could end up stuck or in a pit if the jump is not executed properly. To prevent such a scenario, one method that works very well with the Jump steering behavior is the use of jump points and landing pads. Essentially, what this means is that within a level, there are various designated “jump point” and “landing pad” areas. When an AI characters is moving towards a ledge, and realizes that it must take a jump, the Jump steering behavior determines the correct velocity and direction needed to make it from that jump point to the landing pad on the other side. It does this via a trajectory calculation that takes into account the difference in position between the jump point and the landing pad.
Once it has calculated the trajectory, the Jump steering behavior moves the AI character towards the jump point with the correct velocity and direction that it just calculated. Once it hits the jump point, the unit goes airborne (how this is done depends on how you are implementing physics within your game). Now that the unit is airborne with the correct velocity and direction, the AI unit will land safely on the other side, and the Jump steering behavior has done its job and can sit back and relax until the AI approaches another gap.
But Why Landing Pads?
At first glance, it may seem that jump points are all that is required. Why is it necessary to always have landing pads? In some cases it seems that the direction of the jump isn’t too crucial as long as the unit has enough velocity to cross the gap. But, as it turns out, most of the time direction does really matter in addition to velocity.
Thus, it is not simply enough to have jump points alone, since while this might work if the gap is small or the landing area is large, it does not work in many circumstances, particularly, if the AI is trying to land on a small landing area. This is why the added information of the landing pad is crucial, since it makes sure that the AI lands safely on the other side in all circumstances.
As can be seen in the above diagram, only using jump points works in the first instance, but not in the second, because without landing pads, then the Jump steering behavior only cares about getting the AI unit across the gap with the correct velocity, but it doesn’t care whether or not the AI unit actually moves towards and lands on the landing area correctly.
As seen above, using the addition information that comes along with landing pads, the velocity and direction of the AI unit is changed in order to ensure it lands safely on the other side in the corresponding landing area.
Conclusion and Other Thoughts
So, just to recap, here is the breakdown of what is happening:
- AI unit uses a steering behavior to navigate the level as normal (this is usually a pathfinding behavior or maybe a seek/arrive).
- Once the unit is in range of the gap and realizes it must make a jump, the Jump steering behavior takes over and calculates the trajectory.
- The trajectory (with the corresponding velocities) is passed off to the VelocityMatch behavior, which applies the calculated velocities to the AI unit, bringing it up to the velocity it needs to make the jump.
- Once the unit touches the jump point, the Jump behavior schedules for the unit to actually go airborne.
- The unit lands and the original steering behavior (pathfinding/seek/arrive) takes over until the next gap.
The benefits to this technique are that once you have the behavior set up, you (or the level designer or whoever else is working on the levels) can just add whatever amount of jump and landing points to the level and you’re all set. In addition, the behavior does not require much processing, since the trajectory only needs to be calculated once per jump.
Ultimately, this technique is most suited for games where the AI characters actually HAVE to jump and cross gaps or vault over obstacles. Thus, this is most suited for games such as platformers (2D or 3D) and 3D shooters, where there are gaps and obstacles for enemies to cross. Honestly, this can be done on just about any platform, but to me it seems like it would work especially well with a game developed in Unity with C#. Steering behaviors are fairly modular, and it seems like it would fit in well with that sort of development style.
So, for my implementation of this Jump steering behavior I created a tech demo which attempts to showcase the steering behavior, along with the jump points and landing pads. I based my Jump steering behavior code on pseudocode found in Artificial Intelligence for Games, a textbook written by Ian Millington and John Funge. After creating the Jump code, I combined it with some previous steering behavior and pathfinding code I had used in a previous project in hopes of better illustrating the concept.
Anyway, on to the code. I’ll just try to show the most important parts. Here is essentially the catalyst of the Jump code; this runs once the AI unit is within range of the jump point. Essentially, if there is no trajectory, calculateTarget() is called to create a trajectory. Then, this trajectory is passed off to VelocityMatch to actually apply the trajectory to the AI unit.
CalculateTarget(), as shown below, solves the trajectory equation for the velocities that need to be applied to the AI unit.
CheckJumpTime() is where those velocities are actually calculated.
Anyway, put that all together, add some pathfinding, and this is what you might get! It has less bugs now!
Also, here’s a link to a presentation I did regarding this topic for my Game AI class: AI_JUMPING_2002
Primary reference, a Game AI textbook: Millington, Ian, and John Funge. Artificial Intelligence for Games. 2nd ed. Boca Raton, Fla.: CRC, 2009. Print.
GitHub page with a description of the Jump steering behavior: https://github.com/libgdx/gdx-ai/wiki/Steering-Behaviors
Presentation based on the AI For Games book’s description of the Jump steering behavior, with some extra info here and there: http://www.academia.edu/8835040/GAME_AI_MOVEMENT
– David Hartman