Performance optimization in games can sometimes be even more challenging and time-consuming than the actual development process. This is why both major game companies and independent developers invest heavily in optimization efforts.
The Performance Problem
Imagine you've created an AAA game, but players who download it discover they're only getting 30-40 FPS on an RTX 4090 with an i9-13900K. No matter how good your game is, if players can't achieve optimal performance, they'll leave negative reviews.
This is why optimization matters.
I'll outline several optimization techniques for Unity. However, it's worth noting that I cannot list every possible optimization method—these are skills we develop over time through experience and continuous learning.
1. Resolution Management
Everything visible in your game is processed through the CPU and GPU before being displayed. Each object contributes to performance overhead on both components.
The simplest solution is to remove unnecessary objects, preventing them from creating load on the CPU and GPU. However, if an object is essential, you can reduce its resolution as a Plan B.
Finding the Balance
Be careful not to reduce resolution too much, as this can make your game visually unsatisfying. Finding that fine line between performance and visual quality is crucial.
2. LOD (Level of Detail)
LOD systems reduce the detail of objects as they move further from the camera. This technique significantly reduces the load on both CPU and GPU.
Benefits of LOD:
- Reduced CPU/GPU load - Less detailed models require less processing
- Memory efficiency - Lower detail models consume less memory
- No perceived quality loss - Distant objects naturally draw less player attention
- Scalable performance - Automatically adjusts to viewing distance
LOD Best Practices
Set up multiple LOD levels (typically 3-4) with distances that make sense for your game's scale. Use Unity's LOD Group component to manage transitions smoothly.
3. Culling Techniques
Culling is based on removing objects that are outside the camera's view. This method is used not only by Unity but by many game engines. It prevents excessive load on both CPU and GPU and reduces unnecessary memory usage.
Types of Culling:
- View Frustum Culling - Hides objects outside camera's view cone
- Occlusion Culling - Hides objects blocked by other objects
- Portal Culling - Room-based visibility management for indoor scenes
- Distance Culling - Hides objects beyond a specified distance
Occlusion Culling Setup
Enable Occlusion Culling in Unity's rendering settings. Bake occlusion data for static objects to achieve significant performance gains in complex scenes with lots of geometry.
4. Unity GPU Profiler
The Unity GPU Profiler displays your game's graphics processing data. This tool provides game developers with capabilities for identifying, debugging, and improving performance issues.
How to Use the Profiler:
- Access it through Window → Analysis → Profiler
- Enable Deep Profile for detailed function-level data
- Focus on CPU and GPU timings in the hierarchy view
- Identify bottlenecks in rendering, physics, and scripting
- Use the GPU Profiler module to analyze draw calls and batching
Key Metrics to Watch
- Frame time (should be under 16.6ms for 60 FPS)
- Draw calls (minimize to reduce CPU overhead)
- Vertex count (optimize meshes to reduce)
- SetPass calls (batch materials to reduce)
5. Lighting Optimization
Lighting is personally one of the most challenging and complex elements in games. Well-executed lighting brings incredible visual quality and performance benefits to your game. However, if you lose control, your game's FPS will plummet.
Types of Lighting:
- Ambient Lighting - Base illumination for the entire scene
- Directional Lighting - Simulates sunlight with parallel rays
- Point Lighting - Localized light sources radiating in all directions
- Spot Lighting - Cone-shaped directional lights
Lighting Performance Tips
- Use baked lighting for static objects
- Limit real-time lights (especially shadows)
- Use Light Probes for dynamic objects
- Disable shadows for distant lights
- Use Enlighten or Progressive Lightmapper
Shadows are equally critical as lighting. As I mentioned, lighting and your game are separate worlds unto themselves—invest time in mastering this area.
6. Texture Compression
This method compresses visual data, reducing both file size and the load on CPU and GPU. It's actively used not only in the gaming industry but also in modeling programs.
Compression Formats:
- RLE (Run-Length Encoding) - Simple compression for patterns
- DXT (S3 Texture Compression) - Standard for PC platforms
- ETC (Ericsson Texture Compression) - Optimized for mobile devices
- ASTC (Adaptive Scalable Texture Compression) - Modern, flexible format
Texture Settings
In Unity's texture import settings:
- Set Max Size appropriately (1024, 2048, etc.)
- Enable Generate Mip Maps for 3D textures
- Choose platform-specific compression formats
- Use Crunch Compression for additional size reduction
7. Asset Bundles
Asset Bundles are used to reduce game size, improve loading times, and make resource management more effective. This method compresses visuals, audio, text, and code to reasonable sizes.
Benefits:
- Reduced initial download size - Essential for mobile games
- Faster loading times - Load only necessary assets
- Easier updates - Update individual bundles without full reinstall
- Memory management - Load and unload assets dynamically
Asset Bundle Strategy
Group related assets together and separate frequently-updated content from static content. This allows for efficient updates and memory usage.
8. Shader Optimization
Simplifying complex shaders can lighten the load on both CPU and GPU. However, like some other methods, this may reduce visual quality, potentially making your game look worse aesthetically.
Shader Performance vs Quality
Just as with everything else, you need to find the right balance. Mobile platforms especially benefit from simplified shaders, while high-end PC games can afford more complexity.
Shader Optimization Tips:
- Reduce the number of texture samples
- Minimize conditional statements (if/else)
- Use shader LOD to provide simpler variants for distant objects
- Avoid expensive operations like
pow()andsin() - Use mobile-optimized shaders for mobile platforms
9. Code Optimization
The code you write in your games can directly or indirectly affect performance. This is an endless topic, so I'll provide a few examples to give you an idea.
Avoiding Nested Conditionals
❌ Bad - Nested Conditions:
if (a == 1) {
if (b == "Hello") {
if (c != null) {
Debug.Log("Success");
}
}
}
✅ Good - Combined Conditions:
if (a == 1 && b == "Hello" && c != null) {
Debug.Log("Success");
}
This not only improves performance but also enhances code readability.
Efficient Object Finding
Avoid Frequent GameObject.Find()
I don't recommend using GameObject.Find("") frequently because every time you
use it, Unity searches for the target object's name among all objects in your scene.
Better Alternative:
// ✅ Use tags for better performance
GameObject player = GameObject.FindWithTag("Player");
// ✅ Even better: Cache references
private GameObject player;
void Start() {
player = GameObject.FindWithTag("Player");
}
Cache Component References
❌ Bad - Repeated GetComponent():
void Update() {
GetComponent().velocity = Vector3.forward;
GetComponent().angularVelocity = Vector3.zero;
}
✅ Good - Cached Reference:
private Rigidbody rb;
void Start() {
rb = GetComponent();
}
void Update() {
rb.velocity = Vector3.forward;
rb.angularVelocity = Vector3.zero;
}
Raycast Optimization
Raycast is an element that strains Unity's physics engine. It's beneficial to use it sparingly when possible.
Limit Raycast Distance
Unless you specify otherwise, a Raycast extends infinitely, which significantly impacts performance. Always define a reasonable limit:
// ❌ Bad - Infinite raycast
if (Physics.Raycast(transform.position, transform.forward)) {
// ...
}
// ✅ Good - Limited distance raycast
float maxDistance = 100f;
if (Physics.Raycast(transform.position, transform.forward, maxDistance)) {
// ...
}
// ✅ Even better - Use layer masks
int layerMask = LayerMask.GetMask("Enemy");
if (Physics.Raycast(transform.position, transform.forward, maxDistance, layerMask)) {
// ...
}
10. Set Priorities
During your game's development, identify the essential features your game needs and which features are extra. This way, you avoid adding unnecessary adjustments or content that strain device performance, and you'll also be more organized during the development process.
Feature Prioritization
Create a clear hierarchy of features:
- Core Gameplay - Must have, optimize last
- Essential Systems - Required but can be optimized
- Polish Features - Nice to have, disable if needed
- Extra Content - Optional, easily removable
11. Collider Optimization
Colliders are components that help us control object collisions. However, unnecessary use of colliders negatively affects performance.
Collider Performance Comparison:
| Collider Type | Performance | Use Case |
|---|---|---|
| Box Collider | ✓ Excellent | Simple shapes, buildings, platforms |
| Sphere Collider | ✓ Excellent | Spherical objects, projectiles |
| Capsule Collider | ✓ Good | Characters, cylindrical objects |
| Mesh Collider | ✗ Poor | Complex geometry (use sparingly) |
Mesh Collider Warning
Mesh Colliders conform to the object's shape, making them much less performance-friendly than Box Colliders. Don't use Mesh Colliders unless absolutely necessary.
Alternative: Use multiple primitive colliders to approximate complex shapes.
Conclusion
Beyond these techniques, there are many other optimization methods. You can discover them through trial and error or by researching resources on the internet.
Final Optimization Checklist
- ✓ Profile before optimizing - identify real bottlenecks
- ✓ Start with the biggest performance gains
- ✓ Test on target hardware regularly
- ✓ Maintain visual quality where it matters most
- ✓ Document your optimization decisions
- ✓ Keep learning new techniques
Remember: Optimization is an ongoing process, not a one-time task. As you add features and content, continuously monitor and adjust your game's performance.