Citizens Dev Diary - Units

Citizens: Far Lands

Citizens is a blend between turn based city builder and a puzzler for strategy masterminds. Build a thriving settlement, extract and process resources and manage your population by catering to their needs, thus allowing you to build bigger and better!

Hello everyone. I figured it might be a nice idea to write a little post about the mechanics of our combat system in Citizens: Far Lands. It has taken a little while to develop, and has gone through a major overhaul, so I think the lessons I've learned on it could be shared with a wider community for the greater good :) For those of you who are not into programming, I tried to keep it light. You might still find it interesting to see how it all works "on the inside". Initially the combat system in Citizens started as a turn based system. From the beginning it was written to be as reusable as possible. Although I'm not a good programmer, I try to make my systems like plugins: something I can just easily drop in and out of the program I'm working on. Initially the basic requirements were: [list] [*]A few soldiers (let's call them subunits) should move together as a unit. We will call these "Flags". [*] Each Flag has statistics that are always the same, and some that grow or shrink with each subunit in the unit. For example damage should be increased when there are more subunits, and should shrink as they die. [*]Each subunit has its own animator, they should be able to move, attack, die and stand idle [/list] I started off with designing the basic component called a "UnitObject". This was a scriptable object that defined what the unit was, what it was called, what statistics it had and so on. Over time it would grow to gain additional parameters, but I started with some simple ones like health and damage. [img]https://i.imgur.com/HNOdgcL.png[/img] Here you can see an and result. This is how we define an "Archer". There are some additional optional parameters that are left empty (for example units can have unique banner carriers). If the unit throws missiles, we can specify those too (arrows, axes, giant chickens...). An important list to take not of is "[b]Keywords[/b]". Stealing the idea from tabletop strategy games (Kings of War, Warhammer), we define what a unit is by giving it a bunch of strings. "Missile", "Infantry", "Cavalry" and so on. This way we can also add "defence" and "attack" modifiers which are based on said keywords. We'll discuss these later. Scriptable objects are nice because they provide a visual interface for the designer to change the unit stats quickly and easily. If we were trying to make the game moddable (so basically if we were writing it again :) ), I'd probably do something like this, but the end result would be converted to an XML file read from streaming assets. The next part is Sub Unit. Sub Unit is a prefab that defines an individual soldier. It has its mesh, animator and components needed for it to work. [img]https://i.imgur.com/D3V84Yp.png[/img] SubUnit component contains mostly data and a few helper methods. A lot of it is populated at runtime by the battle manager (parent flag, troop, anchor and so on). It has some basic controls for animations such as "move", "idle", "die" and "attack". SoldierAnimation component is basically a wrapper for the animator. It provides a slightly more friendly interface. [img]https://i.imgur.com/888FQLH.png[/img] How SoldierAnimation is useful: [img]https://i.imgur.com/H1ifqsP.png[/img] The last and most important component is the "Flag" component. Flag component has all the methods and parameters that the battle manager is constantly interacting with. Because we're lazy, we use Unity's inbuilt Navmesh Agent to move the troops around. Flag detects its own movement and tells all its SubUnits "hey, I'm moving now, play the move animation". Flags can grow and shrink in the number of active subunits, so we need methods for these too. Each subunit we add increases health and damage, but leaves some other statistics such as movement speed or attack speed unchanged. Whenever a subunit dies, these are reduced. [img]https://i.imgur.com/K3zbwvk.png[/img] Since we moved away from the turn based system, attacking is done in real time. There's a simple timer that ticks down, to check whether enough time has passed between attacks so that another can be carried out. When the timer is up, unit attempts to attack a selected target. There is some logic in selecting targets, but it would require its own long post. [img]https://i.imgur.com/DGSDkE6.png[/img] So, attacks! Remember keywords I mentioned? Damage dealing itself is quite simple. At its core, we simply takeaway the amount of damage from flag's health, but there is damage reduction and amplification. Spearmen unit can have a 50% attack bonus against "Cavalry" keyword. Units that are standing in a forest can have a 50% defence bonus against "Missile" keyword. Terrain modifiers can also contribute a lot! We can effect range, unit speed, damage amplification, damage reduction, attack speed... all sorts of stuff. All in all, the system works quite well. If you have the right animations and meshes, a new, fully functioning unit can be setup by a designer in a few minutes. I hope you enjoyed this little dev diary, and perhaps it gave you some ideas if you're working on your own stuff. The system is no longer turn based, and a demo update is coming in a few days where you'll be able to try it yourself. Our next dev diary will deal with AI and battlefields themselves! [img]https://i.imgur.com/zN7cRLS.png[/img]