Login / Register

Latest official blog posts

Development Toys

15th March 2021

When I decided to make Banished, one of my main requirements was a definite 'NO ANIMATION'! Well, at least as little animation as possible. The idea of modeling, rigging, keyframing, and adding all the things required to have animations didn't seem very feasible for a graphics programmer turned indie developer. So for the first half of Banished, everything was buildings, terrain, and a box for characters that hopped around.

Eventually came a day where I added chickens. I modeled it, textured it, rigged it, and spent probably more than a few days figuring out how to animate it. After that it wasn't so bad. I built some simple humans an made it work. But rigging models, setting up I/K, setting keyframes, and trying to make nice animation wasn't my favorite thing. With time I'm sure I could have gotten better at it. But with so much to do building the game myself, it wasn't a priority.

For my current game, I'm going to need a lot more animation. I still don't want to keyframe everything. Potentially twice too, since this time I have different male/female skeletons. There's a lot of animations I want. A walk cycle holding each and every tool. Different animations for every tool and thing the villagers can do. Running. Sleeping. Ah! Maybe hire an animator?

But instead, I decided to buy some toys (er, tools). I purchased them so I can build a bigger game than before but not have a large increase in workload, and they're helping me overcome the skills I don't have.

So. I've been wanting one for a few years, and I am now the happy owner of an inertial motion capture suit. I put it on, it records my movements, and then I have animations. Yay!

But not all is easy in motion capture land. I've spent the last week or so building a pipeline that gets my animations into the game fast. I believe that traditionally, an animator would bring motion capture into another tool, modify it slightly to make it work in game, export that, and then bring it into a game engine. I want to just record and get that data into the game without a whole lot of extra work. Luckily, the motion data from the suit is very good. I don't have joints doing funny things very often. So there's not a lot of cleanup, if any at all.

The first technical thing to consider is that the animation is being re-targeted from my body structure, to whatever I've built for my characters.

Writing the re-targeting code wasn't as bad as I feared. I export a version of the skeleton of my characters in a T-pose that matches the basic configuration of the motion capture skeleton. This doesn't have to be the same way the character is modeled. The character could be in A-pose or N-pose or whatever, I just need to rotate bones into T-pose to match and export. Any transform differences are accounted for so I can map the rotation values from skeleton to skeleton. Then per bone I can pick which skeleton I want offset and rotation data from. I also had to write some code to move forward hip movement onto the root node which the engine needs, and reorient the entire model depending on which way it was facing in the motion capture data.

So once I mapped the motion data onto my skeletons, there are still a few issues. While the motion is good and follows how I've moved, based on arm length, leg length, hip width and shoulder width, the hands and feet don't end up exactly where I expect. In many cases this doesn't matter. But when it does, traditionally an animator would tweak the captured motion. But I'm going to use 2 bone inverse kinematics to place hands where they need to be when it matters. This also helps when interacting with objects. The same animation could be used to pick up different size objects and the I/K will put the hands in the right place. Feet sliding is taken care of by scaling the speed of forward movement based on the ratio between hip height in my characters skeleton and the hip height in the motion data.

The last issue is looping animations. In a walk cycle, the end pose needs to match the start pose. But it's really unlikely I'll actually match 100% by recording data. So I blend the beginning and end of the animation with the data on the other side of the loop. It's close anyway, and by blending a few frames together the loop looks perfect.

So after all that work was done, lots of testing and tweaking, I can now build animations fast. Put on the suit, record the motion I want, Then I scrub through the recorded data to find what I want and export it. My engine can read that exported data and a simple text file configuration tells the engine how to compile the animation for a character.

So does my recorded looping walk cycle look like? Not bad!

137-0.gif

I think this is only the 2nd time I've modeled a human. I'm getting better at modeling. And rigging for motion capture was certainly an education. (Does anyone enjoy applying skinning weights to vertices?) The models are a work in progress, and I built them as fast as possible to test the mocap. They will likely be edited and different as time goes on. I hope to add hair options, different clothes, skin tone, etc. But for now these models will move the game development forward.

Another toy that deals with motion capture, are motion capture gloves for recording hand movement. Currently my models have mitten hands, but I want it for recording hand positions while holding tools or having palms facing out while the thumb does other things. This way I don't have to go into each animation and decide where the models will be gripping something versus having relaxed hands.

137-1.gif

One cool thing about having the full hand motion capture data, is that I have full finger data, so if in the future I wanted to add the index finger, I'd just have to modify the models, and re-import the animation data. No other work needed.

Once I got it working, (which took most of a week) I made a bunch of test animations and got them into the game engine in around 40 minutes. That includes putting the suit on and setting up, recording motion, exporting to fbx, and configuring import frame ranges.

