Progress Update #5

 Rewriting "Everything"


    It's been a while, but I'm back with lots of progress to show. I finalized the multithreading and fixed the issues with it. I fixed an issue with saving the game that I have had forever and just now got around to. I also finally implemented the better texture generation method that doesn't deal with atlases.

Multithreading:

    So the original issue I was having with the multithreading was a race condition where some of the TerrainFaces would finish generating before others triggering the function that should happen only when all faces are done calculating. The faces that weren't finished yet would then have no data on the height of the terrain, thus defaulting to 0 for the entire face. This function being called prematurely was hard to deal with, because it had to be called from the main game thread. This would mean that I would have to open the new thread to do the calculations, then go back to the main thread to finish the operation.
    As is the case with many other complex programming problems I've run into, it ended up being fixed by a single line (more or less). 

AsyncTask(ENamedThreads::Game Thread, [this]() { TF.CreateMesh(); });

And that's it. This one line essentially calls anything within the {} on the game thread. So in my case I am calling the create mesh method of TerrainFace on the game thread. I found this solution on this answerhub thread if you want to check it out.

Here's a time comparison of single-threaded and multi-threaded performance:



Slow Saving:

    An issue that has plagued me since I started this project is that the editor would take forever to save the scene whenever there was a planet present. I had done some testing and the scene would only save slowly when there was a planet with a populated procedural mesh. Because of this information I deduced that the cause of the slow saving was the procedural mesh being saved.
    Looking into this possibility I came across this reddit thread in which someone suggests, "UE4's procedural mesh component is designed to be updated every frame so it doesn't take advantage of special static mesh only performance improvements". So great, I thought, the central mechanic of the game, having dynamically updated planets, is going to cost a lot of performance. But then the response to that reddit thread gave me an idea: what if I converted the procedural meshes to a static one for saving? So that's what I set out to do.
    I started off by noticing that the procedural mesh component in the editor had a button titled "create static mesh". The first thing I tried to do was to call the function that that button was connected to. When that didn't work (because the function is private, duh) I did maybe not the best thing and copy pasted the function into my own file. I changed a few things to make the function work better for my purposes though:
  • I removed the part of the code where it would go through each "procedural mesh section" and replaced it with a loop that would go over each procedural mesh from each terrain face. 
  • I added a bit at the end that will clear the procedural meshes once all the data from them is copied into the static mesh.
  • I made all of the individual meshes produced by the terrain faces combine into one single static mesh.
  • I changed the way that materials are copied from the procedural meshes.
The final function is ConvertToStaticMesh() in Planet.cpp

    After this was done and some debugging with materials, it was working smooth as butter. Now saving a scene was as fast as essentially having an empty project. Although sometimes it will throw this error:

The static mesh had references that were part of an "external map" even though there is only one scene in the project. Then when I try to resolve these references it fails. After some looking around I found someone said that doing File>RefreshAllNodes in their blueprint fixed the issue for them. Lo and behold when I did the same with my Planet_BP the editor saved with no hiccups. 

New Texture Method:

    This has been something that I've had my eye on for a while. In mid September 2020 at the end of  Progress Update #3 I mentioned having found an article on "how to save a procedurally generated texture as a new asset entirely through C++". Now it was finally time to give it a try.
    Before now I have been using Unreal's built in color curves and color curve atlases. At first I was really excited about all the functionality they had, but the more time went on the more I realized the things I didn't have control over. Like the fact that up until a recent source build of the engine you could only have an atlas texture be square, something that I didn't want.
    So following the Isara Tech article I was able to get it working in a few days. I now had more control over my textures and could blend the biomes which wasn't possible before.

Extras:

    After these big things were taken care of, I took on three sub-challenges. 1) Making the planet generation settings easier to use, 2) making the settings save better, and 3) making the water look nicer.

  1. This is going to mean digging through the engine source code and looking at how the engine makes things like the actor transform look good in the details panel (probably lots of  property specifiers).
  2. This means making the settings non-instanced and automatically apply to their respective planet.
  3. I am currently working on this and it is based on a reddit post I saw that turned one noise texture into a nice looking water shader (the dev that made it also has a twitter where he logs his process on his own indie game).

Comments

Popular posts from this blog

Polishing the Foundation

Progress Update #13

A New Chapter