Using Arrays to Organize Variables

I have some code that is working well, but I would like to optimize and organize it. I am new to C# and do not yet know the best practices, so here is an example of something short I have written that I would like to ask a few questions about.

The piece of code manages three stats (say Food, Hunger, and Damage) and sends updates on their values to Sliders F,H, and D to keep them displaying the proper values. At three different intervals, I want to be able to call these numbers to “tick” down, so I tried to make a generalized “tickStat” function. At first I had each stat in its own field and I tried to pass a reference to that variable into the function so that it could be ticked down appropriately, but then I found that you cannot pass references in C#. On this board, it was advised to use arrays to keep track of the similar stats and to use an index to choose which stat to effect (as in the code below). Is this the best way to go about what I want to do? Is there a way to organize things so that they are conceptually grouped by Stat?

You can also see that I did not do this array refactoring for the public Slider fields. I could not figure out how to properly declare an array of Sliders. I could also use help on that :slight_smile:

enum stat {f, h, d};

private Slider[] sliders;
private float[] tickRates;
private float[] tickAmounts;
private float[] totals;
private float[] currents;

public Slider sliderF;
public Slider sliderH;
public Slider sliderD;

void InitializeStatArrays()
{
	sliders = new Slider[] {sliderF, sliderH, sliderD};
	tickRates = new float[] {.5f, 1.0f, 2.0f};
	tickAmounts = new float[] {1f, 1f, 1f};
	totals = new float [] {100f, 100f, 100f};
	currents = new float[] {100f, 100f, 100f};
}

void Start () {
	InitializeStatArrays();

	StartCoroutine(tickStat((int)stat.f, sliders[(int)stat.f], tickAmounts[(int)stat.f], tickRates[(int)stat.f]));
	StartCoroutine(tickStat((int)stat.h, sliders[(int)stat.h], tickAmounts[(int)stat.h], tickRates[(int)stat.h]));
	StartCoroutine(tickStat((int)stat.d, sliders[(int)stat.d], tickAmounts[(int)stat.d], tickRates[(int)stat.d]));

}

IEnumerator tickStat(int thisStat, Slider thisSlider, float thisMuch, float thisManySeconds)
{
	while (currents[thisStat] > 0f)
	{
		currents[thisStat] -= thisMuch;
		thisSlider.value = currents[thisStat];
		yield return new WaitForSeconds(thisManySeconds);
	}
}

You can send references as arguments, just use the ref keyword. The way you declare an array of sliders is the same as every other array declaration: Slider[], which you have in your code.

The way you’re doing this is of course not the best way of doing it (Hell, arrays are like the 2nd worst way to do it), as that would probably be creating a class to hold the values you need, and then declare the functions that will use them. That would also group them by Stat, if the class you declared them in was called Stat.

More on classes here: Classes | Microsoft Learn

how about a list of stats?

private List<Stat> stats;

class Stat
{
    private float _time;
    private float _rate;
    private Slider _slider;

    public Stat(string name, float value, float time, float rate)
    {
        _time = time;
        _rate = rate;
        foreach (Selectable selectableUI in Selectable.allSelectables)
        {
            if (selectableUI.name == name)
            {
                _slider = (Slider)selectableUI;
                _slider.value = _slider.maxValue = value;
            }                    
        }
    }

    public IEnumerator Tick()
    {
        // possible that slider not found so check for null
        while (_slider != null && _slider.value > _slider.minValue)
        {
            _slider.value = Mathf.Max(_slider.value - _rate, _slider.minValue);
            yield return new WaitForSeconds(_time);
        }
    }
}

private void Start()
{            
    stats = new List<Stat>();
    // create a stat for the slider. name (must match name in editor), max/initial value, update time, update rate
    stats.Add(new Stat("SliderF", 100f, 1f, 0.5f));
    stats.Add(new Stat("SliderH", 100f, 1f, 1f));
    stats.Add(new Stat("SliderD", 100f, 1f, 2f));

    foreach (Stat stat in stats)
    {            
        StartCoroutine(stat.Tick());
    }
}