0

I'm currently creating a C# script for Unity containing many variables, and I want these to be changeable from other scripts.

To do so, I've currently written a function which asks the name of the variable (as a string) and then uses a switchcase for each variable.

public string charName;

public int currentHP;
public int maxHP = 100;

public int strength;
public int defense;

public void ChangeValue(string valueToChange, int howMuch)
{
    switch (valueToChange)
    {
        case "currentHP":
            currentHP += howMuch;
            break;

        case "maxHP":
            maxHP += howMuch;
            break;

        case "strength":
            strength += howMuch;
            break;

        case "defense":
            defense += howMuch;
            break;
    }
}

Would there be a more efficient way of doing this ? The switch case seems really inefficient, I'd need to modify it everytime I want to add a new variable to the script.

The perfect thing for me would be to ask the variable as an argument, but I can't figure out a way to do it.

Thank you for your time !

5
  • Why not defininig the appropriate interface and expose it? Commented Aug 22, 2019 at 8:59
  • 1
    since they are all public why not directly access those fields instead? Commented Aug 22, 2019 at 9:09
  • I'll later have to execute other functions when modifying a variable, which is why I can't access them directly. I'm looking into interfaces, which I didn't know about, and they might be the solution to my problem, thanks ! Commented Aug 22, 2019 at 9:11
  • 1
    I don't understand ... what other functions? Maybe you want to look into properties then. There you can simply add some check or additional behavior when setting a property ... example. Otherwise I would rather suggest a Dictionary<string, int> which would even be more efficient using a proper enum instead of strings Commented Aug 22, 2019 at 9:27
  • Properties are perfect for what I need ! Thank you very much ! Commented Aug 22, 2019 at 9:33

2 Answers 2

2

Since your use case actually is executing a certain behavior every time a value gets set I would suggest to rather use Properties. There are two options depending on your needs some examples (see here for more examples)

// Auto property which doesn't have any behavior
// read and write able
public string charName { get; set; }

// read only property
public int currentHP { get; private set; }

// read only property with a backing field
private int _maxHP = 100;
public int maxHP
{
    get { return _maxHP; }
}

// same as before but as expression body
private int _strength;
public int strength { get => _strength; }


// finally a property with additional behaviour 
// e.g. for the setter make sure the value is never negative 
private int _defense;
public int defense
{
    get { return _defense; }
    set { _defense = Mathf.Max(0, value); }
}

As you can see properties kind of replace getter and setter methods and in some cases even take the role of a field (Auto-Properties). In both the getter and the setter you can implement additional behavior. As soon as you do you have to use backing fields.

You can use and access them just like fields for example

someInstance.defense += 40;

executes both, first the getter in order to know the current value of _defense, then it adds 40 and uses the setter to write the result back to _defense.


As alternative and closer to your original approach is as said a Dictionary. I would combine it with a proper enum like e.g.

public enum ValueType
{
    MaxHP,
    Strength,
    Defense,
    CurrentHP
}

private Dictionary<ValueType, int> Values = new Dictionary<Value, int>
{
    {ValueType.MaxHP, 100},
    {ValueType.Strength, 0 },
    {ValueType.Defense, 0 },
    {ValueType.CurrentHP, 0 }
};

public void ChangeValue(ValueType valueType, int value)
{
    Values[valueType] += value;

    // do additional stuff
}

This has a minimal overhead of adding the values to be controlled by that method to both, the enum and the Dictionary.

Sign up to request clarification or add additional context in comments.

Comments

0

You can directly change the values of variables from another script if they are public.

Suppose you have a player object:

class Player : MonoBehaviour {
    public int currentHP;
    public int maxHP = 100;
}

You can access these values from another class as follows

class Enemy : MonoBehaviour {

    public Player player;

    void Start() {
        player.currentHP -= 10;
    }

}

You just have to assign player in the Unity Editor by dragging and dropping it onto, in this case, the Enemy script.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.