Devblog August 2026

Devblogs

General

A big part of this month’s development was focused on the Cesium mod to fix most of the issues regarding MMVS game mechanics, including multiplayer support. I also set up the base architecture for the mini games, redid the QTE and Chat/Notification systems in C++, and did various improvements throughout the project with many optimizations and cleaning tasks.

Note: During this month, the graphics quality is low in many videos because my GPU died, so I used a lower-end one.

Cesium Multiplayer Implementation

TL;DR: Implemented multiplayer support for Real World Exploration Mod with detailed steps for world streaming, fake cameras, and dynamic object replication distances.

────────────

After the update to v0.4.7, I plan to release some internal mods. You might remember the mod that allows players to explore real-world environments using Google Photogrammetry in 3D.
I spoke about it in the devblog of October 2025.

Initially, the tool I use, Cesium Ion, does not support multiplayer at all, so I needed to implement a multiplayer system myself with overrides and workarounds.

World Streaming and Fake Cameras

The main issue was that the Cesium streaming system loads only what is visible in the player’s camera view. And because collisions are set up on the geometry, if you don’t look at specific geometry, it disappears, including the collisions.
As a result, if the players are not in the host’s view, they fall through the floor even if the floor is visible on their side. On dedicated servers this is worse because the server does not have a host player camera view.

To fix that, I implemented fake cameras with custom top-down frustum views. All players and important objects like vehicles spawn with that fake camera to ensure the geometry and collisions are always loaded around them.

The method to configure all this is intentionally quite similar to Unreal Engine’s native World Partition system, so the implementation can be set up in the same way.
More details about World Partition in the devblog of May 2025

Object Replication Distance

This time, this change doesn’t only impact the Cesium mod: the game supports extreme scale differences with extreme distances, but the replication distances were not dynamically adjusted. All distances were hardcoded, X for Cobble, bigger for Talas and so on. Now, the replication distances are dynamically calculated based on the scale of the objects, the use case and type.

That way, if a Cobble player becomes giant, the replication distances will grow accordingly, ensuring that all other players can see what the giant player is doing at far distances.

Conversely, if a Cobble player becomes very small, the replication distances will shrink, avoiding unnecessary network updates for distant Cobble players.

In the previous video I show how the player can grow from the minimum scale to the maximum scale. The animation is still buggy, the next section will fix that. (The environment scale in the UI is wrong btw, it needs to scale x100.)

Character Movement Base

Another issue I encountered was with the character movement relative to an object producing this kind of desynchronization:

In the video, the right player thinks they are walking in one direction, but because the target tile is wrong on the client side, they go in the wrong direction without knowing it.

Explanation:
The character movement in Unreal Engine can set up an object as the movement base: if you are moving on a platform, your position will be calculated relative to that platform. This avoids calculating your movement in world space with big units when you are far from the world origin. It helps with precision and stability of the movement, but also with the networking, which will send smaller values for relative movement.

The issue with that is that the platform needs to have a static ID consistent across the network, or needs to be replicated with a unique ID that the server and all clients can recognize.
And of course the platform needs to have the same position and orientation, or the relative interaction will give different results.

Issue:
This is the issue I have with the Cesium Worlds: the main object has the same ID but the sub-objects created for every streaming tile do not have consistent IDs, producing the desynchronization described above.
It also explains why the player is resynchronized when the player jumps: the server clears the base when the player stops touching the ground, causing the client to recalculate its position relative to the world origin.

To fix this, when a player moves on a world tile, I set the player movement base to the level’s center instead of the individual tile:

This fixes the desynchronization issue and other issues related to the movement base, like the animation script that doesn’t detect that the player is on the ground in the previous videos.
However, we lose the precision and stability benefits of having a local movement base. And at large distances, like on real-world scale maps, this can lead to noticeable floating-point precision errors.

Future Plan:
A better solution would be to set up a world grid with base positions placed around the world with a redirection system, so when the player moves on a tile it doesn’t use the tile as the movement base but the closest world mapping point instead.

World Mapping Redirection Example

Here it is just an example: the player walks on a world tile, but the redirection setting on the tile redirects to the closest world mapping point (F10 in the picture), so the character movement automatically targets F10 instead of using the tile itself.

F10 will have the same ID and position on the server and all clients. I plan to set that up in the future, but I first need to create a clean redirection system because it will be used by other systems, this is planned for a future update.

Btw I also speak about the Base Movement in the Devblog for May 2025.

Cesium Abstraction Issues

