So I ran into my first real performance issues now while working on Mine Seeker. I've played around with UE4's performance analyzing tool Session Frontend before while developing Farkle Friends to make sure I was running good. I never ran into problems that I had to investigate until now.
I am working on a level generator and it was coming along good. However I was seeing the UI lock up for 1 to maybe 4 seconds while the generator was running. I have a each, medium and hard quick play difficulty and there is no issue on easy, but there was about a 1 second delay on medium and maybe 3 to 4 second delay on hard. So I opened the Session Frontend and started to dig in. I was able to track down 2 performance issues with my code. One was an issue with the level generator and the other was a different issue causing a big cut in the FPS I was running at.
The first issue I just happened to find while investigating the level generator issue. And it was causing a big drop in FPS that I MIGHT not have been aware of otherwise. In the quick play screen I was running a quick piece of code in the tick function that is called every frame. I was updating the UI with information the user needs. What I found was this code was taking up quite a bit of time. I was calling a function that I previously created that will take a number and return a array of Slate Brushes which allows you to apply textures or sprites to an image and display it on screen. To figure out what number was passed in I convert the number to a string array. That conversion every tick was having a fairly big impact on FPS obviously. So I removed that from tick and now instead I just wait until the UI needs to be updated, usually when a user clicks. So first performance issue FIXED! I was feeling pretty good about myself at this point.
The next issue was a little more difficult. I ran the analyzer a few times and found out that the C++ portion of the generator was just fine. I didn't have any issues until after I passed the data to blueprints. What I found out to be the problem was when I loped though the data returned to blueprints from C++ and creating the game tiles was the drag. So I tried to move the game tile UI code to C++ but that came to an end after a few days of trying. I found out working with UI in C++ in UE4 is difficult, buggy and complex. So I moved all the UI back to blueprints. And after a few more days of thinking and bouncing ideas off other developers I cam up with an idea. Instead of creating all 900 tiles (30x30 grid for hard) at once, create just one row at a time. So I created a class in blueprints that will do just that. I create one row, pause, create another row, pause, etc. This actually fixed the problem and now the game doesn't freeze when creating the tiles. I can control how fast the pause is as well. And this has a good side effect of making the animation I play when showing a tile a little more elaborate. But still this brought about a new bug. Imagine that.
Blueprint delay nodes come in handy when you need to pause execution for a moment. I have used them in a few places before. When a delay node is hit, it will pause for the specified number of seconds before continuing. So for the hard level I place a delay node that will pause for 0.025 seconds before continuing with the next row of tiles. Which did work however I ran into a number of things being null after the first delay node was hit. I would call the function that shows the grid of tiles, it would show the first row and hit the first delay node. Then instead of continuing down the rest of the function showing the rest of the tiles, before the delay finished it went back to right after the function call to show the tiles and finished. So I was hitting code that relied on the tiles being there before they actually were. This is not the behavior I expected but after asking a question in their answer hub, I found out this is actually expected behavior. I was able to get around this problem by adding an event dispatcher I can call when the tiles are all created. I then moved the code that was crashing to be run when I call this event. And that fixed the issue. Now I have a fully functioning level generator and the ability to use it without a huge performance hit.
Now that I have this done I have to go back to single player mode and update that to use this generator as well. I'm getting pretty close to being able to have a little demo for people to try. I'll make sure to post here when I do.