The smooth gameplay comes from a smooth frame rate, and our upcoming Action platform game, Shadow Blade, has seen 60 frames per second on standard iphone and ipad devices as an important goal.
Here are a few things to consider when improving game performance and achieving target frame rates in a compact optimization process.
When basic game functions are in place, make sure the game performance is up to par. One of our basic tools for measuring game performance is the unity built-in parser and the Xcode analysis tool. Using the Unity Analyzer to analyze the running code on your device is a valuable feature.
We summarize this experience in measuring, adjusting and re-measuring the frame rate of a target device at 60fps.
First, in the case of trouble to invoke the "garbage collector" (Garbage Collector, useless unit collector, hereinafter referred to as GC)
We are not accustomed to the specific behavior of the useless unit collector because of the programming background of C + + games. Make sure you automatically clean up the memory you don't use, which is good at first, but soon you'll find your profiler often shows that the CPU load is too large because the garbage collector is collecting garbage memory. This is especially a big problem for mobile devices. To follow up on memory allocations and try to avoid them as a priority, here are the main actions we should take:
1. Remove any string connections in the code, as this will leave a lot of garbage to the GC.
2. Replace the "foreach" Loop with a simple "for" loop. For some reason, each iteration of each "foreach" loop generates 24 bytes of garbage memory. A simple loop iteration can leave 240 bytes of garbage memory 10 times.
3. Change the way we check game object tags. Replace "if (Go.tag = =" Enemy ") with" if (Go.comparetag ("Enemy") ". It is a very bad practice to invoke the tag properties of an object assignment and copy extra memory in an internal loop.
4. The object library is great, we create and use libraries for all dynamic game objects so that nothing is dynamically allocated during the game's runtime, and everything is reversed to the library when it is not needed.
5. Do not use LINQ commands because they typically allocate intermediate retarders, which can easily generate garbage memory.
Second, the communication overhead between the advanced script and the native engine C + + code is handled with care.
All gameplay codes written using Unity3d are script code, which is the C # code that is processed using mono execution time in our project. Any communication requirement to the engine data requires a call to the local engine code that enters the Advanced scripting language. This, of course, generates its own overhead, while minimizing the number of calls in the game code is in the second place.
1. Moving around in this scenario requires a call from the script code to enter the engine code so that we cache the transformation requirements of an object in one frame of the gameplay code and send only one request to the engine at a time to reduce the call overhead. This pattern also applies to other similar places, not only to moving and rotating objects.
2. Referencing a local cache to a component reduces the need to use "getcomponent" for one component reference per game object, which is another example of calling local engine code.
Third, physical effects
1. Set the physical simulation time step to the minimized state. In our project it is not possible to make it less than 16 milliseconds.
2. Reduce the call of the role Controller move command. Mobile role controllers occur synchronously, and each call consumes significant performance. Our approach is to cache the move request per frame and apply it only once.
3. Modify the code to avoid relying on the "Controllercolliderhit" callback function. This proves that these callback functions are not handled very quickly.
4. In the face of weaker devices, use skinned mesh instead of physics cloth. Cloth parameters play an important role in operational performance, and if you take the time to find the balance between aesthetics and performance, you can get the ideal results.
5. Do not use Ragdolls in the physical simulation process, only let it take effect if necessary.
6. To carefully evaluate the trigger's "Oninside" callback function, in our project, we try to simulate logic without relying on them.
7. Use hierarchies instead of labels. We can easily assign hierarchies and labels to objects, and query for specific objects, but when it comes to collision logic, the hierarchy has an obvious advantage in running performance at least. Faster physical computing and less useless allocation of memory are the basic reasons for using hierarchies.
8. Never use the mesh collider.
9. Minimize collision detection requests (such as Ray casts and sphere checks), and try to get more information from each check.
Iv. make AI code faster
We use AI enemies to block Ninja heroes and fight them. Here are some recommendations related to AI performance issues:
1.AI logic, such as visibility checks, generates a large number of physical queries. You can have the AI update cycle set below the image update cycle to reduce CPU load.
Five, the best performance is not from the code at all!
When nothing happens, it shows good performance. This is our basic principle of closing all unnecessary things. Our project is a side horizontal scroll action game, so if you don't have visibility, you can close many dynamic level objects.
1. Use level-of-detail custom levels to turn off enemy AI in the distance.
2. Mobile platforms and barriers, when they are far away, their physical collider will be closed.
The 3.Unity built-in "animation picker" system can be used to turn off animations for objects that are not being rendered.
4. The same disabling mechanism can also be used for particle systems in all levels.
Six, callback Function! What about the blank callback function?
To minimize unity callback functions. Even if the enemy callback function has a performance penalty. There is no need to leave blank callback functions in the code base (sometimes between a lot of code rewriting and refactoring).
Seven, let the art staff to rescue
When programmers scratching to think about how to make more frames per second, artists can always magically come in handy.
1. Share the game object material so that it is stationary in unity so that they can be bound together, resulting in simplified drawing calls that are an important element of good moving performance.
2. The texture atlas is especially useful for UI elements.
3. The square texture and the reasonable compression of both power are necessary steps.
4. Our artists removed all the grids from a distant background and converted them into simple 2D-bit faces.
5. Light maps are very valuable.
6. Our art staff removed the extra vertices at some points.
7. Using reasonable texture MIP standards is a good idea (game State Note: This is especially true for devices with different resolutions to render good frame rates).
8. The combination of grids is another action that the art staff can play.
9. Our animators try to get different characters to share animations.
10. To find a balance between aesthetics/performance, there are many iterations of particle effects. Reducing the number of transmitters and minimizing the need for transparency is also a big challenge.
Viii. to reduce memory usage
The use of large memory will of course have a negative impact on performance, but in our project our ipod has experienced multiple crashes due to exceeding the memory limit. The most memory-consuming thing in our game is textures.
1. Different devices use different texture sizes, especially for textures in the UI and large backgrounds. "Shadow Blade" uses a generic template, but if the device size and resolution are detected at startup, different assets are loaded.
2. We want to ensure that unused assets are not loaded into memory. We have to be a little late. In the project, we found an asset that was referenced only by a prefab instance and never fully loaded into the in-memory instantiation.
3. This can also be achieved by removing the extra polygons in the mesh.
4. We should rebuild the life cycle management of some assets. For example, adjust the load/unload time of the main menu asset, or the expiration date of the level asset or game music.
5. Each level must have a specific object library tailored to the needs of its dynamic objects and optimized to the minimum memory requirements. The object library can be a little more flexible, including a large number of objects during the development process, but be specific when you know the game object needs.
6. It is also necessary to maintain the compressed state of the sound file in memory.
Original: Http://www.cgder.com/forum.php?mod=viewthread&tid=201&extra=page%3D3
"Reprint" summarizes the experience of using Unity3d to optimize game running performance