Luren Wang
Luren Wang

Reputation: 55

Unity: ArgumentException: Value does not fall within the expected range

I have met a strange problem when using Coroutine in Unity. Before modification, my code is as the following:

IEnumerator Destory()
{
    yield return new WaitForSeconds(destoryDelay);
    yield return StartCoroutine(Timer.Start(0.5f, false, gameManager.EnableBtnSummon));
    GameObject.Destroy(this.gameObject);
}

Time.Start() is an utility written by myself and used for delay invoke.

public static IEnumerator Start(float duration, bool repeat, Action callback)
{
    do
    {
        yield return new WaitForSeconds(duration);                
        if (callback != null)
            callback();
    } while (repeat);
}

Because Time.Start() includes WaitForSeconds(), so I decided to modify above code as the following:

IEnumerator Destory()
{
    //yield return new WaitForSeconds(destoryDelay);
    yield return StartCoroutine(Timer.Start(destoryDelay+0.5f, false, gameManager.EnableBtnSummon));
    GameObject.Destroy(this.gameObject);
}

Unfortunately, console throw an error:

ArgumentException: Value does not fall within the expected range.

gameManager.EnableBtnSummon is just an Action processing game logic. After debug, i make sure that error occurred before this function run. But i will show it for more clues.

public void EnableBtnSummon()
{
    //will not reach this!
    print("Enable Button Summon");
    //if detecting monster, change relative sprite of monster medal
    if (currentMonsterIndex != -1)
    {
        Image captureMonsterSprite = monsterMedalList.transform.GetChild(currentMonsterIndex).GetComponent<Image>();
        captureMonsterSprite.sprite = mosnterExplicitMedalList[currentMonsterIndex];

        Image gameOverMonsterSprite = gameOverMonsterList.transform.GetChild(currentMonsterIndex).GetComponent<Image>();
        gameOverMonsterSprite.sprite = mosnterExplicitMedalList[currentMonsterIndex];

        currentMonsterIndex = -1;
        captureMonsterCount++;
    }

    if (captureMonsterCount == monsterIndexDictionary.Count) return;

    var summonAnimator = btnSummon.GetComponent<Animator>();
    summonAnimator.SetBool("isSearch", false);

    btnSummon.enabled = true;
    btnExit.enabled = true;

    fogParticleSystem.Play();
}

I cannot understand it, could someone tell me what happens? thx...

Upvotes: 2

Views: 32108

Answers (1)

Programmer
Programmer

Reputation: 125245

The exception:

ArgumentException: Value does not fall within the expected range.

is happening on this line of code:

yield return StartCoroutine(MoveTowards.Start(destoryDelay + 0.5f, false, gameManager.EnableBtnSummon));

This has nothing to do with StartCoroutine as the title of the question says. The source of the problem is the MoveTowards.Start coroutine function. The third parameter(Action callback) that is passed into it is the issue.

The issue is that you are passing null to the third parameter of the MoveTowards.Start function. Since you are passing gameManager.EnableBtnSummon to that third parameter, this means that the gameManager variable is null.

You can verify this by adding Debug.Log(gameManager) before that line of code. The output should be "null" in the Console tab.

FIX:

Initialize the gameManager variable:

Name the GameObject your GameManager script is attached to "ManagerObj" then use the simple code below to initialize the gameManager variable.

GameManager gameManager;

void Awake()
{
    gameManager = GameObject.Find("ManagerObj").GetComponent<GameManager>();
}

Note:

Rename your Start function to something else as there is already Unity built in function named "Start" and "Awake". You need to change the name to something else but this is not the problem.

Upvotes: 12

Related Questions