This week I started developing the unit feature. This feature is going to handle all units in the game.
My approach is currently very simple. The pace of the game is slow enough for me to have units running completely on the server-side. A delay of the entire RTT on a bad connection, even if it is as high as 1s, won't be a problem for this game. Because of this, players will only issue commands for the units, and the entire unit logic will run only on the server. Locally, I just have to interpolate/extrapolate the unit's position.
The Unit AI is implemented quite easily then. Since it all happens in the same context, I can use a simple behavior tree (BT) to implement everything. The BT controller is disabled on clients and enabled on the server.
What I did in this iteration is exactly that. I have created a scene where I have isolated the static entities feature. There I have code that creates a simple map with one resource, one city, and one extractor.
The unit then is spawned and set up with its configuration (it defines how many resources it can carry in this case). After that, I trigger the unit's brain to run a simple BT. The current implementation just looks for the nearest extractor, goes to it (pathfinding), and extracts all the resources it can. Then it finds a resource receiver, in this case, a city, and goes to it to deliver the resources. This is not going to be the final AI since in this game the player is going to control where the unit is going to go, and what it is going to do there, but it is a valid proof of concept.
I decided to use behavior trees because they are easy to understand and because they provide a flexible way of defining behavior. With BTs I can quickly create some actions and tasks, combine those into reusable subtrees and in a matter of minutes, I can create really complex AI with small, easy-to-understand building blocks.
In the past, I had developed my own solution, on top of the XNode library. Not hard at all to develop, but XNode puts a LOT of constraints on the data and ties it to the presentation layer. This is something I really don't like, causing the code to have unnecessary allocations and restraints that it shouldn't have. After a lot of research, I found the NodeCanvas library. Really easy to use, awesome looking, has fast rendering on its window, and the best thing: is an API that is easy to use, clean, and really flexible. I chose that for now, lets's see where this goes.