Welcome Visitor
Today is Friday, November 17, 2017

 

Game development tips: Level optimization in Unity

    Print

You may or may not know that I am currently working on a game for the PlayStation 4 titled "The Nightmare from Beyond." What you surely don't know is that, even if it's basically a PC, the PS4 demands some level of "best practices" when it comes to asset management, programming and optimization. To put it bluntly, just because it runs on PC doesn't mean it will run well on the PS4, or even run at all. And that is the reason why, against common sense, the PS4 is my primary platform for development. I apply the "if it runs well on the PS4, it will run even better on the PC."

enter image description here

Optimization is one of those issues. I am targeting 60fps but I was getting around 40fps on the PS4 and 60fps on the PC. Keep in mind this is not just a matter of "let's make sure it runs well on the PS4!" It's also a matter of "let's make sure it can run well on PCs with older video cards." With good optimizations (and some compromises), it can even make "Nightmare" run on a last generation MacBook Pro.

So, you can see, optimization is a very important thing, not just for consoles, but also as a way to support older or less powerful platforms. This time I will focus on optimization related to what the camera sees. In other words: rendering. Also, as always, I will focus on 3d games, since I don't really work in 2d games that much.

enter image description here

In 3d games, the first thing you should keep an eye on is texture size. Unless you're working on a game with a very specific art style, you will be using textures. The most obvious thing is making sure your textures have the correct size depending on the object they are being applied to. For example, that little power-up prop sitting on the table in your level doesn't require a 2048 px texture... The smaller the object, the smaller textures should be. You should also keep in mind how close those objects might be to the camera to decide how much detail they need. Another thing I've found useful is to ignore alpha (transparency) when it's not needed.

In "The Nightmare from Beyond" levels are pretty small. The reason for this is that we are aiming for short loading times to give the sense of "uninterrupted gameplay." This means every level should load in no more than 5 seconds, so having small levels and correctly-sized textures help a lot.

Even if the levels are small, sometimes levels have a lot of objects in them. Sometimes levels are built in a way that some parts of the level are hidden depending on where you are, and that can cause a lot of problems when the game is trying to render things that aren't even visible because they are behind a wall. Unity has something called Occlusion Culling. Basically what this does is calculate a grid so the engine automatically hides or shows parts of the level based on the camera angle. This is a good automated process, but depending on your geometry you might see objects abruptly pop in and out of view.

enter image description here

I've found that a better method, albeit way more time consuming, is to set up trigger volumes to toggle visibility of the different areas of your level. Basically, what I do is to create a group that includes a trigger and an empty group I set as parent of all the geometry that will be toggled. When the character enters the trigger, the geometry is shown, and when the character leaves the trigger, the geometry is hidden.

Assets can also be very useful for this. Some time ago I discovered an amazing asset in the Asset Store called Super Level Optimizer. This tool pretty much does three things (separately): it allows you to create "texture atlases" so all objects in the level use a shared texture rather than individual textures; it allows you to combine meshes in a single mesh to reduce draw calls; it combines materials in a single material to reduce draw calls (using the same method as texture atlases). Personally, I am not a big fan of texture atlases, because I like to be able to control the size and compression of textures individually. However, I've found that combining meshes helps a lot.

Super Level Optimizer lets you combine meshes automatically, or select the meshes to combine. You can use either one depending on your needs, or your level setup. I've found that a combination of Super Level Optimizer and the visibility volumes I mentioned are a powerful one.

Lastly, real time lights can also cause a lot of performance problems, so they should be used with caution. It is tempting to simply use real time lights everywhere, but they can really impact your performance to the point of making the game unplayable. You should definitely use baked lights everywhere, except where you need real time lights for specific reasons, for example, lights that toggle, or a dramatic shadow somewhere. Also, based on my experience, real time lights can cause performance problems even when they are not visible.

enter image description here

Level optimization is something very time consuming, but when ignored can really affect your game. This is especially true for indies, and it's a shame to see a nice looking game that is also unplayable because the dev didn't really take the time to optimize.

Relevant links: https://www.assetstore.unity3d.com/en/#!/content/25370

