Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Optimizing Large Scenes in Unity


Published on

In this case study I show how we managed to put 5,000 bases on a world and make it run smoothly on mobile devices, using the Unity game engine

Published in: Engineering
  • Login to see the comments

Optimizing Large Scenes in Unity

  1. 1. Optimizing Large Scenes in Unity How we put 5,000 bases on a planet and lived to tell about it Noam Gat Tacticsoft @noamgat
  2. 2. Hello! Noam Gat CTO @ Tacticsoft Past - JoyTunes, Omek Interactive, OGRE
  3. 3. Earth Arena Case Study Tacticsoft’s upcoming Mobile Strategy MMO Take over the world with your friends!
  4. 4. Earth Arena Case Study 5,000 bases on a planet, with 3 levels of detail and smooth transitions
  5. 5. The challenge (today) is not to make a single object look good, but to make an entire scene run smoothly - Frames per second - Loading Time - Memory footprint - Artist pipeline Scene Management
  6. 6. Step 1 - Prove the problem
  7. 7. Step 1 - Prove the problem Premature optimization is the root of all evil
  8. 8. Naive solution - Instantiate a prefab for every base in the world - Each object contains 3 LOD objects - Show / hide object groups based on camera
  9. 9. Naive solution Worked surprisingly well! - It was faster to disable/enable renderers rather than game objects - Started becoming heavy on iPhone 6 with 1k objects, but was good enough
  10. 10. Test Driven Development (TDD) Not only about unit tests. Create a consistent, easy to run, reproducible environment to check that what you created meets your expectations.
  11. 11. Stress Test, Take 1
  12. 12. Step 1 - Prove the problem Not stupid, but naive.
  13. 13. Step 2 - Investigate
  14. 14. Step 2 - Investigate Between the different aspects of the scene, which one was causing the crash? - Frames per second - Loading Time - Memory footprint - Artist pipeline
  15. 15. Unity’s Toolset
  16. 16. Benchmarking A few experiments revealed: - Unity objects / components cost ~1k per instance - 5k objects, 10 GOs/object, 3 components / GO - > 150k components -> 150MB scene - Dynamic batching was the biggest CPU hit, and batching was also becoming a problem
  17. 17. Step 3 - Solve We wanted a solution that has: - A stable memory footprint in large worlds - Good FPS / batching performance - Looks like the previous solution - Won’t be a nightmare to control artistically
  18. 18. Solution approaches Two approaches: - Pooling - Return out of camera objects to a pool, reuse them when the camera moves - Baking - Dynamically a large mesh with many objects packed together (similar to Unity’s static batching)
  19. 19. Solution problems Pooling - When looking at the world from far away, we see half of the objects in the world, so pooling is only a 50% reduction
  20. 20. Solution problems Baking - When looking at the world from up close, we have 3d models with relatively high poly counts and some with animations
  21. 21. Solution The problems never happen at the same time, and we can predict which will happen when.
  22. 22. Solution (Artist side) Baked objects go to baking pipeline Instanced objects go to pooling pipeline
  23. 23. Array of Structs / Struct of Arrays - Array of structs is the intuitive way to look at things (every object has several properties) - Struct of arrays is a bit weird (several properties have values for every object) Struct of arrays allows us to look at a vertical of all objects (“All baked LOD1 objects”) and do something special for them
  24. 24. Baked pipeline Not MonoBehaviour, ~ 200 bytes memory Minimal amount of information to render and order
  25. 25. Baked pipeline
  26. 26. Baked pipeline Less batches, much less game objects / components
  27. 27. Baked pipeline gotcha When viewing a lot of sprites from far away, better to turn off “Tight” sprite packing to allow more sprites in same amount of geometry
  28. 28. Pooled pipeline Which instance to instantiate Where to put it
  29. 29. Pooled pipeline Rest of pooled pipeline reiles on previous “camera culling” method from first naive attempt - instead of disabling / enabling objects we take / return them to the pool
  30. 30. Object permutations The objects have different properties (colors etc) based on their role in the world. We do not want a different prefab for each permutation of each object.
  31. 31. “Visitor” Design Pattern
  32. 32. “Visitor” Design Pattern
  33. 33. “Visitor” Design Pattern The visitor pattern allows us to easily reuse prefabs, making modifications as needed in both the baked and pooled pipelines. It puts healthy design constraints on what you can and can’t put on objects placed on the map (MVC principles etc)
  34. 34. Step 4 - Test
  35. 35. Number of objects
  36. 36. Number of batches
  37. 37. Device performance
  38. 38. The future...
  39. 39. TL;DR - It’s OK to be naive for 99% of the code - TDD applies to optimization as well - Many approaches to solve problems, the correct one stems from understanding the problem - Several design patterns are very useful for optimization
  40. 40. Thank You! Come play our games! @noamgat