Tag Archives: AI

It’s alive! It’s alive!

Finally!

At long last, I can happily present the first version of the ship-to-ship combat AI!
It’s really simple, for instance it’s trying to aim at the center of the enemy ship, while often aiming a bit more towards the bow would make more sense.
But for a concept of proof, I’m more than happy with it!

Here’s a short video demonstrating the AI. The black ship is controlled by me, the yellow one by the AI:

ST2U2DNavMeshImporter (Oops!… I did it again♪)

For the tilemaps, I’m using Thorbjørn Lindeijer’s Tiled and Sean Barton‘s SuperTiled2Unity. Since I just made a project to bake 2D colliders into NavMeshes, I went ahead and created a SuperTiled2Unity importer that automatically creates a NavMeshSurface with the correct position, rotation, size and all the necessary components.

All that’s left to bake your NavMesh after importing the tilemap is the press of a button!

You can find the project here: https://github.com/SharlatanY/ST2U2DNavMeshImporter

Here’s an example of an imported tilemap. All I did after the import was, to press the “Bake 2D”-button:

The project is published under the MIT license, so, you’re practically allowed to use it in whatever way you wish.

NavMeshSurface2DBaker

Currently, Unity only offers the ability to generate NavMeshes (the objects telling the path finding system where NPCs can move) from 3D obstacles. Since I’m developing a 2D game and would like to make use of Unity’s inbuilt path finding, this posed a problem.

That’s why I developed a solution that worked for my case. When everything worked, I thought to myself that it wouldn’t take too much additional effort to polish this a little, make it more multi purpose (e.g. I only needed it to detect polygon colliders and had no personal need for also handling circle colliders, etc.) and easy enough to use so it might be useful to other people as well.

What I ended up with is a solution to easily bake 2D colliders into a NavMeshSurface.

Supported colliders:

  • BoxCollider2D
  • CircleCollider2D
  • PolygonCollider2D
  • CompositeCollider2D
  • TilemapCollider2D (For those to work, you have to make them part of a CompositeCollider2D, though!)

You can find the end result here: https://github.com/SharlatanY/NavMeshSurface2DBaker

Here’s an example of a baked NavMesh for a hex tilemap (red tiles have a collider):

The project is published under the MIT license, so, you’re practically allowed to use it in whatever way you wish.

Unfortunately, as is often the case, I was very, very wrong about the effort it would take to make the project more useful to others as well.
Getting it to work for my specific use case took about a day of work, making it more general purpose, easier to use ,cleaning up the code, setting up the GitHub repository, adding instructions and a project example, writing this blog post, etc. took at least two more full days of work.

Now, I’m torn about how I should handle such things in the future.

On one hand, I’m really very happy to have made something that might be of use to others (I’ve seen people looking for exactly this functionality multiple times) and to give something back to the community. After all, there’s lot’s of people out there that helped me out in one way or another and even if it’s not always possible to pay them back, this feels like a way to at least pay it forward.
On the other hand, polishing and releasing this made the task more than 3 times as long as it would have been if I just stopped at the point where it was good enough for my own purposes.

If we’re honest, the project I’m trying to create is way out of scope and a monumental task that will still take me years to finish.
I only work on this in my spare time and when I feel like it because I know I’ll never finish it as soon as I have the feeling that I must work on it.
Currently, I’m on vacation and make quite good progress. But during the rest of the year, I maybe get to work on this project somewhere between 1 and 2 full days a week (likely closer to 1..) on average. Which means that making the NavMeshSurface2DBaker presentable and releasing it cost me about half a month of normal (=non vacation) development time.
With all the things that I already know still have to be done and the rate at which I discover new things that will also have to be done, I’m not really sure if I can afford and justify such escapades.

 

Progress Report: November 2018

One of my next goals is, to implement a simple naval combat AI to finally have something playable. I feel, this should have happened way sooner. Sure, you can sail around a map, enter ports, buy some things, etc. but that doesn’t feel like a game (no matter, how rough).

An AI deciding “I should catch up to the other ship!” or “The ship is in bad shape, I should flee!” is no good, if it doesn’t know how to catch up/flee/etc.
That’s why I’m currently working on some simple movement patterns.

Progress Report: September 2018

The focus of September was on AI ship movement, mainly on path finding.

There are a lot of common path finding algorithms out there but there is one drawback they have:  while they can take some  information like terrain movement cost into consideration, they generally just find the shortest way assuming an agent could move however he wanted. This also means that they can’t calculate a path considering possible agent restrictions like that the agent can’t fully slow down (or only with some delay), an agent might have a limited turn rate and only be able to turn whilst also moving forward, etc.
Another thing they can’t do, for example, would be to also consider the wind direction and it’s influence on ship speed, to calculate the quickest/best path.

Unfortunately,  an algorithm supporting all this would most likely be not only be computationally too expensive but also out of my league, time and ability wise.

So, what I opted for instead was the following idea: I use some standard path finding but instead of just moving ships along this optimal path, I’ll try to stick to the optimal path as much as possible but will only move/rotate the ship as much as the calculated restrictions allow. For example, when the calculated path tells me the ship should rotate 5° in a frame and the ship can only rotate 3° considering alignment to wind, wind speed, etc. I only rotate the ship 3° and will then try to rotate the rest in the next frame.

Following, you can see a video where I try this out with different turn rate settings. One important thing to note is that, at least currently, the ship can’t slow down and will always move as fast as possible as it can under the current circumstances (wind direction, etc), which further exacerbates the problems you’ll witness. This isn’t entirely realistic but might be kept for game play reasons. But even if not, the ship would most likely still have some inertia that will keep it from slowing down instantly.

Things to note

  • As long as there are no tight turns, movement works flawlessly.
  • Tight turns pose big problems.
  • With higher turn speeds, the problems become fewer but are still present.
  • There are situations in the video. where you can see the problem I described in the beginning: Since it has problems making quick turns, it would make way more sense for the ship to continue sailing around an obstacle and make a soft turn instead of trying to immediately turn around. But because traditional path finding calculates what it determines the most ideal path without considering the ships slow turning speed, the calculated path is totally different and causes the ship to do an almost 180° turn practically on the spot.
    This picture shows the problem as well:

    Traditional path finding doesn’t always lend itself to finding paths that make sense for a ship… (Yellow line = desired path, end of line = desired destination)

Why this might not matter

I currently won’t try to fix this for a few reasons:

  • The ship stats/controls aren’t calibrated at all. As long as I don’t at least roughly know, how the ships will steer in the end, there’s no sense in optimizing an AI for it.
  • Luckily, naval fights mainly consist of loads of water and the occasional “Arrrh!”. There simply will be near to no obstacles at all. At most a few ships and the rest is open space.
    If there are practically no obstacles, having problems with avoiding them might simply not matter. But to be sure, I’ll have to develop a simple naval battle AI first.

What if it matters after all?

I do have some ideas on how I could fix or at least lessen this problems:

  • Ships could slow down and try to rotate in a smaller arc if the amount they want to rotate is greater than a certain amount of degrees.
  • Ships could not rotate when too close to an object so they don’t crash into it, etc.
  • I could try to calculate paths from a spot a little in front of the ship to the desired destination and use that path if it contains fewer path segments than the currently calculated path.
  • etc.