Nae's GIANTESS SURVIVAL SIMULATOR - Devlog - Making Multisize Goblins Scale During Gameplay — page 1
/ 5

Nae's GIANTESS SURVIVAL SIMULATOR - Devlog - Making Multisize Goblins Scale During Gameplay


infoAbout This Title

Hey everyone! This update was a big milestone for the game. On the surface it's "a goblin you can fight." and under the surface, it's the foundation for every NPC that will be added to the game. I want to walk you through why I built it this way, what it means for gameplay, and the technical rabbit holes I fell into along the way (there were several) A quick note that this devlog will be much more technical and nerdy than my previous ones because almost everything I did to get these systems working was heavy math. If that doesn't scare you then read on!

Why a Size Changing Enemy is Important

I could have added a normal, fixed size enemy in a fraction of the time. But this is a size game, and I've learned from every system so far (player shrinking, the giantess, mounts) that retrofitting size support into something built at one scale is a nightmare. It's much better to build size awareness in from day one than to bolt it on later.

So the rule I set for myself was simple: this stuff has to work at any scale you can reasonably fight an enemy, from 0.1 and up and everything attached to it (AI, combat, sounds, animation, saving) has to work at every point in that range.

Their health, movement speed, and damage all scale with their size, so small goblins are fragile but quick and hard to hit, while big ones soak damage and hit like a truck. Their footsteps and even how far away they'll notice you all change with their size too. You can run straight between their legs if the size difference is great enough too!

Because fighting things at wildly different heights broke the old combat, your character now fights differently also. Your melee swings follow your camera. Look down at a tiny goblin and you'll swing down at it. Look up and you'll swing up. Damage lands toward the center of your crosshair much more reliably than before though it does depend on the actual swing pattern of your weapon.Just like the mount system, this update was really two things: a goblin you can fight, and a framework that supports every enemy that will be added to GSS. New enemies from here are new assets and new tuning and not new foundational engineering.

The Dynamic Size System

The most important thing about this system, and the thing that shaped every decision in it, is that it was carefully designed for runtime size changing. It doesn't just set a size once when an NPC spawns and forget about it. An enemy can change size during gameplay and everything responds. That's what makes it ready for size changing effects down the road, whether that's size magic from other enemies or players growing and shrinking NPCs themselves. It's also fully save game compatible, so an existing enemy will spawn back in at exactly the size they were when you saved.

Mechanically, everything hangs off a single replicated size value on the enemy. When that value changes, it fans out to every system that cares. That sounds clean when I write it in one sentence. In practice, "every system that cares" turned out to be almost all of them. Here's the full tour!

StatsHealth, movement speed, damage and all stats all scale with size. This required a refactor of many stats that were previously set in stone and basically read from a spreadsheet to instead be connected to formulas and multipliers that get their base value from the character's size. Size isn't cosmetic in this game... it's a full stat sheet multiplier. Blackboard AIFirst, a definition: The blackboard design system in Unreal Engine is a data storage asset used by artificial intelligence (AI) systems to hold memory and state variables, serving as the central hub where data like target locations and line of sight statuses are read and updated. This is not to be confused with generative pattern recognition and machine learning models which are disingenuously marketed as "AI." Blackboard is what games have used for over a decade along with a full suite of perception subsystems to allow real artificial intelligence with preprogrammed events as basic as a zombie attacking to as complex as managing relationships in RTS games. AI Distance ScalingThe melee AI reads distances from the BB_Base blackboard, with values like MeleeDistance written in through SetMeleeDistance, and the combat logic lives in BT_Sub_Combat_Melee_Base with services like BP_AI_Service_Action_Attack deciding when to swing. All of those distances were authored for same size characters initially. A 0.1 scale goblin using default values would start attacking you from what is to her, a football field away and her damage trace would reach straight through you.

So every distance now scales with the character's current size, and their attack range scales down with their body so a tiny goblin has to actually be at your feet to hit you. An annoying gotcha along the way: the stock BP_AI_Task_MoveToTarget task was silently forcing Use Blackboard Radius back on at runtime, overriding everything I configured on the behavior tree node. Nothing I changed in the Details panel did anything until I opened the task blueprint itself and found the line resetting my values. Capsule Scaling and CollisionDistance checks between characters of very different sizes need to compare foot positions, not capsule centers, or a big character "standing next to" a small one reads as far away. I built a pure GetFootLocation function that grabs the character capsule and also falls back to actor location for any characters in the future that may not use a standard capsule. The surprise here was that Get Scaled Capsule Half Height returned the same value regardless of the actor's scale, because the capsule wasn't inheriting it the way I expected. The fix was Get Unscaled Capsule Half Height multiplied by the actor's Z scale, which gives the true world space half height at any size. Collision behavior also changes for very large enemies: their capsule stops being a solid wall to smaller players / NPCs, so instead of bouncing off an invisible cylinder, a small player can run right between a huge goblin's legs instead of colliding with an invisible wall under them.

Animation Height Offsets

This one I didn't see coming. When I would change a goblin's size, suddenly she'd be hovering above the ground. The animations I used had a built in vertical offset that's correct at normal character scale but amplified in either direction by clipping or floating with any significant size change. I had to choose between manually adjusting literally every goblin animation or solving it with code so I chose code.

