Setting public static variables in a static class
Hi all, I'm not finding anything that seems to address this issue:
I'm creating a static class for holding all of the sprites for players. That way, I only have to assign the sprites once and any player can get them by accessing the static class.
example:
public static class PlayerSprites {
public static Sprite faceLeft;
public static Sprite faceRight;
public static Sprite getSprite(Orientation orientation)
{
if (orientation.facing == "left")
{
return faceLeft;
}
else
{
return faceRight;
}
}
}
Orientation
is simply a class that holds a series of ways the character can behave:
public class Orientation {
public string facing = "left";
public bool standing = true;
public bool shooting = false;
}
}
However, I can't seem to find any way to set the public Sprite variables. Is there a way to do this?
even though you may think it irrelevant, you should show the structure/class for Orientation
. why are you using a string for facing
and not an enum
? string comparisons are slow...
what do you mean by "I can't seem to find any way to set the public Sprite variables"?
I added the orientation class, but I really do believe it is irrelevant to the question. It's just a collection of flags so I can keep track of what the player is doing and assign the right sprite. The spring comparison is only a temporary thing I threw in there to get it work. I'll come up with something better later.
As for the original question, I have a static class with static public variables. Is there any way to set static public variables in a static public class from the inspector?
Answer by ian_sorbello · Nov 18, 2015 at 01:27 AM
Your entire class does not need to be static - just the accessor, i.e. getSprite().
Something like this would work:
public class PlayerSprites : Monobehaviour {
public Sprite faceLeft;
public Sprite faceRight;
private static PlayerSprites _instance;
void Start() {
_instance = this;
}
public static PlayerSprites Instance() {
return _instance;
}
public Sprite getSprite(Orientation orientation)
{
if (orientation.facing == "left")
{
return faceLeft;
}
else
{
return faceRight;
}
}
}
You can then add this component (it's now a MonoBehaviour) on an object in your hierarchy. Then use Unity to drag and drop the Sprites you like into the public variables.
Then finally, you can get access to your sprites like this:
Sprite s = PlayerSprites.Instance().getSprite(orientation);
Nope, that won't work. You may ask why, because if your getSprite is static then you cannot use non static member within (faceLeft/Right).
I guess you meant getSprite to be non-static, then we're good. Also, I would recommend to use a DontDestroyOnLoad to make the object survive new scenes but then make sure to destroy any new instance that would duplicate.
Very interesting idea, I hadn't thought of that.
Does the underscore have a specific property about it in C#/Unity? Or was that just a convention you like to use?
I'll play around with this and see what I can do with it. It may help me in other areas too.
Underscores don't do anything special, so that's just their convention.
The problem with this, is that it requires an object in the scene with this script attached. Which means you need to make it a prefab singleton so every scene can have it. Also, as fafase mentioned, if the getSprite accessor is static it won't work as shown, just the instance variable/method should be static with a proper singleton setup in Awake.
Yes - agree - it does require an object in the scene with a script attached - but this is a strategy that has worked well for me.
And, it is a singleton, not a static class - hence why the static based Instance() method.
The reason why I think this is a handy pattern, is that your code can access the underlying assets through the getSprite() method (does not need to be static) - and the component itself is visible in the hierarchy window, so you can drag and drop your other assets (sprites) onto it easily.
The object is a dummy object - it doesn't need to be visible or be anywhere special.
If you make the object a prefab - then you can bring this into any scene you like...
I modified the answer since it was wrong. getSprite cannot be static to work in the current context and to be used as you showed.
Answer by OncaLupe · Nov 18, 2015 at 05:56 AM
I'd look into Scriptable Objects. They're items that stay in your Assets, but can hold data like a script. You can access the data from any script in your scene like a Static, but the contents are visible in the inspector as well. Also, since it's an asset, any changes made to it in runtime are saved. They take a little to set up, but should work perfectly for what you want.
http://unity3d.com/learn/tutorials/modules/beginner/live-training-archive/scriptable-objects
I didn't know about these. I really like the idea of scriptable objects. The more I work in Unity, the less I like working in the Inspector and the more I like to script everything, so this is right up my alley. Thanks.
Your answer
Follow this Question
Related Questions
I cant access a script that I made in Assets/Scripts from the FirstPersonCharacter script. 1 Answer
Managing In-Game Variables of Different Data Types 1 Answer
Game Objects not using same script independently. 1 Answer
Inheriting values from base class in c# 0 Answers
Static Class Strings not truly null? 1 Answer