- Home /
Is there a simple replacement for a static variable?
So I'm using a key unlock system with a static boolean and then setting it to true and false via events, but my teacher hates static variables and calls them lazy and tends to mark me down for them, on the rare occasion I do use them. So my example is:
static var unlockDoor : boolean;
public var objectToDestroy : GameObject;
function Start () {
unlockDoor = false;
}
function OnTriggerEnter(other:Collider){
if(other.gameObject.tag == "Player" && unlockDoor == true){
Destroy(objectToDestroy);
unlockDoor = false;
}
}
And then I would unlock the door by doing this:
function OnTriggerEnter(other : Collider){
if(other.gameObject.tag == "Player"){
buttonUnlock.unlockDoor = true;
Destroy(this.gameObject);
}
}
What other alternatives are there? ( I've tried some and none work as simple as this does)
If this isn't a problem, and professional programmers use static vars all the time, I'm interested to know.
Answer by CHPedersen · Dec 08, 2013 at 02:37 PM
There's a reason the keyword exists. You're free to use static where applicable. :) What your teacher hates probably isn't the use of "static" in general, but using it in lieu of a proper instance variable, parameter passing or reference keeping. In that case its use IS lazy and indicates bad design.
For your example, the unlockDoor boolean should NOT be static, because it means the variable will be untied to any particular instance of your door, and will instead be a general property whose value holds for all doors. Setting "buttonUnlock.unlockDoor = true" then means ALL doors become unlocked, which defeats the purpose of manipulating this variable in OnTriggerEnter.
You should instead make either of the following:
A private boolean variable (non-static) called "locked", which is set to true or false in two methods, called "Lock" and "Unlock". These methods should be public, so you can call them on the door instance.
A public boolean property called Locked which exposes get/set methods. You would then set its value with syntax similar to the static, but again, on the INSTANCE of the door object.
An example of a variable whose value it is perfectly fine to keep static is Unity's own Mathf.PI, see the documentation:
http://docs.unity3d.com/Documentation/ScriptReference/Mathf.PI.html
The value of PI is constant and equal to 3.14... and is not a property whose value defines the state of any particular individual object. Such a variable is a natural static.
Beat me to it by 24 seconds, also using the same example reference to $$anonymous$$ath.PI. :)
I was about to write an answer but my cat distracted my for ~10 $$anonymous$$ so i knew i should first reloaded the page before i continue... Well two answers is enough ;)
ps: Sometimes even constants are better defined in an instance. In Unity it might not be that applicable since Unity introduces a lot global state on it's own, but in general it simplifies testing. Of course there are true constants like PI. It makes no sense to use any different value for PI, so that's ok.
$$anonymous$$y apologies, gentlemen. I know how frustrating it is to get ninja'd. ;)
I kind of regret using $$anonymous$$athf.PI as an example. It's listed as static on the docs, but really, it should be const, since it will never change and should be a compile-time constant; purely static vars can change at runtime.
A better example might've been the SystemInfo.graphicsShaderLevel variable, as that's a variable that depends on the local system (thus non-const) and is unassociated with any objects and valid across the entire scope of the application.
Answer by MartinCA · Dec 08, 2013 at 02:38 PM
It's kind of difficult to answer you question, as it is a design question, and without a better understanding of the system all I can give you is some best practice pointers.
A static variable is a variable which lives outside the context of an instance. For example, the constant PI, or any of the Mathf class methods. None of those things are logically related to a single instance of Mathf.
In your case however, a door's lock state can be definitely tied to an instnace, or a specific door. Consider this, you have your Door class, this class defines "a door". However, if you want to define a specific door, you'll refer to it's instance rather than it's class - "the blue door is a door", the which is answered by "the blue door" - the instance, while the what is answered by "a door" - the class.
In such case, defining unlockDoor as static is wrong, and bad, because you're using a static variable as a global, which is what get's people really worked over.
A better definition would be like so: A door can be either locked or unlocked. A locked door is opened using a specific key:
class Door
{
bool isLocked;
string keyType;
}
The player has a keyring, which holds all of his keys:
class Player
{
Keyring doorKeys;
}
A keyring holds all of the keys the player has acquired. A keyring can be checked to see if it contains a required key:
class Keyring
{
string[] keys;
bool HasKey( string keyType );
}
When the player reaches a door, he checks the lock type on the door ( it's a blue door lock, it's a small door lock, etc... ), he then checks his keyring for the appropriate key, and if his keyring contains the right key, he will use it to unlock the door:
OnTriggerEnter( Collider other )
{
Door door = other.GetComponent< Door >();
// Make sure the trigger is actually a door trigger
if ( door != null )
{
string keyType = door.keyType; // Check the door's key type
if ( keyring.HasKey( keyType ) )
{
door.Unlock()
}
}
}
Your answer
Follow this Question
Related Questions
Static Variable Problem 1 Answer
Prefab's Script affecting all the Prefab 1 Answer
Static, yet Private, Variables? 1 Answer
Trivial question for Javascript/Unityscript experts: static variables? 4 Answers
How to make a var "global" 0 Answers