I have 1 “controllScript” that controls almost everything, except for the movement and such of some GameObjects that have their own scripts. But thees GameObjects need to reed a variable that the controllScript controlls. Is it better to have that variable be static and just do
Statics are alright in some cases, but you should be careful when getting them. Honestly, I use looots of statics in my central ControlScript gam object. Some people may tell you to use static, few may tell you to use a singleton, but they’ll all tell you to be careful. There can be memory leaks and “weird” (unpredicted due to how static works) behavior.
In my opinion, use the first if that variable DOESN’T directly change outside of itself (as in, script.variable = tothisnow). If I recall correctly, you can get some “weird” behavior by trying to change a static variable in another script and then try to access it from the script itself (it’ll seem like it didn’t change).
Use the second method only in the start function, if you’re going to use it.
Sorry for rushing through this. There are more reasons to use (or not to use) either of them, as well as a few other “methods” and tips to do the same thing, but hope this helps.
Edit: Also, I typically cache the script/object itself, since I access quite a few functions (non-static) and variables as well as a few other things.
Does the BattleController need to make use of Unity methods such as Awake, Start, Update, FixedUpdate, On? If so it needs to be a monobehaviour and you should treat it as a Singleton.
If not you can make it a Static class, but BattleController sounds like the kind of script that eventually is going to want to do things that only a MonoBehaviour can do. There are lots of ways to set up a singleton, the way nearest to your current usage would look something like this…
public class BattleController : MonoBehaviour
{
static _instance = null;
public static Instance {
get {
if (_instance == null){
_instance = GameObject.FindGameObjectWithTag("MainCamera").GetComponent<BattleController>();
}
return _instance;
}
}
float _sp;
public float SP { get { return _sp; }}
void ExampleUsage(){
// You can now access this 'singleton' from any script through BattleController.Instance
float currentSp = BattleController.Instance.SP;
}
}
The advantage of doing this is that GetComponent is kind of slow. GameObject.Find***** is very slow. Both should be avoided whenever possible, and cached when needed. For the most part, if you need to get it more than once cache it (this goes for things like .transform as well - cache it as it’s really just a shortcut for this.GetComponent()).
edit: Not sure what was going on in MDragon’s case but you shouldn’t experience any issues at all accessing or adjusting static variables across classes. As long as you understand exactly what a static variable/method is the usage should be completely predictable.
…Dang, I meant static variables in general scripts (in a way). I’d also avoid a static class and rather go with a MonoBehaviour singleton- but I’m also an idiot, and like to go with Find.GetComponent.
Yes, it does use the methods from MonoBehaviour. But why cant I just make a variable static, not the whole class?
And what makes a singleton better? Tried reading up on it, but didn’t really get why it’s better than static variables.
It’s not better than static variables, it’s just different. If you don’t need ‘instantiated’ behavior there is really very little difference (other than the fact that with a Singleton you control the lifespan of all of the member data - but that’s probably not terribly relevant to you right now). You, however, do need instantiated behavior - meaning you need at least one actual instance of your class (so that you can use Awake / Start / OnAnimatorMove / Update…) and presumably only. With just static variables you have no way to publicly access instance level methods or properties. If you literally just need some read only variables this may not be a big deal, but what happens when you need to say:
MyClass.DoMethod();
eventually? By only using static variables you preclude yourself from doing two very important things:
1: Communicating with the Singleton (you are using a Singleton already, you just don’t have a way to access it from other classes)
2: Enforcing the Singleton (by just using static variables you have no way of saying “I want one of this class to exist when needed, but only ever one of this class.”
Let’s say I have myClass which has public variable myMode. I need to read that variable from another script/class but myClass does not have instance defined and it is not possible (don’t ask, such conditions). So, since myClass is attached to gameObject I can just do gameObject.GetComponent<myClass>().myMode.
The problem arises from the fact I need to put watchdog on any changes of that variable in Update. Which means I’m essentially checking it every frame. So it is every frame. Not okay. I was thinking to make it less worse by storing component when scene is loaded once and reuse it, however this:
public Component ModeWatch;
//...
ModeWatch = gameObject.GetComponent<myClass>();
//...
var x = ModeWatch as myClass;
var y = ModeWatch.MyMode.ToString();
wont work obviously. Any ideas how to reduce performance hit with GetComponent calls? Besides obvious “dont do that”. I NEED to get that variable’s value without changing myClass at all.