Home Creators Posts Import Register Favorites Logout

Content

Hey everyone! You all voted for tiny speck NPCs in the priority poll, and the first speck settlement is was added to the game along with the new soul gathering system. This was a very technical one and I learned a lot of new things building it, so this devlog is going to dig deeper into the technology than usual. Let me walk you through what this feature is, why it exists, and how it actually works under the hood!

Why This Feature Exists

The whole idea of the speck kingdoms and the speck system in general comes down to a few reasons. The first is size content for the player to be much bigger. This world is built on huge differences in size, so I don't want it to only have giantesses and big enemies. I want smaller enemies too, and even super insignificant tiny speck cities. Until now there was nothing in the game that could make the player feel big, because you can shrink but you can't grow yet. The specks change that.

The specks themselves are little medieval technology level characters. As the world expands more and more, I love the idea of tiny settlements and cities with specks inside them that you come upon and view as a gathering resource, which adds to the dominance and submission side of the size content. And this concept was voted on by a majority of you to be worked on, so clearly a lot of people really like the idea of tiny speck NPCs.

Souls and the Power Dynamic

The specks also create a really nice basis for the soul gathering system. I want souls to be a permanent crafting material, something that gets used in recipes across the board as crafting is expanded. The concept works great for power dynamics too: if one speck is worth one soul, and later you defeat an enemy bigger than you and get 500 souls from them, the implication is that this enemy absorbed or stepped on 500 little specks worth of souls. That adds a lot of impact to the overall game mechanics by tying the resource directly into the dominance and size themes.

As the first test of souls in crafting, this update lets you use souls to create XP scrolls. Gather a bunch of souls and you can effectively craft XP, which gives you another way to level up. And the way you get those souls is by stomping on the little specks that run around inside their city.

Why You Can't Just Spawn 1,000 Characters

Now let me talk about the scale of what I was doing in terms of the technology, because it's very unusual for a third person game to have mechanics with hypothetically thousands of characters running around, especially a multiplayer game. I could not just spawn a thousand characters because that would crash anybody's game.

The way characters normally work in games comes from object oriented programming: each object that exists in the world basically has code inside of it, and that code is always running on the player's processor while they play. Twenty NPCs is a lot for most games, which is why they usually cap out around 10 or 15. There are lots of creative tricks to stretch that, like freezing a character's code when the camera looks away and updating where they would have been when you look back. But if you want 500 characters on screen at the same time, all moving, there is no trick in the world that lets every single one of them make its own decisions and run its own code as its own object.

The AI Director

Left 4 Dead was one of the first games I know of that started solving this problem with hundreds of zombies on screen, and Total War games also used a similar system even earlier for thousands of soldiers in an army. The trick is that none of those characters has its own code running inside of it. Instead there is one AI (actual video game AI, not to be confused with generative AI) that Left 4 Dead called a director. The director decides what each little character should do and which way it should face. It's like one central computer controlling a bunch of little pawns instead of each pawn having its own brain.

There are a lot of limitations to this. A normal character with its own code has a perception system: eyes, so an enemy that sees you can aggro and run at you, plus auditory perception and all kinds of other senses. A director controlled NPC has none of that, so the director needs really granular control of everything or the illusion gets ruined. In Total War's case, you have to make sure all the little soldiers follow in formation instead of wandering off, because an individual soldier can't actually see or hear anything and typically doesn't even have its own health bar. That's data that would normally live on a character, along with weapon types, armor values, and so much more. So you generalize: Left 4 Dead just plays a death animation when you shoot a zombie, and Total War gives the whole army unit one shared health bar instead of individual ones.

Vertex Animation: 3D Flipbooks

The second half of the technology is something Total War's developers, Creative Assembly, pioneered: vertex animation.

