One of the reasons I love programming is that there is always something new to learn – a new language, a new technology, a new technique. The bright side is that it’s always fresh and fun. The downside is that sometimes it makes you feel like an idiot.
I’m going through this “new and exciting” experience with my game. Unity is a fantastic development platform – it’s flexible, it’s easy, and it’s powerful. I’ve been working with it for over 2 years now, so I thought I had figured a good bit out about how to do things. But I’ve been struggling with getting a decent frame rate even though my game is really pretty basic. My game has tiny worlds (minuscule, really), mostly static meshes, low-poly models, etc. However, the frame rate would frequently dip below 30 FPS… Totally unacceptable on my fairly beefy computer.
Now, a lot of my problems are just the result of a misunderstanding about how Unity optimizes some things. Unity uses an “Update” method on objects that need to be updated every frame. I was using this method all over the place to manage things that needed to happen over time – but not necessarily every frame. Well, as it turns out, having that Update method means Unity needs to call that method, which takes time, even if the method doesn’t do anything. So, I went back and stripped out most of my “Update” methods and replaced them with coroutines. And instantly I got a 20-30 FPS increase.
But my frame rate was still sitting in the mid-50s for a simple game. I’ve spent hours tweaking some of my most commonly used code to eke every last drop of performance out of it. I’ve done a pretty good job, and created a lot of code that’s useful for time-slicing and scheduling operations to run over multiple frames. Still not enough, though.
So today I’m doing some thinking and out of nowhere, an idea pops into my head: “What if I try triggers for targeting?” A trigger in Unity is a collider that doesn’t affect physics. So, it can tell when another object enters, moves around within, or leaves its collider. You could use them to trigger an enemy spawn when the player gets close, or fire a trap, or whatever. Stupidly, I had not been using them for targeting. Instead, I was periodically scanning every target within range and finding the best target. With triggers, I can instead handle this as new targets come into range – when a new target comes into range, check to see if it’s “better” than the current target. This has two side effects: it’s doesn’t take as long because you’re only checking a single target, and it happens as soon as the target enters range. This means that turrets will now immediately notice a new target and react to it instead of having to wait for the next target scan.
Luckily, my AI design was pretty good, so making the switch was easy and I got it tested within an hour. My frame rate is now sitting in the 100+ range, though I still want to try it out on a really busy battle. If things work out, I won’t have to go to some of the “drastic” measures I was thinking about (like enforcing a unit limit).