Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the best practice to using the static variable in C# of Unity

Tags:

c#

unity3d

According to this tutorial demonstrated on youtube

It is working to make a static variable to hold the score and change it in other scripts when the player should be awarded, but it also advised that using static variable in C# script of Unity might not be recommended.

Flowing is what I do to construct the scoring system:

in ScoreManger which was bonded to an UI Text component to show the score:

public class ScoreManager : MonoBehaviour {
    public static int score;
    Text text;
    private void Awake()
    {
        text = GetComponent<Text>();
    }
    private void FixedUpdate()
    {
        text.text = "Score: " + score;
    }
}

And the procedure to add the score:

private void OnCollisionEnter2D(Collision2D collision)
{
    if (collision.gameObject.CompareTag("Player"))
    {
        ScoreManager.score = ScoreManager.score + score;
        Destroy(gameObject);
    }
}

So what's the best way to do this without a static variable, and if someone could explain why using a static variable is not recommended will be more grateful.

EDIT

Have tried the event handle way as @rogalski demonstrated in the answer, but the IDE shows that there is an error for type conversion on the lambda function of ExecuteEvents.Execute<T> enter image description here

like image 921
armnotstrong Avatar asked Mar 02 '17 11:03

armnotstrong


People also ask

When should I use static variables in C?

static variable is used for a common value which is shared by all the methods and its scope is till the lifetime of whole program. In the C programming language, static is used with global variables and functions to set their scope to the containing file.

Is it good practice to use static variables?

Static variables are generally considered bad because they represent global state and are therefore much more difficult to reason about. In particular, they break the assumptions of object-oriented programming.

Which is the best way to declare a static variable?

Static variables can be accessed by calling with the class name ClassName. VariableName. When declaring class variables as public static final, then variable names (constants) are all in upper case. If the static variables are not public and final, the naming syntax is the same as instance and local variables.

Which of the following is correct about static variables?

3. Which of the following is correct about static variables? Explanation: Static member functions can access static data members only.


2 Answers

You have to remember that Unity is a component based engine meaning that components have to do some specific work independently. This can be well combined with event driven programming methodology which mean that application ( or each of it's components ) are dependant on some event input.

Unity introduced really well designed Event ( or Messaging ) system which you should use instead of making static fields, classes etc.

To point you out in the right way of implementing this I'll use the most trivial example.

( EDIT -> Added definition for EventData which is required for Unity's messaging system )

First register your event :

public interface ICoinPickedHandler: IEventSystemHandler
{
    void OnCoinPickedUp(CoinPickedEventData eventData);
}

Then implement this EventTarget into your script :

public class ScoreManager
    : MonoBehaviour, ICoinPickedHandler
{
    private int m_Score;

    public void OnCoinPickedUp(CoinPickedEventData eventData)
    {
        this.m_Score += eventData.Score;
        eventData.Use();
    }

    // code to display score or whatever ...
}

Now to use this you have to just fire the event :

private void OnCollisionEnter2D(Collision2D collision)
{
    if (collision.gameObject.CompareTag("Player"))
    {
        // assuming your collision.gameObject
        // has the ICoinPicker interface implemented
        ExecuteEvents.Execute<ICoinPickedHandler>(collision.gameObject, new CoinPickedEventData(score), (a,b)=>a.OnCoinPickedUp(b));
    }
}

Now you have to create EventData :

public class CoinPickedEventData
    : BaseEventData
{
    public readonly int Score;

    public CoinPickedEventData(int score)
        : base(EventSystem.current)
    {
        Score = score;
    }
}

Of course this example requires from you to know the target to which you want to send that event. But if you do not know the target, you can use approach to ExecuteHierarchy.

More on that topic on docs.unity3d.com.

like image 176
Mateusz Avatar answered Sep 30 '22 06:09

Mateusz


First of all , it would be better to wrap the static variable in a method: addToScore , so in case behavior changes you only have to implement the changes once.

For the static variable: I think it would be better to make the score manager a singleton instance instead of a static variable. Because then if you decide you need more score managers, reset the score manager, save more data in the score manager or whatever it will be a lot easier.

like image 44
Mark Smit Avatar answered Sep 30 '22 06:09

Mark Smit