You may or may not know that I am currently working on a game for the PlayStation 4 titled "The Nightmare from Beyond." What you surely don't know is that, even if it's basically a PC, the PS4 demands some level of "best practices" when it comes to asset management, programming, and optimization. To put it bluntly, just because it runs on PC doesn't mean it will run well on the PS4, or even run at all. And that is the reason why, against common sense, the PS4 is my primary platform for development. I apply the "if it runs well on the PS4, it will run even better on the PC."

enter image description here

Optimization is one of those issues. I am targeting 60fps but I was getting around 40fps on the PS4 and 60fps on the PC. Keep in mind this is not just a matter of "let's make sure it runs well on the PS4!" It's also a matter of "let's make sure it can run well on PCs with older video cards." With good optimizations (and some compromises), it can even make "Nightmare" run on the last generation MacBook Pro.

So, you can see, optimization is a very important thing, not just for consoles, but also as a way to support older or less powerful platforms. This time I will focus on optimization related to what the camera sees. In other words: rendering. Also, as always, I will focus on 3d games, since I don't really work in 2d games that much.

enter image description here

In 3d games, the first thing you should keep an eye on is texture size. Unless you're working on a game with a very specific art style, you will be using textures. The most obvious thing is making sure your textures have the correct size depending on the object they are being applied to. For example, that little power-up prop sitting on the table in your level doesn't require a 2048 px texture... The smaller the object, the smaller textures should be. You should also keep in mind how close those objects might be to the camera to decide how much detail they need. Another thing I've found useful is to ignore alpha (transparency) when it's not needed.

In "The Nightmare from Beyond" levels are pretty small. The reason for this is that we are aiming for short loading times to give the sense of "uninterrupted gameplay." This means every level should load in no more than 5 seconds, so having small levels and correctly-sized textures help a lot.

Even if the levels are small, sometimes levels have a lot of objects in them. Sometimes levels are built in a way that some parts of the level are hidden depending on where you are, and that can cause a lot of problems when the game is trying to render things that aren't even visible because they are behind a wall. Unity has something called Occlusion Culling. Basically, what this does is calculate a grid so the engine automatically hides or shows parts of the level based on the camera angle. This is a good automated process, but depending on your geometry you might see objects abruptly pop in and out of view.

enter image description here

I've found that a better method, albeit way more time consuming, is to set up trigger volumes to toggle the visibility of the different areas of your level. Basically, what I do is to create a group that includes a trigger and an empty group I set as parent of all the geometry that will be toggled. When the character enters the trigger, the geometry is shown, and when the character leaves the trigger, the geometry is hidden.

Assets can also be very useful for this. Some time ago I discovered an amazing asset in the Asset Store called Super Level Optimizer. This tool pretty much does three things (separately): it allows you to create "texture atlases" so all objects in the level use a shared texture rather than individual textures; it allows you to combine meshes in a single mesh to reduce draw calls; it combines materials in a single material to reduce draw calls (using the same method as texture atlases). Personally, I am not a big fan of texture atlases, because I like to be able to control the size and compression of textures individually. However, I've found that combining meshes helps a lot.

Super Level Optimizer lets you combine meshes automatically, or select the meshes to combine. You can use either one depending on your needs, or your level setup. I've found that a combination of Super Level Optimizer and the visibility volumes I mentioned are a powerful one.

Lastly, real-time lights can also cause a lot of performance problems, so they should be used with caution. It is tempting to simply use real-time lights everywhere, but they can really impact your performance to the point of making the game unplayable. You should definitely use baked lights everywhere, except where you need real-time lights for specific reasons, for example, lights that toggle, or a dramatic shadow somewhere. Also, based on my experience, real time lights can cause performance problems even when they are not visible.

enter image description here

Level optimization is something very time consuming, but when ignored can really affect your game. This is especially true for indies, and it's a shame to see a nice looking game that is also unplayable because the dev didn't really take the time to optimize.

Relevant links: https://www.assetstore.unity3d.com/en/#!/content/25370

Read more from:
Tips + Tutorials
Tags: 
nemirc, tips, unity
Share: 
Related Articles
     Print
Powered by Bondware
News Publishing Software

The browser you are using is outdated!

You may not be getting all you can out of your browsing experience
and may be open to security risks!

Consider upgrading to the latest version of your browser or choose on below: