Weekly Update 13 is now live on Steam. Here’s a summary of the biggest changes.
Black Screen Fix
We received a number of reports from users that were experiencing an issue where the game would start up with a black screen. This was caused by the game not being able to load any of the files it needs to execute. The common elements between the reports was Windows 8 and having the game installed to a drive other than C: After a lot of back and forth, we tracked down the issue to Windows reporting the wrong case for the directory the game was installed to.
Based on the exact circumstances, it appears that this issue could have affected users with other versions of Windows or with the game installed on the C: drive, although we didn’t actually see any cases like that. Either way, it should be fixed now! If you’re still experiencing any problems please let us know.
Script Component Optimization
One of the unique things about the Future Perfect scripting architecture is that each script runs in it’s own “sandbox” environment which keeps it isolated from all of the other running scripts. We designed the system this way for a few reasons. First, it helps create strong abstraction between scripts since they can’t depend on the internal implementation details. Similarly a run-time error in one script can’t bring down any other scripts. And finally, it allows us to run multiple scripts in parallel by creating a Lua virtual machine per-CPU thread. Since the scripts can’t directly access each other, it doesn’t mater that they’re not all in the same Lua virtual machine.
In order to implement this sandboxing, each script component did a fair bit of work when it was created, including making its own copies of many of the engine’s API functions. These extra copies meant when the script component was destroyed a fair bit of garbage was created. Due to the way the client handles network prediction, script components are created and destroyed [b]a lot[/b] as the client state is restored back in time. The garbage created by each one would eventually would lead to a big hitch in the garbage collector every few frames.
We optimized the sandboxing process so that almost all of the extra API copies are unnecessary. This means script components are more lightweight and the pressure on the garbage collector is significantly reduced.
This image shows the time taken per frame for the last 150 frames. As you can see, the hitches (i.e. the larger bars) are less frequent and smaller. There are still a few things we need to do to eliminate them completely. The first is changing the client prediction code to not have to recreate the script components so frequently. The second is to run the garbage collector for a small amount of time each frame so that the spikes are amortized over all of the frames. Both of these changes would have made the original problem much less visible, so we wanted to tackle it first when it was easy to measure.
User Interface Refinement
Now that the editor UI layout is in a state we’re happy with, we’re starting to work on some of the rough edges that hamper usability. One small example is the Entity Panel which is used to access the individual components of an object. Mucking with the components is an “advanced” feature of the editor; players who want to do level design without creating new types of objects shouldn’t need to know about that (once we have everything implemented). With this in mind, the panel starts out in a hidden/collapsed state and you access it by clicking on the menu bar.
However, in the collapsed state there was no indicator that the panel could be expanded, so players who were looking to go deeper with the editor wouldn’t even know to try that. Adding a simple triangle icon to indicate the panel is collapsed should clue new players into the hidden functionality.
If you have suggestions for ways we can improve the user interface, please head on over the forums.
Our particle system uses a stack of modifiers to apply various effects to the particles. We had two existing modifiers — modification of the size and opacity of the particle over it’s lifetime — and in this update we’ve added a third which affects the acceleration applied to the particle.
All of the values specified for these modifiers can take on four different forms: a constant value, a random blend between two constant values, a curve, or a random blend between two curves. This means that the modifier that affects opacity actually comes in 4 different forms, and the acceleration modifier (which operates on X, Y and Z) comes in 16 different forms. To make the modifiers as efficient as possible each of these different forms needs to be explicitly written out so that we are not branching on the form per particle.
Coding the modifiers like that isn’t really practical, so when adding this new modifier we decided to improve the underlying system. We took inspiration from Bitsquid’s “Scripting Particles” presentation to implement a data-wide interpreter. Unlike the method in the presentation, we aren’t exposing the a scripting language for the modifiers, but instead implemented our fixed modifiers in an assembly language which runs on a simple virtual machine.
We may expose a scripting system like Bitsquid in the future, but even with a fixed modifiers we get some nice advantages from this approach. The first is that we can handle the various forms of the different modifiers easily without adding a ton of code. We can also implement optimizations like SIMD easily since they only need to be implemented in the virtual machine rather than for all of the modifiers. Finally, we apply a number of different optimization passes over the generated opcodes to produce an optimized set of instructions. A simple example is if the particle system includes two acceleration modifiers. After optimization these two modifiers can be collapsed through constant folding.
Future Perfect uses a texture streaming system to load and unload textures from video memory as needed. Since this happens in the background, it’s possible for a texture to be needed that’s not available yet. To ensure we have something to use in that case, we always keep a very low resolution version of the texture in memory that can be used in a pinch.
These low resolution textures were only created once the texture was accessed for the first time which meant that when starting a new level you might see a frame or two of black textures. We’ve fixed this so that the low resolution textures are now loaded during the loading screen.
If you’d like to see the details of everything that changed in this update, check out the “Update 13” list on our Trello Board.
If you’d like to help support the project and get access to all this progress, you can do so by purchasing Future Perfect Architect Edition from our website.