It's been a long while since my last post! I've been super busy at work, so I haven't had a good opportunity to sit down and work on the project in a while. I've been doing some reading on networking with Unity, and I'm just about ready to get started on Phase 2 of the project.
Before I dive into that, I decided to take another look at the basic behaviors I've programmed for the AI ships. I realized that a key behavior was not working as intended - which turned out to be a great bonus! My original orbit behavior wasn't strict about which plane the ship should attempt to circle its target on, which resulted in some interesting emergent behavior, reminiscent of 'swooping' at the target, then circling around for another run. This turned out to be an excellent and dynamic attack posture, and so I am using it to that end. This does, however, mean that I need to come up with another way to get the AI to circle around its target at a specified radius.
As I've mentioned before in this blog, I want the flight controller to be truly physics based (for no reason other than the challenge of it). As such, I don't want to simply plot a circle for the ship to follow. After working out a few options, I've decided that one of the easiest ways to manage this behavior, while still allowing for my obstacle-avoidance algorithm to contribute, was to generate a series of target points along the orbital path (effectively my own version of navPoints), and to move from one to the next and approximate the circle. The first version of this I've built only features 4 target points along the orbit, and if I tune the ship's max speed (it stops accelerating if it exceeds it, it doesn't actually clamp the speed) it works very well - including collision avoidance.
The next step will be to generalize the method to be more code-efficient, and to let me input the desired number of target points I want to generate around a given orbit. Hopefully this will help me find the ideal number for orbits of different size, and generalize the method further. Eventually, I'd just like an orbital radius to be input, and everything else calculated from there.
Hello there humans, big update today. It's been a super busy work-week (as always) but I have managed to officially finish Phase 1 of this project! I'll throw together a video into this update this weekend for your viewing pleasure. As always comments, thoughts, and suggestions are welcome.
What's that? I haven't mentioned phases until this point? Well that's because recently adopted the strategy from a work colleague (thanks Heins). I've broken down my game development into a series of phases, each with a distinct focus toward getting the project done, and into players hands. I've scoped most of them out, and am tracking them as Milestones on the project on Github.
My plan for the development of the game is as follows:
I don't have timelines for all this yet, as my ability to work on the game is very dependent on my work - on which I spend the majority of my time. That being said, I'll try to come up with reasonable estimates to share with you all in the coming week. If you'd like more info, please feel free to take a look at the github repo as it is significantly more detailed.
Update 6: Weapons Galore
Date: March 6, 2018 - 8:51PM
I've just finished my first big push for integrating all of the ship systems and simple damage mechanics together! Ships can now be damaged by damage-dealing weapons, or by collisions! Any ship or station with a shield will soak damage through its shield first. Once the shield is out of hit points, it will collapse, and then the ship itself will begin to take damage. I don't have a mechanic in place yet to replace/regenerate shields, although that is definitely something I'll be adding once I'm beyond MVP.
Today's update also introduced two new weapons, which brings the total weapons roster up to 4. I have so many ideas for additional weapon types and mechanics, but for now I just wanted to flush out a few options:
Phasers (Fixed) - fires a beam in a straight line, does damage to first object hit (no force)
Phasers (Tracking with Arc) - fires a beam toward a target within a defined firing arc, does damage to first object hit (no force). Think Star Trek phasers.
Blasters (Fixed) - rapidly fires individual bolts in a straight line, (force on impact)
Blasters (Tracking with Arc) - rapidly fires individual bolts toward a target within a defined firing arc. Think Star Wars Turbo-lasers.
Now It's finally time to start building the game controller, as well as some simple UI elements to control the flow of the game. My immediate goal is to build out the core gameplay mechanic of combat, so that the game can be started from a menu screen, a single player can pilot the ship around a generated map, fight enemies, and either get destroyed by those enemies or wipe them all out. The game will end in either case, and route the user back to the title screen - thus making the game itself playable. That's the MVP scope I'm running with right now, and I like it because it means that individual systems and features can be tested before I start working on networking and building out the distributed UI for the multi-player bridge.
Once I'm finished MVP (I predict no more than a week more for that), I'll scope out the next phase of the project!
As always, comments and suggestions are welcome! I'll have another update soon.
Update 5: Introducing Shields
Date: March 4, 2018 - 3:08PM
I'm going to be at work late tonight, so I thought I'd get some work on this project in a little earlier in the day today. Small update for now, but I've recorded a video to go along with it.
I've introduced basic shield models to each of the ships and the first iteration of an in-game space station. I've based this off of a station featured in Star Trek TOS (as I did with the ships) as they are constructed of fairly simple shapes - which makes accurate colliders simple to generate, while keeping the shapes interesting. Rest assured as the project goes on, I'll be designing novel and much higher quality assets - but for now I'm building out the features - so blocking them out is an efficient option.
Note: For those of you interested, the station is modeled after DS K7, from Star Trek TOS
I want shields in the game to be invisible unless under stress, at which point they will flare up from the point of impact. This is a visual seen a lot in science fiction film and television, and one that I happen to love. For the time being, I'm keeping the shields translucent so that they're easy to debug.
Much more to come soon, but for now here's a quick video of a player-controlled ship interacting with the free-floating station. Enjoy, and as always feel free to leave comments or suggestions below!
Update 4: A Little Math
Date: March 3, 2018 - 8:07PM
As promised, I've written up the method I'm using to generate the Distance-Keeping behavior described in detail in Update 3. I've also included a key/description of the variables for reference. If you have any questions, just let me know in a message and I'd be happy to explain.
Update 3: Active Distance-Keeping Behavior
Date: March 3, 2018 - 3:04PM
I've been working the past few evenings on a new behavior for the AI ships. Although my intent ended up changing part-way through, I'm very happy with the results! There are two features introduced in this update: a new AI behavior, and a Scanning System for both the AI and for the player ship!!
Additionally, I've put the project up on Github so anyone interested can see the code. You'll find the repo here.
Note: For those of you who enjoy math, I'm going to include a description of my algorithm for creating this behavior later today!
Orbiting Behavior (Likely to be renamed :P )
Originally, I had wanted to design an Orbit Target behavior, which would have the AI ship attempt to track to a circle with a defined radius centered around the target. However, I also attempted to do this given an arbitrary starting vector, which means that the plane of this circle in 3D space would not be explicitly defined - or even constant. This would allow for more variation and perturbation (given that the AI is still avoiding obstacles while in this behavior).
However, what resulted was significantly more dynamic than I expected. Since the math is dependent on vectors in 3D space, the quadrant that the angle between two vectors is calculated in must be taken into consideration when defining the path tangential to the desired circular orbit. Without doing this the ship's guiding vector still attempts to maintain a certain distance from the target object while moving the ship perpendicular to the target vector - but the resulting orbit is most definitely NOT circular (or elliptical at all for that matter). The behavior IS dynamic and would be excellent for an offensive AI behavior. So I'm going to keep it, and use it that way. My next attempt to build an orbit behavior will certainly feature a defined orbital plane, which will make it much easier to achieve the intended behavior.
Here's a quick video of the current Orbit Target behavior in action. The red vector line indicates the guiding vector for the ship at any point. The green vector indicates the direction toward the target object, and the blue vector represents the path perpendicular to the green vector.
This is a feature I'm really excited about, as it showcases the way I intend to address systems and subsystems on all spacecraft (including the player spacecraft). This features a high-level controller component, and lower level component classes which may be attached in any number to a GameObject or it's child GameObjects. I've so far done this with a Weapons Manager and now the Scanner Manager. The breakdown looks something like this:
- Player Controller or AI Controller
- Flight Manager
- Weapons Manager
- Scanner Manager
The idea is that when the game boots up, the Scanner Manager will search it's parent GameObject and it's children for any instances of the Scanner class (importantly, this includes Scanner subclasses). Similarly the Weapon Manager will look for any instances of the Weapon class (and its subclasses).
This is great, because I can define standard weapons features in the Weapon class, or standard scanning features in the Scanner class (like interact with a target, take input, etc.), and have standard methods of control - but by using subclasses each weapon can be specialized differently.
The goal behind the Scanning system in general is to provide both the Player and AI a way to determine what is around them in space. This is great because it means that their ability to interact with other GameObjects is based on what their scanning system `sees`. By basing the scanning system on several discrete Scanner components placed on a ship, each with their own damage states and all of which feed data into the overall Scanner Manager, it becomes possible for a vehicle to loose of improve its scanning ability. Since object avoidance (for AI) is dependent on which objects they know to avoid, damaging the Scanner components could result in an AI flying into an asteroid field, or other great emergent behaviors.
I'll be uploading a video of the scanner system later today.
That's it for this update! As always, please like and comment below - I always welcome ideas and criticism.
Update 2: Multi-Object Collision Avoidance and Goal Tracking
Date: February 25, 2018 - 7:07PM
More updates on the spaceship AI pathing behavior! I've modified the behavior to include handling for multiple obstacles, and it's working great. I've put together a small video to demonstrate the behavior below. There are now three distinct behaviors for the AI flushed out (you can see the drop-down titled Current Action in the Inspector in the video):
PATH_TO_TARGET: Ship attempts to reach target. Once within range, behavior changes to CUT_ALL_ENGINES.
FOLLOW_TARGET: Ship attempts to reach target. Once within range ship continues to wait for target to move.
CUT_ALL_ENGINES: All ship flight control inputs are set to 0 and the ship is set adrift (with damping).
Update 1: AI Collision Avoidance
Date: February 25, 2018 - 5:50PM
My primary goal today has been to build out the route-planning methods for the AI ships. In particular, I'm currently focusing on the path toward target behavior. Having studied control systems in my undergrad, I decided to use a topographical approach, by creating a false gradient that would instruct the AI as to the direction it would want to take. This involves creating a vector sum of the vector between the ship and its target, and a weighted version of the vectors between each avoided object and the ship. The weight on each of these avoidance vectors in the sum is inversely proportional to the ship's proximity to the avoided object.
Although it would have been simpler to implement, the AI I designed doesn't use Lerp or an auto-rotation (ex. RotateToward()) to follow the summation vector. Instead, it projects the vector onto it's local horizontal and azimuth planes, and uses the angle between `transform.forward` and these projected vectors to instruct the flightController on how to add Torque. This results in a physics-based flight model, controlled by my AI. The general formula for the AI's guiding vector is as follows:
I've provided a small clip of it in action below. The green line rendered in the Scene view represents the vector sum at any point in time. Notice that the closer the ship gets to the target in its way, the more the presence of the avoided object effects the direction the ship wants to go in.