TL;DR: Issues I got with overriding the Cesium Ion world reference class to support the world position replication and the workarounds I did.

────────────

It’s fun to fight with code, adding more and more code to finally find a simple solution that solves everything.

With the Real World Exploration Mod, I have to work with a lot of code that I didn’t write myself (the Cesium Ion plugin) and make it work with the game’s multiplayer, VR, AI, and all of the project’s other constraints. At first, I created several class overrides to add my own logic. However, I quickly found myself fighting against the plugin’s original code, which conflicted because very few functions are virtual, so they can’t be overridden. The Wwise plugin has the same problem, but the Cesium Ion plugin is far worse.

To manage world positioning, Cesium Ion relies on a central world reference class that everything else depends on. My initial approach was to override that class so I could add my own networking logic for multiplayer replication, and it worked.
The problem is that my custom world reference has to spawn before any plugin objects, otherwise the plugin automatically creates the original one. On the server I managed to make it work with many workarounds, but the client was much more complicated.

If the server spawns objects in this order:

  • Custom World Reference
  • Dependent A
  • Dependent B

A client with a bit of latency can spawn objects in this order:

  • Dependent A
  • Custom World Reference
  • Dependent B

If Dependent A is spawned first, it creates the original world reference locally, so I end up with multiple world references on a client instance. And I can’t force the spawn order on clients easily.

I started adding more and more code to prevent the original world reference from spawning, or to make the dependent objects switch to my Custom World Reference, but it became a mess and never felt stable.

Finally, the solution was simply to stop overriding the original world reference.
Instead, I created a new controller that manages the networking and controls the original world reference once it exists. If the controller spawns after the world reference, it takes control immediately. If it spawns first, it waits until the world reference exists and then takes control.

Custom World Reference Controller C++

A simple solution that let me delete a lot of code that instantly became unnecessary.

Cesium Macro Collisions

TL;DR: Issue with the macro foot placement on Cesium tiles and appropriate collision shape generation.

────────────

With the Cesium mod, when Talas is extremely giant, I can’t use the Cesium tiles collision because every floor detail and streaming variation makes Talas’s feet glitch. And if I use a flat floor, it will not adapt to the terrain. So I created a new collision surface that adapts to the terrain, which is perfect for achieving a smooth collision shape of the world.

The server calculates the shape once and then sends it to the clients, which avoids multiplayer replication issues with the shape not being calculated the same way on the clients.

I also reviewed the camera culling system so it avoids the floor disappearing when you look down in a giant footprint. But it is still experimental.

Note: the footprints are set up only on the shader side, so sadly the collision doesn’t let you fall inside.

Mini Game System

TL;DR: Early development of a mini game system for managing, creating and playing mini games with custom rules.

────────────

It’s early, but I’ve continued working a bit on my mini game system started in March 2025

For now it’s used only in a private mod using the Cesium mod, but in the future it will be possible for the game master to set up and manage mini games in the game. And it will be possible to create your own mini game with the modding tools.
Example: The game master can start a mini game that will set game settings, spawn Talas in a very aggressive mode, and you will have to survive for 5 minutes.

I created the bases with game states and internal management, then the mini games can use them to create their own logic and score management.

In the mini game I created for the mod, it spawns many micros in the world and sets you as Macro: you control a giant Talas and have to kill as many of them as possible in 5 minutes. The other players also spawn as micros and have to survive.

Mini Game Example in Cesium Mod Mini Game Custom Game Score

It’s a side work to give more control in the future. I have a milestone dedicated to it.
Also no worries, I will not turn MMVS into a Macro Mario Party, this is bonus sandbox content.

New Quick Time Event System

TL;DR: New Quick Time Event system in C++, more stable and future-proof.

────────────

I totally redid my Quick Time Event system.
When you start a game or respawn, you have a button ‘Press Any Key to Continue’. This is a QTE that just waits for you to hold any key for 1 second. In VR, it waits for you to hold the right or left trigger buttons.

QTE System Example

But I got some issues with it: the system was managing different use cases at the same time in a non-modular way. Because it was old code that was hard-coded in the player controller scripts, it was just better to redo it properly.

So I fully recreated the code in C++. It is now fully modular, like my other systems.
I can plug it where I need it with custom UIs and run several QTEs at the same time even if that is not used yet in the game. And I can now create new QTEs with simple config files. (Respawn QTE, Game Entry QTE, etc.)

Moved to C++ QTE System

