- Home /
Making a script static - good practise?
Hi to all!
Browsing @Eric5h5 's Vectrosity's code a while back, I noticed the following:
static var using : TheScript;
function Awake()
{
using = this;
}
I've been using that trick more and more, so much so that if I know a script will only have one instance, I'll automaticaly make it static. Avoids a lot of code maintenance, and is plain handy, but does it impact performance? Is it bad practise?
I use it a lot to reference stuff too, like this:
//MasterScript
static var using : MasterScript;
var slaves : Slave[]; //populate in inspector or in Awake(GetComponentInChildren)
function Awake()
{
using = this;
}
Any script can then call MasterScript.using.slaves[slaveNb].DoWhatever();
I'd very much appreciate informed insights!
Cheers,
Gregzo
Static classes are great, very useful. I use them around all the time, and haven't yet encountered any problems.
@asafsitner your comment is misleading. You make it look like it is a great idea with no drawbacks. Unfortunately this is not the case (see my answer).
Answer by Kryptos · Aug 08, 2012 at 07:34 AM
Static variables are bad practice. Use them sparingly. Not because they are really bad for performance (the GC collection does work differently though), but because most users misuse them.
My advice: only use one static variable for your singleton object, then put all other global variables in this singleton.
Example of typical misuse: referencing an object that is not persistent. Part of the object will be destroy automatically by Unity (i.e. Unity will forget about it) when loading a new scene. But most memory will not be release due to this last reference (and secondary references and cross-references), hence a memory leak.
Possible workaround: wrapper method for loading a level that takes care of releasing references + reconstruction of the references upon level loading.
And to prevent headaches asking myself whether this script or this other script should or not release references, I tend to generalize releasing references in all my script:
public class MyClass : MonoBehaviour
{
MyOtherClass someRefObject = null;
void Start()
{
// Get a reference to the MyOtherClass object, for example with FindObjectOfType
this.someRefObject = (MyOtherClass) FindObjectOfType(typeof(MyOtherClass));
}
void OnDestroy()
{
// Release reference upon destruction
this.someRefObject = null;
}
}
Thanks for the detailed reply,+1. I understand your concerns, but what if you know for sure refed objects will not be destroyed? Your solution would complicate things needlessly, no? $$anonymous$$y current project is for mobile, so I'm avoiding Instantiate and Destroy as much as possible, recycling ins$$anonymous$$d.
If you only have one level, then it is ok. But once you load a new level you will have memory leaks if you're not careful about it. And for iOS, lack of memory can crash the game.
And in my experience, you never "know for sure". In fact you should never think that way. It will prevent you from discovering very annoying bugs at the end of the development.
I'm not sure I understand if my use case would cause leaks or not... Example : scene0:menu, scene1 : on screen keyboard. $$anonymous$$eyboardScript has "static var using = this" and references 49 $$anonymous$$eyScripts in an array(not static). Back to main menu, $$anonymous$$eyboardScript and all keys are destroyed. Where's the leak?
Answer by Ludeme Games · Aug 08, 2012 at 07:33 AM
Yes, I think this can be quite good... but every technique is only good to solve certain types of problems. Do you want a kind of manager class for something you know there will only be one of? For example, a SoundManager? In that case this can be much faster than finding an object with the component in the hierarchy or more memory efficient then storing a reference to the found object where it is used.
To extend the idea further, you may want to warn if using != null before it's assigned... to make sure that the pattern is used properly. You may also need to be aware if objects are destroyed in Slave[].
I'm using this technique to ref objects of finite number, example: all keys of a keyboard. $$anonymous$$eys.using.keys[noteNb].DoWhatever. Will investigate what $$anonymous$$ryptos says, but I can't really see so far how my use would cause leaks...
Your answer
Follow this Question
Related Questions
Unknown identifier, OnCollisionEnter Error 1 Answer
Global Varible Problem 2 Answers
"transform" in a static function 1 Answer