Trouble trying to automate function (index out of range?)

As the player plays my game, he unlocks rewards progressively, some time ago for testing purposes I tried to implement a system and only had 2 rewards, it worked but now Im trying to add more rewards and it seems Im breaking the script for some reason (IndexOutOfRangeException: Array index is out of range.)

The old script which worked correctly:

void Start() {
        for (int i =0; i < unlockReward.Length - 1; i++) {
            currentReward = i;
            rewardBar.maxValue = unlockReward*;*

}
if (SaveManager.Instance.state.unlockableSkins[0] == true) {
currentReward = 1;
}
if (SaveManager.Instance.state.unlockableSkins[1] == true) {
currentReward = 2;
}
if (SaveManager.Instance.state.unlockableSkins[0] == false) {
currentReward = 0;
}
}
The new automated function, not working (console displaying IndexOutOfRangeException):
void Start() {
for (int i =0; i < unlockReward.Length - 1; i++) {
currentReward = i;
rewardBar.maxValue = unlockReward*;*
}
if (SaveManager.Instance.state.unlockableSkins[currentReward] == true) {
currentReward = currentReward++;
}
if (SaveManager.Instance.state.unlockableSkins[currentReward] == false) {
currentReward = currentReward;
}
}
This function should be pretty simple, at the start of the scene, the game checks if you have the first reward already unlocked, if so it checks the second and so on, until it finds where you stopped.
The values which the script access :
int currentReward = 0;
private int[] unlockReward = new int[] { 30, 40, 60, 40,50};
(…)
public class SaveState
public bool[] unlockableSkins = new bool[] { false, false, false, false, false } ;

The reason you are getting an IndexOutOfRangeException is that when the for loop finishes, i has a value of 5 which makes it >= unlockReward.Length therefore ending the loop. You are setting currentReward = i; (5) and then you are trying to access SaveManager.Instance.state.unlockableSkins[currentReward] with a currentReward value of 5 which doesn’t exist in the array.

Try doing something of this sort:

for (int i =0; i < unlockReward.Length - 1; i++) {
	if (SaveManager.Instance.state.unlockableSkins *== true) {*

currentReward = i;

  • }*
    }

rewardBar.maxValue = unlockReward[currentReward];
This loop goes through all the boolean values of your unlockableSkins array and sets the value of currentReward equal to i if the condition is true. At the end it sets the bar value to the best reward unlocked as stored in the currentReward variable.

Your code has several logic errors:

First of all this loop is pretty pointless:

     for (int i =0; i < unlockReward.Length - 1; i++) {
         currentReward = i;
         rewardBar.maxValue = unlockReward*;*

}
All it does effectively is this:
if (unlockReward.Length > 1)
{
currentReward = unlockReward.Length-1;
rewardBar.maxValue = unlockReward[currentReward - 1];
}
Since your currentReward always ends up as unlockReward.Length - 1 currentReward always has the index of the last reward.
If that last reward is true, you increase currentReward by one which now points to an index out of bound (assuming the unlockableSkins and unlockReward array has the same length)
if (SaveManager.Instance.state.unlockableSkins[currentReward] == true) {
currentReward = currentReward++;
}
Since currentReward is now one after the last element the following code throws an out of bounds exception:
if (SaveManager.Instance.state.unlockableSkins[currentReward] == false)
Finally the body of the last if statement is pointless
currentReward = currentReward;
This has no effect unless currentReward is a property which could have side effects.
You really should rethink about your whole algorithm. I can’t make much sense of it so it’s not clear what value means what. If the rewards always unlock sequencially you don’t need all those booleans at all. The currentReward would be enough.
If you want to keep your current boolean array, you can simply find the last not yet unlocked reward by doing
currentReward = 0;
var skins = SaveManager.Instance.state.unlockableSkins;
while(currentReward < unlockReward.Length && skins[currentReward])
currentReward++;
Note that currentReward will not be either the first reward that is not unlocked yet, or it will be out of bounds in case all rewards had been unlocked already. This case you may want to take care of. So:
if (currentReward >= unlockReward.Length)
{
// All rewards unlocked.
}
Of course currentReward does not represent a valid index at this point and must not be used as an index into one of your arrays.
ps: I just realised that this line actually makes no sense either:
currentReward = currentReward++;
You use the post increment operator but assign the return value to the variable itself. This will have no effect at all. The post increment operator does evaluate the current value first, then it increments the variable and then it returns the initially evaluated value. To break this line down into single steps, this is what happens:
int tmp = currentReward; // evaluate current value
currentReward = currentReward + 1 // increment variable
currentReward = tmp; // do the actual assignment of the evaluated value.
So in the end nothing changes at all.