I worked on this project for about 3 months as an experiment in designing AI behaviors for vehicles constrained by the simulation they participate in. I chose to do this with planes that move roughly according to the way planes do in real life. That is using wing and tail flaps as well as a rudder and throttle to manipulate air pressures to gain lift and make turns.
Player/AI Controls:
Accelerate or Decelerate
Left/Right Aileron - Move Up or Down
Left/Right Elevator - Move Up or Down
Rudder - Move Left or Right
Final version of my AI in action. Top screen is the player and the bottom screen is the lead AI.
As the player (purple) flies around the world the lead plane will attempt to follow it while 4 other AIs attempt to keep formation around it. The long while boxes show the world location that each AI plane is targeting as a very rough way for me to debug.
All in all I think I got the behavior itself down pretty well by the end. The AI will occasionally get confused or fly upside down but still does a pretty good job of following the player's path. Id like to turn this into an AI for a flying dogfight game but for the reasons I go into below I would most likely just start over with what I learned from this project.
This project ended up being much more haphazard in terms of my code structure than I would have liked. My approach began with attempting to create some basic movement behaviors and then use those in a BT to create more complex logic, but I quickly realized that behaviors which are fairly simple to implement when dealing directly with accelerations and velocities become much more complicated to implement when the AI can only manipulate movement through physical controls on a vehicle.
I can not recommend anyone use the code shown here to implement plane AIs, as a result of the decisions I made in the beginning of this project much of the code is hacked in and to make proper behaviors much of this would need to be refactored. Instead please read through this and take some of the things I've learned from my mistakes into consideration if you are making a game that requires AIs for physically based vehicles.
To the right I have my Seek function. For those familiar with game AI this is typically a very easy to implement behavior that moves the AI towards a target location at full speed, however since my planes are not able to simply manipulate their own velocities or accelerations to move towards the target location, this function ended up consisting of 6 smaller behaviors and a small amount of decision making logic.
This was one of the first behaviors I tried to write and while I was able to get Seek working, I spent far too many hours testing and tuning this one function. I vastly overestimated how small of a behavior I would need to implement in order to properly tune each one and then use them in a composite behavior. To do this properly I would want to implement Seek in a behavior tree using these smaller functions.
After realizing that I needed to break down my functions into simpler more individually testable behaviors I started creating functions for the most simple actions I could think of that a plane would need to perform in pursuit of a target. This included things like having the plane hold its altitude or angle of vertical incline steady as well as functions for individually controlling the ailerons, elevators, and rudder to orient the plane towards its target.
Even this function for having the ailerons (wing flaps) orient the plane became a bit cumbersome to test and tune as there were multiple factors involved in making sure the plane had the correct roll angle to make a turn towards its target.
In retrospect I should have broken this one down into separate steps for orienting roll to make a turn and then let a behavior tree handle the logic for leveling out and increasing or decreasing the elevation of the plane after properly orienting itself. As it is, this function became very difficult to tune correctly because having the orient roll and elevation targeting aspects contained in the same function would sometimes interfere with each other. Having a behavior tree handle the decision of which behaviors to perform would have made it much simpler to tune each one and combine them without convoluted logic.
In addition to organizing my behavior functions poorly, I also struggled to get the planes to move correctly because many of the values I was using for forces and torque on the plane were far too large for the mass and scale of my planes. Good practices like implementing clamps on forces and torques will help but only take you so far. It is essential to make sure that BEFORE you start implementing behaviors or even most of the core physics of your vehicle, that the scale for all your values is appropriate for the engine and won't cause chaotic or undesirable behaviors. Once I began actually implementing the movement and trying to tune it for both players and the AIs, it became obvious to me that I had to go back and choose better values for many aspects of my planes to have any reasonable chance at producing the desired gameplay.
I also think that if I had the time, or planned to work on this project for a longer period of time I would need to make better debug tools so that I could tell which parts of my logic were working and which aren't during gameplay. I had very few indicators, visual or otherwise, of what each AI was actually aiming for and how they were updating inputs to orient the plane. I relied primarily on Unity debug lines to see the target vectors and print statements for values output by the AI, but without better ways to see the angle difference between each axis of the plane and its target, as well as the corresponding control values for each flap, debugging often took me much longer than expected.
In conclusion I hope this provided a bit of insight into the issues I faced working on this project and how to better deal with them. Although I had tons of roadblocks and unexpected issues I'm glad I had the opportunity to work on this and considering my love for vehicle games I'm sure I'll use what I've learned here in one of my future projects.