Join! Login   Search
RaMtiGA - Raising a Middleworld to its Golden Age
RaMtiGA - Raising a Middleworld to its Golden Age: Blog
Jan 28

Written by: Jashan Chittesh
2011-01-28T23:16:57 

I'm still in the process of optimizing the level geometries, in particular apples and power ups. And guess what (revolutionary truth on this channel): Profiling pays really really well. Like, it's common knowledge that in Unity, it's a good idea to cache any of the convenience properties (which misleadingly look like variables) like transform, renderer and so on when you use them frequently.

IIRC, access to these has been optimized inside Unity, so accessing them without caching them in a separate variable is certainly less painful for performance as it was in really old versions of Unity (like 2.0, for instance ;-) ). However, you still pay for not doing this: In my little test setup with 72 Apples and 72 Power Ups, it makes the difference between around 0.65 ms per frame or around 0.70 ms per frame. So that's around 7% speedup in this particular area (which, admittedly, is much less significant than rendering but nevertheless is currently one of the more significant performance-eaters).

However, what really gave me trouble was actually a mistake I made (and that's really a noob-mistake, so I feel kind of ashamed to even mention it ;-) ): GetComponent in Update() ... in a script that's attached to many objects (depending on the level it could be 30 but also 100 or more in some cases). When I replace that per Update-call to GetComponent with a cached variable, it becomes really significant: Now we are at 0.50 per frame vs. 0.70 ms per frame. Now that's 27% less time by just using a little bit of common knowledge.

There's some other minor issues, like removing empty Update() methods (this doesn't really give you that much - but on very low-performance environments like iOS this can play a role). And of course (and this actually required some "engineering"): Disabling visual stuff done in Update() when objects aren't visible.

In my case, this wasn't totally trivial because I have the rendered objects usually as children of the (otherwise empty) game objects that carry all the scripts. I think this is a more flexible approach - but the problem is that when you have no renderer, you don't get the OnBecameVisible() and OnBecameInvisible() events. Which kind of sucks ... but obviously makes sense.

So, what I did is create a little helper script called DelegateVisibilityEvents. And it does just that: You can attach it to any game object that has a renderer, assign a delegate object (that has no renderer) and it will then call OnBecameVisible() and OnBecameInvisible() on the delegate object. This isn't completely trivial because those two methods aren't really defined in MonoBehaviour. When you implement them, they are called ... but there's no interface or anything like that so you could call it from another class. So, I had to create that interface. Not a biggie ... but a little bit annoying.

So ... what happens with this is that instead of doing all those updates on all the apples and power ups in the levels, they are only done for those that are currently visible. This is also not something super-esoteric or anything but just plainly "good practice". But I just missed implementing that right from the start and now it makes me really happy because things are getting faster and faster.

That's really the nice thing about starting as a noob: Eventually, you'll get a chance to fix all the mistakes you made earlier on. Ok, maybe some people would rather not make those mistakes from the start (which would spare me having to fix them now) ... but hey: There's fun in learning. Focus on the possibility ... yay! :-)

Tags:

Your name:
Your email:
(Optional) Email used only to show Gravatar.
Your website:
Title:
Comment:
Security Code
CAPTCHA image
Enter the code shown above in the box below
Add Comment   Cancel 
 
Copyright 2007-2010 by Jashan Chittesh   Terms Of Use   Privacy Statement