Performance Optimisation in Unity: Tips for Smoother and More Efficient Games

 

Unity and Performance Optimization

Hello everyone,

In this article, I will talk about performance, which is sometimes overlooked by most developers, including me, in the early stages of the game development process, but is very important. I said very important because performance is a critical factor that directly affects the player experience. In order to offer a smoother and more enjoyable experience to the players and to make our game more demanded and played, we need to develop by paying attention to details such as high frame rates (FPS) and low latency. Unity is a very powerful game engine in this sense, and when used correctly, it helps us develop high-performance games. Since I have experienced that it is so important, I have researched what we can do for performance optimisation with Unity, what are the most effective techniques and tips. Let’s get started.

1. Using Profiler

Unity Profiler is a tool for analysing game performance. Profiler monitors CPU and GPU usage, memory allocation, and other performance metrics. Thanks to this tool, we have the chance to identify the source of performance problems and find solutions for them.

How to use it?

  • First of all, we use Window => Analysis => Profiler to open the Profiler window. With this, we aim to see performance data.
  • Then we run Profiler while playing our game and wait for it to collect data in real time. By analysing the performance in different scenes, we get a feedback from the game.
  • At this point, we analyse the data we collect. For this, we can examine different tabs such as CPU, GPU, Rendering, Memory in the Profiler window and identify performance degrading points here.

2. Optimising Graphics Settings

LOD (Level of Detail) Usage

LOD allows distant objects to be rendered with less detailed models. This improves performance, especially in large scenes, by de-detailing some of the objects in the game.

  • Creating LOD Groups: In a game, we can create different levels of detail to let Unity know which objects should be rendered in more detail and which ones don’t need all the detail. We do this mostly for objects and manage it with the LOD Group component. Thus, especially in large scenes, objects that are not in sight are rendered with less detailed models and performance is increased.
  • Culling: We can improve performance by setting a game plan so that we do not need to render objects outside the camera field of view. We can increase performance by using Occlusion Culling.

Batching Techniques

  • Static Batching: Used for static (motionless) objects. It renders many objects with a single draw call.
  • Dynamic Batching: Used for dynamic (moving) objects. Reduces the number of draw calls by combining small and similar objects.

3. Physics and Collision Optimisation

Rigidbody and Collider Settings

  • Adding Rigidbody component unnecessarily may cause performance degradation. Instead, it is sufficient to add it only to objects that interact physically.
  • Another point about game performance is to use simpler Collider types if possible. Examples of simple Collider types are Box and Sphere. Using Mesh Colliders instead of more standardised ones like these can negatively affect performance.

Physics Simulation

  • Physics simulation is important to make the game realistic. However, physics calculations are often resource intensive, which affects game performance. The first thing we can do to prevent this is to set the Fixed Timestep value. The physics simulation is updated at certain time intervals, not every frame. This interval is called Fixed Timestep and we can set it in Edit => Project Settings => Time. This value is set to 0.02 (50 FPS) by default. We can adjust this value according to our game and performance requirements. A higher value means fewer physics updates, which can improve performance, but may reduce the accuracy of the physics simulation.
  • Another topic is what can be done with Physics Layers. Physics layers control which objects collide with each other. We can use these layers to prevent unnecessary collision checks. First we create new layers in Edit => Project Settings => Tags and Layers. Then we assign objects to the appropriate layers from the Inspector panel. Finally, in Edit => Project Settings => Physics, we determine which layers will collide with each other. For example, there may be collisions between player and bullet layers, but not between background objects and bullets. In this case, the unnecessary collision does not need to run in the background. And certainly not to degrade performance.

4. Memory Management

Object Pooling

  • This method allows us to create a certain number of objects in advance for frequently created and destroyed objects and reuse them. Especially since continuous creation and destruction of new objects can negatively affect performance, we can reduce this cost and prevent performance degradation with object pooling. Let’s also mention a few points to be considered while doing this. It is important to determine the initial size of the pool according to the needs of our game. A pool that is too small may cause continuous creation of new objects; a pool that is too large means unnecessary memory usage. Then what we do will not have the desired effect on performance. We should also keep a good track of the state of the objects. Objects must be made suitable for reuse. For example, bullets should return to the pool when they reach the target or after a certain period of time. Finally, when returning objects to the pool, we must remember to deactivate them. This prevents the objects from performing unnecessary calculations.
  • We also need to avoid creating new objects by caching objects that are used repeatedly.

Memory Usage Monitoring

  • With Unity Profiler we can monitor memory usage and identify unnecessary memory allocations.
  • We also need to minimise GC (Garbage Collection) operations. If we can prevent unnecessary memory allocation and reduce the activation of GC, this also contributes positively to performance.

5. Code Optimisation

Efficient Code Writing

  • LINQ (Language Integrated Query) makes it easier to make queries on data, but the performance cost is high. For this reason, it may be more advantageous to use classic loops and conditions instead of LINQ in parts where we expect high performance.
  • In C#, memory management is performed by Garbage Collector (GC). Memory is allocated when new objects are created and cleared by GC when these objects are not in use. However, unnecessary memory allocations and consequent attempts to delete unnecessary created objects can negatively affect performance.

Asynchronous Operations

  • Async and Await: Performing long-running operations such as network operations or disc read/write asynchronously ensures that the main game loop runs uninterrupted.

As a result, performance optimisation in Unity is of great importance as it makes our games run smoother and more efficiently. In this article, I have tried to explain techniques and tips that will help us improve our performance. I hope that by applying these tips, we can offer a better gaming experience to our players.

Good coding to all of us.

Thanks for reading.

Selin.

Hiç yorum yok: