In this project I worked with designing the tech design and then later developed them using c++. I also design different zones in the openworld level by first blocking them out and then dressing them after
Level Streaming / World compensation / Open World handler
The purpose of this system was to be able to have big open world levels while having control over how data is stored and loaded during the game process while also being able to keep drawing to a president render targets while keeping the game at a good performance.
The first step this system takes is to split up all sublevels into smaller chunks to make the streaming load time for each chunk to be faster. We ended up splitting up all these chunks into 1000+ levels which is a lot of levels to work with but there are ways I automated systems to still make it workable as it would be with one level.
The two main features of the streaming system is a chunk handler that is attached to the player and keeps track on what levels should be loaded and what LODs should be active. The zone handler is used to group chunks into bigger clusters so they become multiple big chunks instead as well as keep specific data, lods and cluster LODs per zone handler.
The zone handler will group 16 chunks into 1 bigger chunk, with this we can either make 1 big chunk to 1 LOD mesh or if we have 1 chunk streamed in we can use LOD meshes on the last 15 chunks.
(Red is 1 LOD mesh | Green is streamed levels | Yellow is single LOD mesh)
The chunk handler is based on two things where the first thing is a radius that is attached to the player where this will determine what chunk should be streamed in and out. The second thing to this is a vision cone that will detect what chunks are not streamed in and if they are in the player vision they will set what LOD mesh should be displayed and if they are outside we just cull the mesh out to save on performance.
(Red: Chunk LOD | Green: Streamed in level | Yellow: single chunk LOD | Grey: Culled)
When working with render targets at a large stage something we need to keep in mind is that render targets can become very expensive, especially when we use camera components to draw them. A way to make this cheaper is to remove the camera component completely and to still be able to draw to the render target we have to determine the location with mathf instead. To do this we just get the bounds of a zone handler and convert it to a 0-1 value so if we input a location at the center of a zone handler we would get X0.5, Y0.5 and using this we can draw right away to the render target and just use it to store data.
Work process when working with a lot of levels
When comes to working with this system we a naming for all of the level then following this we can easily automate most of the thing with process from setting up the zone handler to filling out all of the necessary data for LODs, material, spawners and anything else that would be needed for the zone handler to work.
When it comes to level design or artist work when we need to work with the chunks we can still use an unreal foliage system since this already places the foliage to the correct level. For something like asset placing I designed a tool that would check a box in each chunk and grab all the assets in that specific chunk and then move them to the correct level if they are placed in the wrong level.
Mesh setup outside of unreal with blender
When it comes to creating LODs we can easily just export all of the landscapes in unreal to one fbx and then import them straight into blender. The thing that is very important to fix at this point is the pivots of the meshes since we don't want an offset in Z which will cause misalignment when used with the main landscape.
(Orange dots are were pivot are located)
A way that we can solve this is to write a python script that gets the current selection of object and set the X and Y to the centre of the mesh and then we set the Z to a set position like 0 in blender and in this case all of meshes will have the same pivot offset making the process of automation with zone handler easier.
(Orange dots are were pivot are located)
Then when it comes to mass export objects we need to keep the pivot of each mesh and export name being the name in blender since this would be the same name as landscape name in unreal. We can make a custom script as well but there is already a good one out there that I use for this which is Batex.
Batex Plugin for mass export can be found here:
After we get all the files exported they all are separate files which will add up to 1000+ files. At this point we would want to rename all these to be easier trackable for the engine later on so we don't have to manually add all these to each chunk. The was i solved this was to just write a windows application in C# that would just rename the file after a prefix in a folder.
The renamer tool I made can replace up to 3 different elements in one text and if we can still keep the zone position like A01 and A02 in the name will help us speed up the process to auto assign the mesh inside the engine.
So in our case we just follow our convention for these things which is "SM_Landscape_Layer_X00_LOD"
After importing the assets to everything to the engine with our naming convention and all lod meshes, we can just run our zone handler generator which will find these names and set the reference to the corresponding mesh.
House Creating tool
Another thing I worked on with this system is a house creation tool. This system would allow us to work with a small isolated level to design and create a house with modular props and test it without having to play in the open world level. When we are done with a house we can also set up a LOD for this house in the same location then save everything to a data asset and load this data asset in the open world to speed up development. This would also allow multiple people to work on multiple houses in the same chunk without blocking each other.
Auto LOD generator per chunk
When it comes to automating the lod creation for this system we can save all foliage LOD items to a datatable collection. Then when we want to generate a LOD for a chunk we can go through this list and replace asset with the lowest LOD of all foliage asset then for building we can just grab the LOD from the house data asset and spawn landscape LOD we did earlier group it and bake it to a mesh. By going through this process we can speed up the LOD creation for chunks and still use existing LODs instead of having to make brand new ones.
During this project I also built a custom automator tool that is built to be modular to other projects at a later point while still keeping support of the previous projects. I also kept in mind when creating this tool to make it expandable so it would be possible to add the application to a new pc and then make it to be another worker that supports the first one to take up tasks that are not started.
Good thing about building each of these as my own project is that I could have full access when creating the user panel which allowed me to make it a simple design and user friendly.
(Control Panel layout)
I was also able to interrogate this system with discord so I could notify specific users when a task was started, failed or was completed.
(Automater flow chart)
The way this application is working is that it runs in the background of a pc and checks a database for new tasks to be added and then assigns them to the worker that is looking for them.
(Automater flow chart)
Automater application running on the worker pc, this application is mostly running in the tray of the pc but still accessible. If the application is open then it will shows logs of past processes and could also help debug issues that might occur if it would be application wise.