For the moment, it is just used for transition actions (Respawn, Open Main Menu, Start Game) with key holding, but now I will be able to easily add more use cases in the future.

Chat and Notification System Improvements

TL;DR: Chat and notification system moved to C++ with improved stability and dynamic data support.

Still with cleaning and bug fixes, I moved the chat and notification system to C++. The system is not complex but has many dependencies that I had to fix.

With the new system I fixed bugs with messages that were not sent, and now the message data can be updated automatically and supports dynamic data. You can’t edit a message that has already been posted, but if you change your name it will also be updated in the chat history.

Chat with Username Update

New Graphic Quality Presets

TL;DR: New graphic quality presets with support for machine-specific configurations.

I replaced the “Global Quality Option” with true preset management, and I added new presets, including some specific to machines like the Steam Deck. (I totally stole the idea from Cyberpunk 2077.)

It is no longer hard-coded, so I can add many presets easily now.

Foot Zone Detection Improvements

TL;DR: Improved foot zone detection for more accurate interactions and better AI awareness.

────────────

In the game, when you rub Talas’ feet, the game code will do many abstractions.

  • First determining if the player is in Talas’ zone,
  • Then checking if a player hand zone is in contact with the right or left foot zones,
  • And finally determining the finger shapes on the foot mesh surface to apply the texture changes accurately.

This avoids performance issues by not checking every detail unless necessary, and by creating caches that can be reused by other systems.

On the AI side it just needs to know if the surface is touched and which specific foot is being interacted with. But with previous optimizations I broke the foot-specific zone detection, causing the AI to think both feet are being touched even when only one foot is actually being touched.

So I fixed that issue and made a better-optimized system that will accurately detect which specific foot zone is being interacted with.

The AI now knows if you touch the right or left foot, and it also knows what specific toe or part of the foot is being touched.

Split Scale Control & Slow Animation

TL;DR: More granular control over character scaling and animation speed.

────────────

I added more control over character scaling. I can now separate the scale interactions of the character into the visual scale, the physical interactions, and the animation speed scale.

  • Here, Talas is giant: x1000
  • But the animation speed is slower: x0.25

I plan to add an option to control this in the Game Master menu. For the moment, it’s just tests.
In the future I plan to set up automatic scaling rules based on the environment and player scale.

Example relative to the environment:

  • When a character is scaled under 1, the gravity should scale with the character but the animation speed should stay constant. So it doesn’t break the gameplay when playing as micro.
  • When it is scaled above 1, the gravity should stay constant using the environment gravity but the animation speed should get slower with the scale. So we can feel how massive the character is, like a giant monster.
  • We can also imagine that the environment time gets slower when the player gets smaller under 1.

Of course, all of this will be controllable with options when I add more rules about that.

New 360° Images When Pinned Under Talas

TL;DR: Added 360° images for scenarios when pinned under Talas.

────────────

I added new screens with 360° images when you are pinned under something. If Talas steps on you with his shoes, you will see the shoe outsole and not the bare sole as before. I also added a version when Talas sits on you, or when you are pinned inside his shoe.

In fact, all these 360° images will be removed in the future because I plan to do a true sole deformation with the camera and physics. That is why I took time before deciding to add them. But I think it will take some time before that happens, so for the moment the 360° images are nice.

Big CPU Optimizations

TL;DR: Improved CPU performance through various optimizations, especially in the Wwise integration and digestive system.

────────────

During this month, I’ve been working on a CPU optimization pass.

Wwise Integration Optimization

It is crazy how much the Wwise Integration plugin can be optimized.

  • By default, sounds produce ray traces every 0.2 seconds to check for occlusion. Between traces, the code continuously fetches data (portals, sound positions, listeners, etc.) and transfers it to the occlusion system, which ignores it.
  • When all listeners are out of range, it still performs occlusion checks. When a sound has volume 0, checking occlusion is pointless.
  • Data management is not perfect either, with many useless copies and memory allocations at every frame.

I saw other issues like that before, and Wwise has the same issue as Cesium Ion (though it is better than Cesium Ion): no virtual functions, all properties are private, no way to override the code as you want, so I need to work directly in the source code.

Here I only fixed the occlusion check when the listener is out of range, and I moved from an average of 1.96ms to 0.35ms just with that. (On the image, the orange part was 1.96ms)

CPU Optimization: Wwise Integration Frame Breakdown

Digestive System & Other CPU Optimizations