Normally when a character animates, it works pretty similar to a real person in concept. There's a skeleton inside the character, the animator moves the skeleton to swing the arms and legs, and the game plays that animation back. It's basically stop motion, but all in 3D, and it's how the vast majority of animation works in games and film alike. The catch is that playing skeletal animations uses a fair amount of computing power, usually on the graphics card. Even 50 characters that are completely stupid and do nothing but stand there playing animations can cause serious framerate loss, because every time a hand moves the game is calculating whether it collides with something, how fast the animation is playing, and a million other little skeleton things. There are tricks for this too, like freezing or slowing animations when you look away or syncing them to your framerate, the kind of stuff the Bethesda engine does in Skyrim. But this game is being built for multiplayer, so I really can't get away with those tricks. One player could be looking behind another player, and once you have three or four players in the same area it all gets way too complicated. I needed a better solution.

Vertex animation is that solution. It has drawbacks, but the benefit is that the character isn't using a skeleton at all. The easiest way to explain it is that each character is converted into a 3D flipbook. No collision, no modular parts, none of the things a character with bones has. They just play a flipbook, and you select which flipbook you want them to play, and that's the animation. It's a very high performance way to have a lot of characters playing what look like (and technically are) animations, but they're flipbooks tricking you. Your graphics card basically sees it as a gif, like watching a gif online, except it looks 3D.

Combine an AI director with flipbook characters, and you can have hundreds or even thousands of them running on lower end computers and even mobile devices before problems start. That's exactly what I did for the speck system, and it's why all the tiny specks running around don't have a big performance impact on your framerate!

Rewriting the Simulation in C++

I try to do the vast majority of my programming inside Unreal in Blueprints, which looks like visual nodes and is much easier to work in because you can immediately see what's happening. But sometimes things have to be written out in line code to be super performant, and this was one of those times. The speck crowd is built on a bug swarm simulation framework whose architecture is proven at over 18,000 crawling instances, and I went into its C++ source and rewrote big chunks of it to turn a swarm into a tiny crowd of people because it turns out there are a lot of differences between how bugs and people move!

Since the flipbook specks have no collision (giving them real collision would defeat the entire purpose of making them performant), the AI director has to do the environment detection itself. It's not detecting what's around each individual speck and and is instead detecting what's in the area in general and then updating the direction and velocity each speck should move in. Under the hood, each speck runs a handful of sphere traces per update on worker threads: a short downward floor trace that snaps it to the surface and aligns it to the slope, a forward probe for obstacles, and a forward ground check so they don't run off ledges. The stock simulation traced against everything visible, which makes sense for a bug swarm because bugs climb walls and houses and everything else while people don't. So I created a custom Terrain collision channel and rewrote every trace in the pipeline (the floor snap, the ledge check, the recovery searches, and the spawn placement) to only recognize what counts as actual ground, with limits on how steep of an incline they're allowed to run up, because I don't have wall climbing animations and don't really need them for what we're doing in this game.

Every little bit of performance mattered here because this system has a compounding scale problem. Whatever one speck costs to update is multiplied by how many there are. With 500 it might be okay, but you might have been eating a 0.1 millisecond slowdown for every 50 I added, so I spent a lot of time optimizing the movement code. It's not a perfect simulation, because a perfect simulation would cost too much performance. Sometimes they still float a tiny bit, or clip into the ground a little on an incline, because there's deliberate leeway there so we're not doing super accurate, precise calculations that bog down the performance at scale. Eventually through countless iterations, I hit a sweet spot where even at the player's smallest size you can't really tell any of them have those issues, and that's good enough for me.

Steering, Walls, and (Not) Colliding With You

So how do they get around things like a house, a wall, or a gateway? They will actually run straight into it, and then the AI director detects that the unit is stuck there and tells it to rotate. That's really all that's going on. There's no intelligence behind it. But the way it rotates matters: it doesn't snap instantly. The speck commits to one turn direction and keeps moving while it rotates, holding that direction until the path ahead has been clear for a moment, with the turn speed scaled to real time so it stays smooth. That gives much more natural movement. Instead of running into a wall dead on and coming to a dead stop, they tend to slide along it, which looks a lot better.