The fix was a custom height offset function that adjusts the mesh position based on current size, so every animation sits the character's feet exactly on the ground at every scale. This is the enemy side sibling of the terrain problem I solved for mounts. Nobody notices when feet touch the ground but everybody notices when they don't!RagdollsKilling a resized goblin exposed another fun one: the ragdoll would snap back to the original sized body, so a big goblin's corpse would shrink on death, or a tiny one would stretch out into a full size ragdoll like some kind of body gore horror movie. After some research and testing, I figured out it was because the physics state was still holding onto the old body. The fix is to reset the physics after each size change so the ragdoll always matches the body it belongs to so it doesn't stretch or shrinking when the body physics are activated. Footstep Sounds & EffectsCrossing size thresholds swaps between entirely different footstep sets using the same preset swapping pattern the player already uses when changing footwear. Really big NPCs get a dedicated set of booming footsteps with bigger footprints. The idea is that if something huge is walking nearby the ground should tell you!Randomized Outfits and Cloth PhysicsGoblins now roll a randomized outfit when they spawn so a camp of them doesn't look like a clone army. I designed it to be fully multiplayer safe (every client will see the same goblin wearing the same thing) and works at every size, since the outfit pieces scale with the body. The hard part was the cloth... The outfits use cloth simulation, and cloth solvers really do not like the mesh changing size underneath them DURING simulation. All kinds of weird stuff like physics crashes and the cloth briefly thinks it's been stretched across the map then snaps and flails. The fix was a custom runtime function to reinitialize the cloth simulation whenever the scale changes so the solver rebuilds its rest state at the new size instead of trying to spring back to the old one. Saving and Loading Sizes If a goblin was huge when you saved, she's huge when you load, even if his size was changed during gameplay. The saved player transform already carries Scale3D, but the goblin's size needed its own path, so it survives through the save data functions (GetFormattedVariables_BPI and LoadData_BPI) rather than risking changes to the save blueprints themselves, which can corrupt existing saves. I also lost some hours to an incredible Unreal Engine oversight here... just double clicking an interface event in the blueprint's Interfaces panel silently converts it into an empty function override that shadows the parent's working function BUT DOESN'T RUN THE CODE. It has no warning or dialogue pop up at all would show and it would quietly brake the entire save chain so I felt like I was going crazy until I figured that one out.

Player Aim Offset

I found it was necessary to revamp the entire player melee damage detection system in order to work reliably with different sized enemies. You will notice that your character now swings their melee weapon in the direction you're looking and damage toward the center of your crosshair is much more reliable, though it does depend on that actual swing pattern of your weapon!

The core concept is that aiming the visual and aiming the hit are two completely different systems, and both had to be fixed or you'd get a swing that looks right and connects with nothing. Melee damage isn't dealt by the animation. It's dealt by a trace fired from BP_Notify_TraceDamage during the swing, which calls TraceDealDamage_Server on the character. That trace used to go straight forward off the character no matter where you looked which would cause the player to whiff on a tiny goblin at the feet.

On the visual side the answer was hiding in a system the game already had. Bow aiming already bends the spine to match your camera pitch, because bow animations route through the Shooting slot, which carries the AimOffsetsStateMachine that offsets the spine and arm bones. Melee attacks were playing in the UpperBody slot, which explicitly strips aim offsets. That routing difference was the entire reason bows aimed vertically and swords didn't. For truly tracking targets like tiny enemies, I went further with a custom plugin Aim Look Solver, which procedurally bends the spine and the swing arm's bone chain toward an actual world space point rather than a prebaked blend, gated so it only activates in the melee stance.

The trickiest part was the aim origin. The aim ray has to start from the character's chest, and my first instinct (a fixed height offset) breaks the moment the character changes size. Because at 2x scale the chest is twice as high. GetActorLocation doesn't save me either, since it returns the capsule center around waist height and doesn't track scale at all. The correct answer is reading the actual spine socket location with Get Socket Location, computed on the character on the game thread and cached into an AimOrigin variable the animation blueprint reads back. The socket scales with the mesh for free so the aim origin is always exactly at the chest no matter what size anyone is. By the way I discovered some interesting game crashes by trying to run this on the AnimBP's threaded update directly.

The swing now traces along where you're actually aiming on a dedicated trace channel for melee hit detection so the sweep responds to exactly what it should hit and nothing it shouldn't, with a generous sphere radius because pixel perfect melee against a small fast target is frustration, not challenge in my opinion. Since the visual swing and the damage trace are now built from the same aim data, what you see and what connects finally line up by construction.

What's Next

The exciting part is what all this math nerdery unlocks. More enemy types on the same size framework, with different bodies, behaviors, and stat tradeoffs. Items that grow or shrink enemies during a fight, which the replication work was specifically built to support (imagine shrinking a threat down to stompable size, or the reverse happening to you). And size as an actual combat dimension rather than just a visual, where a creature's scale changes how you have to fight it. As always, my focus stays on core systems where I can make the most impact on the gameplay.

If you want to see this kind of work happen live, I build a lot of it on my development streams, and will be streaming quite a bit more environment work going forward as well. Make sure to check the Twitter for streams!

Thank you so much for the support and for voting on what gets built. Please tell me what enemies you'd like to see next! I read everything from comments here and in the Discord feedback channel. Join the Discord! Don't already have the game launcher? Download it here!

Thank you so much for your support!

groupArtist

Nae's GIANTESS SURVIVAL SIMULATOR 1k+ Nae's GIANTESS SURVIVAL SIMULATORverified photo_library2 albums visibility5.5K views View Profile arrow_forward

Comments (0)

1000 characters remaining

No comments yet. Be the first to start the conversation.