May 2025
General
…
Stuck Zone Offset Net-Code with Based Movement
Yay, 10 months to find a correct solution.
MMVS is a multiplayer game, so the code needs to replicate some data between the server and clients.
For the micro player, the game will check the position difference between the server and the client side and resync if needed. This is nice, but not with my Stuck System when the player is grabbed by Talas or stuck to the sole.
Talas’ animation can’t be perfectly synced between server and clients, so the micro character position will be resynced constantly, causing bugs like this one reported by testers:
In previous versions, I made a brute-force hotfix to force the client character to keep its position. That worked, but it wasn’t good for CPU usage and netcode, and it became obsolete with new features like character root motion and offsets in the Situation System.
I was able to fix it using a small hack. The engine code can use “based movement”. It allows the character’s movement to be based on an object. So when the character is on a moving platform, they move with the platform.
The nice thing is that when it’s used, the netcode syncs the character’s position relative to the object instead of the world position.
That means if the platform movement is out of sync, the character will not be moved to the server platform position, but will stay at the same relative shared position to the platform.
So I used that to force the netcode to use the relative position, and I used a custom movement calculation to prevent the character from moving away from its attachment. In the video, the red is the server position, the blue is the local client position.
I added details here: use-relative-character-replication-when-attached-resolved
General Update Situations
This month I worked a lot on the situation system.
I’m very happy with how all my systems work together now. Also, now that I usually do tests and automation in stress test maps, I can quickly see when something doesn’t work after a code change, and it saves a lot of time.
Specifically, modifying the movement code with the Stuck Zone System caused several conflicts with the situation system at the movement management level (I talk about it in the next devblog).
Like with the Stuck Zone System, I created a custom movement mode with code specific to the Situation System, also using based movement.
So, this allows me to remove old code and make a better netcode.
Here, Talas’s position replication uses the relative location from the sofa and not the world absolute location.
Cleanable Footprints and Shoe Footprints
I updated the footprint replication for better optimization.
Before, at every Talas step, the server had to replicate the position of the footprint, the type of footprint, and some information like the textures to use, the time for dispersing, and that kind of thing.
Now the server replicates only the position and the config ID, and the client will use the config to know what texture to use and other parameters.
Also, totally random, I added interactions to clean footprints because why not?
And I finally added footprints for the shoes.
For the shoe, I used a generator made in Blender, using the shoe render on the Compositing Nodetree.
It’s better than doing this by hand, like I did with Talas’s footprints in the past.
Character Config and Game Modding
During the weekends, I like to work on side projects. This time, I wanted to make progress on the character config and game modding.
I started to move the management of the character configuration outside the main character script, into a side module, so I can manage main actions inside.
With this, I avoid external modules having dependencies on the character when they just need to get character config info.
What’s nice about this is that it’s possible to do modding with assets and code injection in the Local Character Modification module before the official in-game modding update.
I don’t know how to do that, but here is some info if you want to try: Character Modding (Code Injection Notes)
Extra Game Content and Character Modding
I cleaned up my SVN repositories to separate the main game repo from additional content repos. This way, I can test game files without adding content that doesn’t belong to me in the main game repository.
Now I can test the new Local Character Modification, here with Vik’s character (3D model by Tosador, edited by Dvorakir).
Animation quality: 12/10. ⭐⭐⭐
For tester builds, extra game content like the Vik model is included, but not for public release builds. You will have to wait for the game modding update for that.
If you remember, in previous versions, I added cheat codes to swap macro and micro models using raw configuration sets.
But this was an explicit model replacement without retargeting, so the result was very bad.
Normally, Cobble and Talas each have their own animations. If I play Talas’s animations directly on Cobble without using retargeting, the result looks wrong because the models have different proportions and skeletons.
Retargeting is the process of adapting an animation from one character to another, so it fits correctly.
Here, Cobble uses Talas’s animations without retargeting:
For the Local Character Modification, I don’t just replace the model, I also retarget the animations using the IK Rig Retargeting from Epic Games.
Here are the first tests:
As you can see, there are still some animation issues (which I fixed later).
Even if I don’t work on it technically, the goal is to be able to use all of this in the Game Modding update, with any character type, VR Chat, or other models.
What’s nice about the Local Character Modification is that it’s possible to change other elements like the footprint textures, FX, sounds, etc.
I would like to make an explicit distinction in-game between cosmetic and non-cosmetic mods:
- Cosmetic mod: Affects only the visual aspects, like the model, textures, sounds, etc. It can be used in multiplayer without other players having the same mods.
- Non-cosmetic mod: Every player must have the same mods, because it can change gameplay elements like hitboxes, damage, etc.
To continue my tests with Modding Characters, I added a new Debug menu to apply character configs or set mod configurations.
It’s not only for config and character modding: I also made progress on how the game loads assets and actors dynamically.
This menu will be available in the next version, but it will not include Vik because it’s just for testing.
For now, the game mods can be set only on the server side (cosmetic mode or not), and it applies to all characters, server and client. I plan to add more control in the future.
I also added an invisible mode and spotlight mode for the game master, just for fun.
Because I love unique and creative characters, I tested Vuin’s character (3D Model by ZealotDKD).
This time the retargeting is more advanced: the animation can handle custom poses and overrides, like facial expressions here, and the modded animation script copies the upper arms with a delay to animate the lower arms.
The eye shader was complicated to reproduce, but I like how it looks now.
And of course, I made a macro version too, haha.
Shoes Fix
Just to show how everything may be connected in game development:
- This month I worked on the shoes to fix a replication bug.
- For that, I needed to work on the shoe script and how it manages the visibility switch.
To optimize, I have two shoe models: one for animation and one that follows Talas’s paws, and the game code switches them in one frame.
Since this changed a bit, I talk about it below. - But a bug made the switch too visible, so to fix it I had to work on the shoe animation scripts in-game.
- That’s why I worked on the animations in Blender.
- While working on the animation, I noticed a bug with my shoe rig, and to fix it I’m working on my Blender rig script.
- And because of that, I needed to work on my script libraries used by my Blender addons.
Also, the shoe rig now uses the new curve system I made for Talas’s tongue rig.
In the next video, I finished the right shoe strap animation when Talas wears his shoes, but the left one is still broken. Same for both when Talas takes off his shoes.
Sadly, this takes too much time and I want to release v0.4.5.1 soon, so I will fix that later in a next version.
After that, I fixed the animation script and the netcode issues.
I also added IK support, so the shoes will adapt to the ground like Talas’s paws.
And I added a new visibility mode with static meshes when the shoes are not in use.
- Static -> When the shoe is not used.
- Animate -> When Talas wears or takes off his shoes.
- Follow -> Follows Talas’s movements.
I like that the visibility mode switch is almost invisible.
The new static visibility mode for shoes gives better CPU performance, and with Lumen rendering, it gives better results when you don’t use hardware raytracing.
Damage Management and Difficulty
After more debugging, I realized that my damage management system was flawed, so I completely reworked how I handle difficulty and damage.
The fact is, many values were hardcoded in the code, and I didn’t really make a distinction between damage and difficulty.
For example, before, if Talas stomped on a micro, the game would apply -200 in Realist, -80 in Normal, and -16 in Safe mode, depending on the difficulty.
Now, Talas will always apply -80 damage on stomp, but if the micro is a player, the game will override the damage or apply a damage multiplier depending on the game difficulty.
Now all damage values use config files specific to each character (Cobble / Talas), and difficulty also uses a config file for each difficulty mode (Realist / Normal / Safe).
I also made a debug menu, here are the current values:
Oh, by the way, being in or under a shoe will now impact the damage.
Bug Search
Here’s an example of how bug search can be awful:
Talas’s step animations are buggy, but only in standalone game, in multiplayer, and on the client side. Like here in the video.
Because it’s standalone, I can’t use the editor tools to track the data and debug at runtime…
So I created a script that shows the data I want to debug with 3D arrows. I do tests, add more data, and restart at every test.
- First, I see that the animation values like the play rate or alpha blend are wrong.
- I search deeper in the animation math functions that set those values and notice that the issue comes from the velocity that comes from the character script.
In fact, the velocity is normal, then switches to zero and back to normal at regular intervals. - In the character, I disable all functions that set the velocity except the physics engine one, but without result.
- I continue to search and disable random functions in the character script before I find that disabling the character startup config set fixes the issue.
- I search deeper in the character config set and I disable all config updates one by one, restarting and testing after each change.
- After many tests, I find that it comes from the foot interact data config used to spawn the footprints, FX, and sounds.
- So I disable the footsteps interactions to find it comes from the footprint spawns.
- And finally, I find that in the footprint object used for Talas, I forgot to disable the collisions.
So on the client side, the character is stopped by the footprint collisions at every step, the velocity is set to zero, but the movement isn’t stopped because the server resyncs it.
In the video, the first Talas uses footprints, the second does not.
4 hours of bug search to disable collisions. Nice ? ?
It’s often the most complicated bugs to find that are the easiest to fix.
Because of issues in the desert map, I had to review how I manage teleporters and certain gameplay objects to avoid game crashes.
The desert map is managed like an Open World: distant objects disappear and reappear when you get closer.
So I have to save specific properties before the object disappears and apply them again when it respawns, like the orbs or doors.
Unreal Engine’s World Partition uses a streaming sources method. This allows loading elements of the world in specific zones without having to load the full world.
Here, the player zone or important NPCs like Talas’s zone is always loaded on the server side.
Some elements, like vehicles, will also have a streaming source to avoid falling under the ground when the player goes too far.
That way, vehicles have time to save their state with minimal information before being automatically destroyed when the player is too far away for too long.
When the player comes back, the vehicle will be respawned and the state will be restored.
Please note: When I say “Open World”, it’s not to say a open world game like GTA or Ubisoft games.
I mean the techs used for open world games, like the World Partition used for the desert level.
In fact, the game is already an open world, Talas’s house with the small size of the player is very big, but the full level is always loaded.
For the desert level, the world is partially loaded, it will stream only the needed zones using Unreal’s World Partition system.
To optimize and add more content, I will also update Talas’s house to use World Partition in the future, with the “Talas House General Update”.
Road Map
This month I also totally refactored the orb management to support World Partition.
About the orbs: the game needs to know how many orbs exist at the start and how many remain in the level.
Before, all orbs were forced to spawn without taking into account the zones loaded by the World Partition.
This allowed me to easily manage multiplayer replication and retrieve information such as the number of orbs directly from the orb actors.
But that’s not the correct way to do it with World Partition because these objects are never unloaded.
Now I use an Orb Manager that caches data like orb spawners and manages replication, such as which orbs are taken. This way, it’s not dependent on the level. It’s a bit like a world save file readable by the server and the client and everywhere in the level.
- Example: in the video, I teleport to an unloaded part of the level.
- The World Partition loads the orb spawner, and the orb spawner checks in the Orb Manager if the orb was taken. If not taken, it spawns it.
- Then I try to take the orb. That will communicate the info to the server, and if successful, the orb spawner will tell the Orb Manager: “Hey, my orb was taken.”
- The Orb Manager will update its list of taken orbs and replicate the info to all clients.
- Then I leave, and the orb spawner gets unloaded. (If the orb is not taken when unloaded, it despawns the orb with it.)
So everything works with the Orb Manager on Server/Client and the World Partition can unload everything without issue.
To fix a bug, I had to revise part of the AI’s perception code. Most of the time in games, an AI will trace a ray between its head and the player.
If there are no obstacles in the world between them, then the AI assumes it can see the player.
In MMVS, AI perception is quite hybrid because it works in both ways, but I did some changes.
Before, the AI would detect if the player is visible, as explained above, but it would first take their state into account.
For example, if the player is pinned to the ground or stuck under Talas’s paw, then they must be considered invisible, unless Talas explicitly looks at his sole, like with the “check sole” animations.
This logic works, but poses several problems because it is conditioned by many elements.
Since Talas is a macro, I can allow a much more advanced verification that will take Talas’s body into account.
- Now the Macro AI will take the player’s state into account with simple parameters like “Is Invisible?” “Is Pinned?”.
- It will then detect whether the player is visible by detecting obstacles in the world.
- And finally, it will detect whether the player is obstructed by a specific part of Talas’s body, such as the paws in the next video.
This allows game logic that is more organic and not pre-conditioned by the animations.
Now you can literally hide behind Talas’s legs. Nice for unaware gameplay.
See more: Devblogs - Wips Telegram Chanel - Discord Chanel - Support the game - MMVS game