They also deliberately don't collide with the player. I originally had that working, and you'd think you want them to collide with your feet, but it looked bad. When you think about how you move in a game, your feet can be in a lot of different locations very quickly when you're running and sprinting, and the AI director's updates for all the little units are slower than that, so it led to too many weird looking problems with specks clipping into your feet mid turn. It's actually better that they run through your feet, and honestly, from the perspective you see them at, it mostly looks like they're crawling under and running between your legs anyway. So that was one thing I developed but ultimately decided not to use because it just felt bad.

Where foot collision actually matters is the stomping, and for that I only use collision at the moment the foot comes down! >:3

Squishing and Collecting

Here's the loop of the logic itself. The player plays the stomp animation, the foot comes down, and an invisible sphere spawns really close around the foot. If any speck NPCs are in that area, they get soul collected. Again, these little NPCs don't have true collision, and what determines whether they're collected is the AI director knowing where all of them are. So really, the player creates the collision and then just asks the AI director: are there any specks under my foot? If yes, delete them. I also exposed the live population numbers (how many specks exist and how many have been squished) from the C++ side out to Blueprints, so the gameplay layer can track all of this.

Once roughly 75% of them are collected, all the rest immediately clear out, and this is for a couple of reasons. The first is gameplay feel because if you clear out 500 of them and there are only 20 left, running around trying to step on each of those last little 20 becomes very annoying. Up to around 75% it plays like diminishing returns, which I think is good because you get a lot collected quickly, and then it gets a little harder and harder if you want more. Beyond that it just felt way too annoying. The second reason is just in case. If some of them get stuck in a wall, in a house, or in some kind of weird collision situation, that's okay, because you should still be able to collect up to 75% of them. And if you somehow can't, there's also a hard respawn system where after a certain amount of time they all respawn anyway. The little specks are a renewable resource. Muehehehe.

Multiplayer Design

Multiplayer was a major hurdle in this implementation. Think about 500 little characters running around... just the data to update their locations and rotations to a server and then out to every other player is A LOT of data, and it's not really important data. If nothing else, there are probably more important laggy things happening, and you don't want to clog up the bandwidth with all that useless information.

Once again I looked at the Total War games, because their multiplayer is one of the best examples of this. In those games, Player A can set their unit sizes to small and have 50 soldiers per unit while Player B sets theirs to large and has 150, and they're both playing in the same match watching the same units fight. The difference is the AI director scaling what's happening to each player's settings. In short, it's a simulation.

So the position of each little speck is never updated to the server and sent to the other players, because it doesn't need to be. Each player's computer simulates its own speck positions and rotations, with its own local AI director tracking location, rotation, steering, and that kind of information. The AI director on the server is responsible for how many specks have actually been collected, and the counts synchronize between players every so often so there's some similarity in what everyone is seeing, but exact locations just aren't necessary. It's a tradeoff, and I could definitely see other types of games wanting those locations to be exact, but for the scope of collecting little specks in little cities, this was an easy decision once I broke down the pros and cons.

The Art of the Specks

The vertex animated speck characters use some very low poly assets that look totally fine when you're way up high. There are roughly six different models with roughly four animations each, so you're multiplying four by six for all the different possible flipbooks.

On top of that, I edited their materials so the AI director adds variation to the colors of their outfits, which multiplies the variety even further. There are a lot of possibilities with the little tiny specks running around if you ever actually want to look closer at them. They're not all the same exact copy pasted character, and I think that worked well.

Specks aren't the only Bugs

There were many, many, many bugs while working on this, too many to really go into, because building a system where one brain controls 500 people is just asking for things to break.

One of the most annoying issues was specks spawning in a pile at the center of the world at coordinates 0,0,0. It turns out that translating locations accurately in such a huge map produces some really big numbers, and the specks are so tiny that the engine's built in ground detection kept failing at our scale. Whenever the placement trace couldn't find valid ground under a speck, the fallback location was a zeroed out coordinate, so even though all my math was right and everything was set up correctly, everything got dumped at the center of the map. The specks are just so tiny, and the map so big, that I basically had to build a new positioning math system inside the plugin to tell Unreal exactly what to do. It has longer, terrain aware placement traces sized for the specks, logic that reads how deep a speck has sunk into a rising slope between updates and lifts it back out, and a sane fallback at the spawner instead of the middle of the world.