137-2.gif

(Why is my shadow resolution so low in this screenshot? I was looking at the characters and didn't notice til after I made the gif. Hmm...)

I think I'm still going to need to traditionally animate animals, and I might hire someone for that. But I also now have an animation re-targeting pipeline, so all similar animals could potentially share animations, reducing the work required. Or at least I could get new animals in and working while animal specific animations get built.

The last toy (er, tool) I bought a digital screen drawing pad so that I can use a pen to paint textures and models directly on the screen. Previously I did everything with the mouse, and while that's fine and I have a workflow for it, being able to use a pen directly on a model is pretty nice. Plus maybe I'll get better at drawing too. I don't have any animated gifs to show that though...

View comments »

Designing the AI

16th February 2021

I like designing new code. Especially when I'm starting with a blank slate. I've got the initial framework for AI built now and am slowly testing ideas and fleshing it out. I went through several iterations of design, and I've ended up with something I think will work, and that can grow as the game does.

(The bad thing about new code is it generally doesn't come with screenshots or videos of cool things right away...)

Before designing anything, or writing any code, I went through a bit of time just writing down what I'd like the AI to do in the game. I'm going to list some of it here, plus some of my vision for what the game will be, but remember, game design is fluid and not all my ideas will necessarily end up in what I finish.

What I'm trying to explore this time is a colony simulation that is higher in detail than Banished, with a smaller set of villagers. This includes things like beds to sleep in, each villager owning equipment that's stored somewhere, and having skills unique to each citizen that are needed to make the village work. I'd like to slow down the simulation to days, including time to sleep, rest, work, and join in town festivities, like weddings or annual celebrations.

So here are some things I'd like to see.

Let's say a villager wants to paint her stone house white. But she doesn't have a painting skill. So she'll let the village know what she wants. If there's a painter in the village, he'll do the job, but there might not be paint. So he'll let the village know there's a need for paint. The worker that makes paint gets to work gathering limestone, or white clay, or white flowers, or whatever it ends up being ingredients. He'll make the paint. The painter will later grab it, and paint the house. And if I want the complication, a tool maker needs to make a paint brush first using animal hair and wood. And the animal hair comes from... etc, etc. And then the first villager gets what she wants.

The main idea there is that if you've got the production line and workers setup, the player won't have to manage turning things on and off, or setting limits. The village will just do it as needed. But the player will have the option of specifying that they want to drive production of a certain resource on purpose.

I'd also like to see group activities. There might be large bison-like animals that take more than one hunter take down. So the villagers need to get organized somehow, and then all follow the same plan to get close to one and attack at the same time.

Lastly I want smarter villagers. If you've directed villagers to build a building and you need a log to complete it, it's probably more efficient to cut down the tree that's nearby rather than walk all the way across the village and back to get one. Similarly, if a wood splitter has a store of logs nearby but isn't working to cut firewood, it's okay to grab the log from that location rather than a far away generic storage yard.

My final goal is that all this needs to be data driven and extensible without the need for a full scripting language. After working with it for a few months, I should be able to add new things villagers do and locations they use without modifying any game code. There are certainly a lot of similarities to what Banished had, but that code is too rigid, messy, and not configurable. It's nice to start again knowing what sort of issues to deal with.

So how am I going to accomplish all this? We'll first I need to start with the smallest case and grow. But also keep in mind my future needs. I've also been doing some research to see what others are doing. Over the last year or so, I've read a lot of game postmortems and AI papers on getting AI characters to do things like I describe. There's a few algorithms that stand out. Namely Utility AI, Behavior Trees, and Goal Oriented Action Planning.

None of them are perfect for what I want, but they all have good ideas. So I'm blending and modifying, to get what I want.

The basics of my idea is to have each villager have goals they want, and keep track of how strongly or weakly they want to do them. As the player places buildings and objects, those objects will be able to fill those needs. Each object gives a score to the villager as to how useful it is to perform it's actions, which will be combined with the desires of the villager. Considering all the possible actions available to them, the villager will pick one of the top ones. Objects can also have their own desires. For example, if a location turns reeds into baskets, the location will desire the source materials if the number of stored materials is low. This in turn will cause villagers to consider collecting reeds when needed.

Objects and locations will also be compartmentalized. A boat building area will handle telling villagers how to use it, rather than the villager handling each and every object it can interact with. The object would hold the animations, particle systems, audio, and other resources needed for use, the actions it can give out to villagers, and the desires that it can satisfy. This way, as the game grows, I (hopefully) don't have to modify existing resources to add a new object.

But where to start!? Designing and writing a giant system with a zillion requirements is hard. Without being able to test its parts as you work is very difficult and usually doesn't work. If you try this, as the code expands it shows you where your design falls flat and needs fixing. It's hard to debug, and it's time consuming to change things when you hit the walls of your design. There are too many unknowable design issues to be able to decide on them up front and roll with it. So I like to start small and simple then grow.

I decided to find the simplest thing the villagers will actually do that makes simple cases for everything I want to be able to handle. This took me a while to come up with, because it's not really a focus in the game, but it's still in there. Of course once I thought of it, it was obvious.

I originally thought I'd implement a campfire to satisfy the desire of villagers to be warm. Seems simple, and is a scenario that will play out in many similar ways throughout the game. But it requires a lot of structure all at once and doesn't quite cover the wide berth of ai systems that I want. When the villager is cold, it desires warming up. The campfire can handle that, but it needs to be burning fuel of some sort for that. I could fake that with the campfire turning on and off automatically for testing. But I feel like to continue down that path, fuel needs to be harvested and/or stored and brought to the fire, which requires inventory, and more locations and actions, cutting trees, splitting firewood, or collecting something else that can burn. That's all too complex, and doesn't have an obvious outlet for group actions.

Trying smaller actions villagers will be able to perform was a non-starter as well. Just collecting rocks and putting them somewhere else seemed a bit to big for a start, as it still requires other systems like inventory, carrying things, and an object that can store things. I wanted to be up a running with the ai without writing other systems at the same time.

So what did I come up with? It's idling. That's right, doing sort of nothing. Find places to hang out, pick one based on distance criteria, walk around. Talking to each other, or have a party. I can get things up and running without harvesting resources, needing storage and inventory, or production chains. There's no game there, but it meets the needs of most of what I want to do. And all I had to write is the core AI systems to make it work. Extending it with more things that objects in the word can do should then be easy(ish).

So that's where I am. After my paper design phase and coming up with a plan, I've implemented the basic structure of villagers with desires, objects that can satisfy those desires, and being able to pick the best action from it's weights. It's all data driven. Each object has animations it can hand out to villagers to make interacting with it look unique and correct. Villagers look at what they can idle near, weight it based on distance and pick from the top choices. They can satisfy their own need to idle and wander randomly as another possible action. Currently it seems to be in a flexible space where it will be easy to extend and add features.

Coming up I'll be working on group idling - getting two or more villagers to decide to stand close to each other and play synced animations as if they are having a conversation. (I hope in the future this sort of thing will build friendships and relationships, but that's really getting ahead of myself...) I also want to setup up triggers for group events, where villagers immediate desire becomes attending that event over anything else. I'll probably also add some rudimentary time of day schedule which changes what sort of idling occurs at different times.

That should set me up with a fairly solid foundation for the more complex systems that will be built on top of the desire/satisfaction system. Then it will make more sense to get into the fun game parts where resources are harvested, production lines are setup, and players try to balance everything so that everyone survives.

View comments »

Save and Load

13th January 2021

Does anyone want to know how save games work in video games? Yeah! of course you do! I've spent the last two weeks working on it. In a simulation game you can't get very far testing things without being able to save. I suppose you can, but you'd spend a lot of time recreating the conditions you need to test a new feature or fix a bug.

The basics of saving are pretty easy. You write out all of an objects properties. What model and materials is the object using? Does it have collision and pathing information? Does it store inventory? What animation is playing? What plan has the AI made? When you read it back in, you just take that data, and setup the object again based on what was stored.

Then it gets harder. Let's say there are several hundred objects. And some of them reference each other. An character might have a target that it is following. When the game is running, this is easy - that character stores the physical (well, technically virtual) address in memory of the item it needs to reference. But when the game goes to write that out, I can't write the physical address. It's meaningless. Because the object is probably going to be in a different place in memory when it's recreated on load.

So I have a system where each object is assigned an identifier. It's just a unique number. The first time an object is written out to a save game, the full object is written, and then its identifier. After that, if the object is referenced again, just the identifier is written. When the save is restored, the object is read in, and while the object gets a new unique identifier, the previous identifier is stored in a dictionary with the objects new address. If references are encountered, the identifier can be looked up and exchanged for the new memory address of the object.

Alright, so now save game works! Well, that was it for my last game. But this one is slightly more complicated, and consists of the bulk of my recent work.

Since the game is going to be open world-ish, saving is harder. The first thing to consider is that when the player is far away from some regions, they don't need to be simulated. So when they go out of range, they get removed. But whatever the player has done in the area needs to be saved. So the same save process happens, but just for that area.

A bit of care needs to be taken here, because to save a group of items together, they can reference each other, but they can't reference things outside the area. So the region is disconnected from the rest of the world. I have some safety code that ensures the disconnection - if something goes to write to the save that isn't in the region, that's a fatal error and needs to be fixed before I can proceed.

The game also can't pause to do these types of saves. So after being disconnected, the save process happens in a background thread. This save data is just kept in memory, rather than being written to disc.

The loading process for this is similar. A background process loads the needed resources, all objects and references are restored, and then the region is connected to the rest of the world and the player can then interact with it. This happens hopefully before the player gets near the area so the world appears continuous. There's some safety code there as well - if the player somehow gets too close to the area before the load and restore is complete, a message appears that loading is occurring and the player has to wait.

So when a normal save comes along, all active game play regions undergo the same process as above, anything remaining goes through the normal save process, and all the chunks of memory that were saved for each region are written to disc.

This whole process took a while to get right, and to get all the bugs worked out. One single piece of information not saved, and really strange things happen when a save game loads. For example, I had a bug where a save game would load and all characters would face east and quickly turn to the direction they were supposed to be facing. I had just failed to save out the current direction they were facing. Another example - I was dealing with objects being duplicated, since multiple areas were referencing the same object. That was before I added the safety checks for objects not being written if they were in different areas.

Dealing with references was tricky too. Since objects depend on each other, loading has to be done in three passes. The first pass restores values for each object. That's generally easy. However, there are internal dependencies in an object. Graphics are totally separate from animation which is separate from audio, but a logic controller might reference all three. Since the graphics component might not be loaded before the controller, anything to configure that uses those dependencies has to be delayed. That's what the second pass is for. Finally a third pass is made once all objects are setup so that external references can be dealt with. Like making sure that an animation of a bow pointing at a specific target can be setup to point that way and the initial animation is in the right pose.

Once save game was working properly, I then wanted to deal with space requirements. The image below has 9363 objects placed on it. You can't see all of them, since small ones disappear when they are far away, but they are there.

135-0.jpg

Saving all of them requires 3.7 megabytes! That's around 400 bytes per object! yikes! It seems like a lot, but each object is storing a lot of gameplay data you don't visually see.

Each object has some overhead making them future proof. Each section of an object, (graphics, audio, collision, animation, ai, etc) has a header and footer, version number, and size. This allows me to make sure when the data is read back in everything is read correctly. It allows me to make additions in future versions, read the old data, and setup any new data. It allows me to skip over any sections that aren't needed anymore. It gives me safety when I change code and forget to update the save function - i'll get a fatal error that the code doesn't match the data written to disc.

This large size doesn't seem a huge deal, until I consider that a player might visit 100 such places. I dont want saves to be 370 megabytes. A player might not go that many places or the save might not total that large, but I need to deal with worst case.

My first fix was to apply a quick LZ compression. Since the trees and rocks save data are self similar, there's a lot of data repetition, so that takes it down to 731 kilobytes. That's 5 times smaller, but still not great, and real game data will have much more variety. I've got some Huffman/Arithmatic encoding I can do as well that brings it down another 50% or so, but I had a better idea.

Items placed on the map are known ahead of time. Even if they are procedural, they can be computed. But a player can interact with every one of them, removing them or changing them, requiring them to be saved. So what if instead, I track if a player has modified one of them. Say cut down one tree. Then I can just procedurally generate all but one of them, skippng over the one that was modified. I can store a single bit per object, which tells if the object is placed as it was on map creation, or it's been modified or removed.

If the tree is in the middle of being cut down it's saved as a full object. If it's gone it costs nothing but 1 bit. If it's there it costs 1 bit. All the sudden 3.7 megabytes becomes just over 1 kilobyte, plus a little for any object that is being interacted with.

As development continues I plan on extending this system a little further. I can precompute objects that aren't there initially. For example if you can plant a forest of trees on a plain, I can have the positions precomputed, but the objects not added. When a tree is planted later, it uses one of the available positions. For a while, the tree grows and is stored as a full object. And when it's reached full growth, the bit is changed to have the tree be there on load, and it costs nearly nothing in save space.

This way the majority of the simple objects in an area cost nothing to save. The save game size will be determined as just what the player builds and by the characters that are walking around. Certainly if a player builds 1000 buildings save games will be bigger, but it's unlikely they will do so across many different places.

Saving is one of those things that's so important, and no one ever notices if it's working like its supposed to. So now saving is out of the way, except for nice menus and interface. Hopefully next time I'll be talking about the beginnings of my new AI simulation.

View comments »