I did other optimization passes focused on the digestive system, but I also made many optimizations on the entire game.

  • During regular gameplay on an AMD Ryzen 9 7950X, a frame takes an average of 8.9 ms (110 FPS), and around 11.0 ms (90 FPS) in the Digestive System.
  • I also tested the game on an AMD Ryzen 7 2700X. A frame takes an average of 14.3 ms (70 FPS), and around 19.1 ms (50 FPS) in the Digestive System.

The AMD Ryzen 9 is two to three times more powerful than the AMD Ryzen 7, but the game automatically adapts to what the CPU can handle. That is why there is not such a big difference in frame rate.

The following image shows what happens on the CPU side during a single frame.

(You can zoom in and read the white text for more details on the frame parts.) CPU Optimization: Global Frame Breakdown

Of course, it is more complex than that, and the result will change depending on what you are doing, some parts will take more or less time. For example, I was in the digestive system during this frame. If I go outside, the “TagDynamicMeshMorphTickManager” part drops from 6 ms to 0 ms.

Note: With CPU tracing enabled to measure process times, the frame takes longer, which is why it reaches 25.5 ms here.

Slime System Optimization Issue

TL;DR: Details about an issue related to the number of FX systems spawned on Talas’ tongue by the slime system and how I fixed it.

────────────

I did more optimization this time on my slime system, to fix a performance issue reported by game testers when looking at Talas’ head.

My slime system will do many calculations to detect which points can be linked together depending on their distance and other parameters. I already have a strong optimization on that part. I can group several points together and use K-d tree algorithms to detect the distance efficiently.

I already spoke about it in the devblogs of June 2024 and July 2024

The issue is how the system manages the FX and groups of points. Before, for every slime element, I had a SlimeTickManager, a SlimeComponent per group, and an FX system per SlimeComponent.

  • For two surfaces, like in the devblog, the system creates only two groups so only two FX systems.
  • For Talas’ toe jam, I have 9 groups of points that move with the toe bones.
  • For Talas’ jaw with the old tongue, that was only 5 groups.
  • And with the new Talas tongue, I have 90 groups of points so 90 FX systems.

Talas maw with slime system points

The new Talas tongue contains many deformations, so it is normal that I have many groups, but it is totally useless to have 90 FX systems for that. Most of these FX systems will generate 0 slime strands and will just consume unnecessary resources.

It’s better to just regroup the FX. So in the new version I made a true group structure that self-manages the points and locations. And the FX will be updated accordingly for all the sub-groups of the slime component.

Now for Talas’ jaw, I have one SlimeTickManager, one SlimeComponent, 90 slime group objects, and a single FX system.

Also this was the last major thing I needed to do for v0.4.7 on the technical side. The game is stable, optimized, and ready, I just need to do more tests and add some missing sounds.

Flesh Wall Push

TL;DR: You now automatically push the flesh wall around you, and avoid camera clipping issues.

A small addition: in the digestive system, to avoid camera clipping issues, I added morph modifiers that will push the flesh wall around the camera position. It also automatically pushes the flesh wall around you with your character movement.

Those modifiers are pretty complex because I need to counter-animate the digestive system movements, and I also need to make sure that the flesh wall movement doesn’t impact the modifier in an infinite loop.

New UI Widgets

TL;DR: New widgets to see audio bus hierarchy and to support tabbed navigation in the pause menu.

Audio Hierarchy Visualizer

In April 2026, I introduced the new sub-bus audio slider: April 2026 Devblog.

But game testers reported that in the UI it just looks like a buggy offset. So I added a UI hierarchy visualizer to make it clear which sliders belong to which audio bus.

Audio Hierarchy Visualizer

The hierarchy visualizer widget is not specific to the audio, so I will be able to reuse it for other UI elements that have a hierarchical structure.

Pause Menu Tabs

I added new tabs in the pause menu page to switch between the game info, the score, and the chat.

Same for the UI tabs widget: it can be reused for other parts of the UI that require tabbed navigation.

Screenshot Auto Compression

TL;DR: Screenshots now automatically create a compressed copy.

I fixed the screenshot path that was wrong in the chat notification, and I also added an auto compression. With a UHD screenshot here, the .png file is 8.14 MB, and the compressed .jpeg file is 410 KB.

(Btw the freeze is just because I tested this on an old HDD that is dying. It is much faster on an SSD and the compression is almost instant.)

The compressed image is created in a subfolder named “Compressed” within the screenshot directory, and it doesn’t remove the original .png file.
So you can easily share the screenshots without worrying about large file sizes and you still keep the original high-quality images.