Then there was an issue where specks would sometimes fall into the terrain and end up under the ground. They don't really have gravity, it is just that the AI director just keeps making them drop to simulate that they should eventually land on something, and having it rain specks under the ground that the player will never see is a bunch of calculation that is not necessary. So there's a simple fallback where if one somehow gets pushed into the ground and can't find valid footing for a couple of seconds, it just gets respawned back at its normal location.

And there were lots of issues with spinning. Just orientation with rotating them so they don't instantly snap where the simulation runs many internal updates per rendered frame, and early on a blocked speck could complete multiple full rotations between two frames you actually see, which looked like wild spinning, so the turning had to be scaled to real time. Sometimes you'll still see one instantly snap if it runs straight into a wall for a second or more, but for the most part they smoothly rotate and steer now, and that took a lot of fine tuning. There was a lot of math with coordinates and rotations, and I've realized over time that anything to do with size involves a lot of math. It's a very mathematical kink. >:3

What's Next

The whole idea with the speck system is to be a framework that can be expanded on, where the hard technical stuff is done so content can be added later. As we work on more new areas of the environment on the Asian style island, I want to add several more tiny speck settlements, distributed so that no matter where you spawn on the map or more where you decide to build your base, there's some kind of speck settlement around where you can go gather souls. I also want souls to be something you gather from enemies as well, not just specks, with the speck cities being the starting resource area for them. I'd definitely like to expand the specks to be more integrated into actual crafting too. A speck terrarium where you harvest their little souls every once in a while is a really cool idea I want to get into when I expand the system. And with the vertex animation setup, there's always the possibility of different types of specks and different architecture styles. Whether we focus on any of that is really going to be up to everybody to vote on in the polls when I'm ready to work on more speck related things.

Thanks for the support and for voting on what gets built. This one pushed me into a whole new layer of technology of adding mass crowd systems to a SURVIVAL GAME and I'm really happy with how it turned out. ❤️💜 Join the Discord!🎮 Don't already have the game launcher? Download it here!

❤️ Thank you so much for your support!

Files

Comments

Blingorp Svenorp

Insights from Goddess Nae's mind : Full of pilk, Star war, Pizzer, and the entire script for The Nightman Cometh. Thank you Goddess Nae for these words of wisdom!

Shina

Thank you for this insight. It's always an interesting read on how you solve "problems" (if they can be called that), I'm sure there is a lot of ways to solve the same task, and you seem to have come up with what seems like a good one that runs good. A little off topic: I was wondering, you keep talking about building it up for multiplayer, but like you said, this speck ai run locally on every client (even in a multiplayer scenario). At which point do you plan on using servers to run the worlds? Even if just a localhosted server to simulate server infrastructure? Or are perhaps the version we playing now already a localhosted server? :P

Nae's GIANTESS SURVIVAL SIMULATOR

Thank you Shina ❤️ multiplayer will start with dedicated servers because of the size and scope of the world and to avoid player tethering. Local hosted (or listen server in this case) has more challenges and I can't decide how to approach it fully until dedicated is working first. As far as WHEN, it's going to be awhile because I am focusing on getting content done and core systems first as a technical reason. And to be fair to supporters of the project, I want to make sure there is a working process for others to help with things like environment expansion and possibly enemies first because it will take a few months of dedicated work for me to build the dedicated server and I want to make sure content is still being released for supporters during that time.

Milk-N-Potatoes

Modern Total War games actually do have individual entity health bars! Starting from roughly Rome 2, they do it that way. And you can take my word for it, my profile pic is literally the chad himself, Balthazar Gelt.

Nae's GIANTESS SURVIVAL SIMULATOR

Hehehe, that's true. I've done some TW modding and the general principle as relates to multiplayer is my point. The total health bar for the unit stack is what informa the individual character online, otherwise setting your unit size to Huge would give you a massive advantage against someone that played with theirs set to Tiny.

Milk-N-Potatoes

Interesting. I've not done much multiplayer. The few times I have we all had the same unit size setting, so I didn't even have the opportunity to test how that would work, let alone try to.