Thursday, April 16, 2015

Building a Scene for Performance

This is me putting experience to good use. Rather than write a whole new post, I'm just copying a section of the project documentation file I am writing alongside the development process. May it help someone avoid the torture I endured.

3.1 Milestone 1: Scene Construction

3.1.1 Problem Analysis

            When Silent Dreams had already released The Dark Eye: Skilltree Saga on PC/Mac/Linux, and were preparing to release to mobile platforms, we discovered a terrible, terrible thing. While faster iOS devices could run the game, at least up to a certain point, slower devices like the iPad Mini or Kindle Fire would crash immediately after the splash screen. We tried different types of texture compression. No results. I spent the next 4 weeks barely eating or sleeping, but coding and rebuilding scenes day and night. I had to separate all the elements in the game scene and load them individually to see where the crash was coming from. What made that exceptionally difficult was that so many of those elements were referencing each other. And, as I discovered, an object causing a crash didn’t even have to be present in a scene. It just had to be referenced by an object in the scene to cause the crash just by preloading. Even worse, if the offending object was referenced by another object not present in the scene, but that object in turn was referenced from within the scene, the preload crash would still happen. I thought I was going to lose my mind.
            I had to create a set of loading scripts that loaded objects into the scene sequentially, and then assigned them their references one at a time. It was gruelling. Then, I had to spend another week debugging and looking for null reference exceptions. But, I did finally find the offending object, nestled in a tree of references, and with the scene being nearly empty to begin with, all test-devices had no problem starting the game.

3.1.2 Solution


            Learning from my tortured past, the first thing I built for Rocket Potato was a scene constructor. The scene begin with the scene constructor being the only present object, and all necessary elements are loaded sequentially. I’m using the yield return StartCoroutine(LoadElement()); command to make sure no elements are loaded until previous elements are done. I’ve even combined that process with a loading screen complete with a loading bar that fills a little with each element, and a text label above that bar that displays the scene constructor’s current activity, kind of like we know from games like The Sims. This should assure a clean loading process even slower devices can handle, and it will help me pinpoint problem objects.

Here is a code snippet of the work in progress:


For those unfamiliar, coroutines in Unity3D are being used here to load single elements at a time. The yield return command means that the function is halted there and will not continue until the coroutine running returns. Using the yield command also ensures that the next step is put off until the next frame. This forces the game to assign at least 1 frame of time to each loading process. In the case of LoadRoomDecoration(), one frame per loaded scene object, additionally.

No comments:

Post a Comment