AI controlled war-time airships going at it

Recently I’ve been working on AI controlled airships, which fight each other, similar to WW2 era naval ships.

If you’re confused about the way the ships look and how they are flying, look to this image I saw a while back which sparked the inspiration for stuff like this:

That brings me onto the first point of feedback, the visual design of the ship should convey that the ships are meant to be flying, I currently don’t think that’s the case.
All I can think of to help this is adding fins to the bottom and a propeller at the rear
Suggestions welcome

Finally here is some more videos:
2v2

Night battle using some experimental fog feature

Thanks for reading and sorry for long videos and poor quality

13 Likes

This is a really cool concept that (from what I can see) seems executed well. I think that you could add propellers laying flat like the marvel helicarrier to show that it is flying. The propellers could be adapted to fit the ship.

3 Likes

This is so based… tell me, how did you make these airships move? Using bodyposition?

1 Like

Currently they use a weird mix of body movers and the new forces which replaced the old body movers.

Specifically, body velocity for the ships thrust and angular velocity for the turning. It would definitely be better to use 2 body movers or 2 new forces (body velocity and body angular velocity, or vector force and angular velocity).
This solution is not without fault though, as the body velocity moves the ship in its forward vector, if it gets knocked so that it faces up, it will fly up away from the one Y plane where all the ships fight. For example when 2 ships collide with each other. Maybe a body gyro to prevent the ship from banking and pitching and a body position to keep the Y position could fix this.

The ship movement was just recycled from an older project from about 2 weeks prior which just showed the ships moving, as to why I chose to use the mix of the two when making that, I’m not sure. But when (if) I refactor this stuff, I’ll definitely switch to using 2 of the same force.

Regarding the code, each ship is its own object, which receives an update from a singleton every frame (I think, the singleton uses heartbeat and issues out this update method)
In the update method, the ship class calls its “UpdateBodyMovers” method


Here you can see how the body movers are upated, crucially the variables turning, speed and heading are used. They are set in a code block prior to this section. Ill post that next. Before that though, you see that the code can use multiple body movers, so here its set up to use a body position if a body position is found. That means I could have a ship which switches from the velocity and angular velocity solution to a body position solution mid game, like maybe it land on the ground on something? Currently though, no body positions are used.

Then just prior to this:
image
Heading is pretty simple, but speed is determined by telegraph and turning is determined by rudder. The rudder and telegraph values are decided by the ships AI, so if its trying to shadow a target, its telegraph may be set to half speed and its rudder will be set so that it will eventually face the target if it faces that direction. (I actually made a forum post about an issue regarding facing the target)

Finally, “telegraphToSpeed” is just a dictionary, which determines the speed of the ship depending on the telegraph.
image
This way certain classes of ships such as battleships will be relatively slower than say destroyers or pt boats.
Also, here the telegraph values are stored as integers, but they correlate to “FULL AHEAD”, “HALF AHEAD”, “STOP”, “HALF ASTERN” etc

2 Likes

I just don’t know why you’re updating the velocity every frame. Wouldn’t it be more optimized to update it every tenth of a second instead?

2 Likes

Here are some additions to the ships based on feedback:

The original:

1st ship:
Note the propellers as well as fins



Here it is in action:

2nd ship
(the propellers are now angled down)



And here is the 2nd ship in action:

Conclusion
I feel that the fin on the bottom as well as the rear add a lot, as well as the rear propellers. However, the propellers at the side feel somewhat cluttered, perhaps there are too many of them. Also having 8 propellers pointing upwards setting there cframe every frame per ship cant be good right?

Eager to hear others thoughts.

Favourite ship?

  • Original ship
  • 1st Design (fins and propellers perpendicular to the hull)
  • 2nd Design (fins and propellers angled down slightly)

0 voters

And finally, you may notice the extra turrets on these ships. I think the term for them is superfiring. This main armament has wider “fov”, so for example the one at the stern can shoot targets behind it, whilst also supporting the port and starboard sides. They have longer range and more health than the secondary armament. See them in action here:

1 Like

Most likely, but optimization as a whole doesn’t really cross my mind when i’m making stuff, and seeing how this is only a prototype, its not the biggest deal. Definitely will change this to your idea in the future. Thanks for the feedback

Is this going to be used in a game, or is it just a test?

And what about the projectiles? How did you make them? Did you use CFrames for them, and if so, how did you detect them hitting the targets?

Not sure yet to be completely honest. All the airship stuff does tie into a larger project I had in mind, and this would just be testing the AI combat. Perhaps I will recycle these assets into a smaller project which I can publish in a shorter timeframe, who knows.

1 Like

After generating the path which the projectile will follow (which is just a bunch of vector 3s), I would:

  1. Raycast from the projectiles current position to the next position along the path
  2. If the raycast didnt hit anything, then it means that the projectile wouldn’t hit anything as it travels to the next point, so then I would set the projectiles cframe to the next point on the path.
  3. If the raycast did hit something, then the projectile would hit something, so then I get raycast.Position to find where it hit, and use raycast.Instance to find out what was hit. Using those 2 things I can determine what to damage and what effects to use.

The projectiles are moved along the paths by setting their cframes, currently it uses a bad solution in that I spawn a for loop on a different thread using spawn(), then just use a wait() within that for loop, and every iteration I do the raycast check as well as move the part. This is terrible, because when the game is played at lower framerates (say if there is more ships present and more projectiles being shot), then the projectiles move much slower. I know how to fix this, as other parts of the project use delta time to get around the wait() amount changing with framerate, I just haven’t got around to doing it yet. (A lot of the code isnt the best, because this is just a prototype)

Additionally, rather than just setting the parts cframe you could tween it along the points.

2 Likes