DevBlog #66 | Foundry Fridays: Streaming Proxies

FOUNDRY

Build a factory optimized to perfection or an artistic masterpiece in an infinite voxel world. Mine and harvest resources, automate your ever-growing production lines and manage complex systems while researching your way to mechanical mastery in FOUNDRY.

Hi there. Today I want to talk a little bit about the work that we're doing to try and improve streaming performance in Foundry. [h2]Current System[/h2] Similar to many other Unity games, Foundry is built in Unity and most entities in our game are represented by GameObjects. Some of the performance challenges that come with using game objects include: - You can only create/destroy GameObjects on the main thread. - You can only enable/disable GameObjects on the main thread. - GameObjects and their components are dynamically allocated meaning that their memory is all over the place and not cache friendly. - GameObjects use a lot of memory. [h2]Option A: Object Pooling[/h2] One of the solutions many games use is object pooling. This is when you preallocate pools of gameobjects and just enable/disable them as they come into streaming range. We actually use this already for some portions of the buildings but there are several challenges with using this strategy for all the objects in the game: - It's difficult to choose how many of each item to have pooled. If we want perfect pooling, we would need to have enough gameobjects in the object pools to handle the player walking in any arbitrary direction and we only have a little bit of time on the main thread available to grow those pools when necessary. - GameObjects use a lot of memory. If we needed to have a significant amount of objects pooled, the memory costs would grow quite significantly. - It is still quite expensive to enable/disable objects, especially ones with deeper hierarchies where unity has to iterate the hierarchy and enable/disable all the components. - Implementing game object pooling is fairly simple to do but converting all the game code to work with object pooling can be quite difficult and lead to very subtle bugs, not just for all the existing code, but for any code that anyone on the team writes in the future. It effectively would add a 'development tax' to all current and future development on the project. [h2]Option B: Unity ECS[/h2] Another solution games will use is Unity's ECS system. Though using Unity ECS would solve many of our issues, the main issue with the unity ecs system is that Foundry was in development for many years before the 1.0 release of Unity ECS and switching the entire game would require a significant rewrite of the entire game. It would be possible to use it for only certain systems but this would mean we would have two entity systems which would add significant complexity to the game. So instead of rewriting everything to use Unity ECS, we're working on incorporating some of the ideas behind it into our own code. [h2]Option C: Streaming Proxies[/h2] The solution we are currently prototyping is to take parts of our own code and make them more data oriented and have it stream in separately from the unity GameObjects. These objects that stream in separately are called streaming proxies. These proxies are data oriented and stream in exceptionally fast. The idea is that most of the world you see will be drawn using streaming proxies and game objects will stream in close to the player: [img]{STEAM_CLAN_IMAGE}/38913947/e75b072cbf503a6f0a331a1f0b4be187b027d586.png[/img] [h2]Initial Prototype[/h2] As a prototype, we've moved over the rendering of everything that uses our compute rendering system over to the streaming proxy system. Here's a video of how fast streaming was before: [previewyoutube=YSmrwlxM5zc;full][/previewyoutube] And here's an example using streaming proxies: [previewyoutube=GewSNkc5ns4;full][/previewyoutube] In the second video you can see that all the streaming proxies stream in exceptionally quick but we're not yet loading collision for any of those objects which means you can't interact with them at all yet. That'll be solved by a mix of streaming in gameobjects near the player and moving more systems over to the streaming proxies such as collision/effects/sounds/etc. [h2]What's Next[/h2] This whole system is a a work in progress and the final solution might end up being a mix of gameobjects/pooling/streaming proxies. Next steps are to stream in the gameobjects near the player but also to move some of the collision handling over to the proxy system. That being said, we wanted to give you guys a look into some of the work in progress that's being done to solve the streaming issues in large bases. Thanks for listening! -Cheerio If you haven't read our previous FOUNDRY Fridays and prefer a video format, feel free to check out our Monthly Status Update video on YouTube: [previewyoutube=MdfJHE1_w44;full][/previewyoutube] Follow us on socials: [list] [*] [url=https://discord.com/invite/eqvCtNH]Discord[/url] [*] [url=https://twitter.com/foundry_game]Twitter[/url] [*] [url=https://www.reddit.com/r/foundry_game/]Reddit[/url] [*] [url=https://www.facebook.com/foundrygame/]Facebook[/url] [*] [url=https://forum.paradoxplaza.com/forum/forums/foundry.1153/]Paradox Forum[/url] [/list] Stay tuned for more news! https://store.steampowered.com/app/983870/FOUNDRY/