[Solved] Array index is out of range (mecanim)

Hi all, first time poster and C# beginner so please don’t destroy me :slight_smile: I’m making a simple rhythm game in Unity, and trying to write a script that triggers animations using code at specific frames of the song. I wrote a script that seemed to be working yesterday, though animations were sometimes triggering twice on a given frame. But in the process of debugging it something has happened, and now I get the following error:

IndexOutOfRangeException: Array index is out of range.
DanceInput.AnimatorInfo () (at Assets/Scripts/DanceInput.cs:71)
DanceInput.Update () (at Assets/Scripts/DanceInput.cs:58)

using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class DanceInput : MonoBehaviour
{

    public RhythmTool myRTool;

    public Animator myAnimator;
    //name of current animation clip
    string animClipName;
    //duration of animation in seconds?
    float animCurrentClipLength;
    //clip info
    AnimatorClipInfo[] animCurrentClipInfo;

    //player's score
    int currentScore = 0;
    public Text currentScoreText;
    public Text currentDesiredInputText;

    //max score
    int maxScore;

    //current frame of song
    private int currentFrame;

    //last frame at which input occured
    private int inputFrame;

    //frames at which each animation triggers, stored in arrays
    private int[] upStartFrames = new int[5] {100, 900, 1700, 2500, 3300};
    private int[] downStartFrames = new int[5] {300, 1100, 1900, 2700, 3500};
    private int[] leftStartFrames = new int[5] {500, 1300, 2100, 2900, 3700};
    private int[] rightStartFrames  = new int[5] {700, 1500, 2300, 3100, 4000};

    void Awake ()
    {

    }

    void Start ()
    {
       
    }

    void Update ()
    {
        currentFrame = myRTool.currentFrame;
        myAnimator.SetInteger("currentFrame", currentFrame);

        InputKey();
        TriggerAnimator();
        AnimatorInfo();


    }

    public void AnimatorInfo ()
    {

        //Fetch the current Animation clip information for the base layer
        animCurrentClipInfo = this.myAnimator.GetCurrentAnimatorClipInfo(0);
        int length = animCurrentClipInfo.Length;
        print("Length of array: " + inputFrame);
        //Access the current length of the clip;
           animCurrentClipLength = animCurrentClipInfo[0].clip.length;
        //Access the Animation clip name
           animClipName = animCurrentClipInfo[0].clip.name;
 
    }

    public void InputKey ()
    {
        if (Input.GetKeyDown("up")) {

                    inputFrame = currentFrame;
                    print("Player input UP arrow at frame: " + inputFrame);
                    Scoring();
                       

                } else if (Input.GetKeyDown("down")) {

                    inputFrame = currentFrame;
                    print("Player input DOWN arrow at frame: " + inputFrame);
                    Scoring();

                } else if (Input.GetKeyDown("left")) {

                    inputFrame = currentFrame;
                    print("Player input LEFT arrow at frame: " + inputFrame);
                    Scoring();

                } else if (Input.GetKeyDown("right")) {

                    inputFrame = currentFrame;
                    print("Player input RIGHT arrow at frame: " + inputFrame);
                    Scoring();

                }


    }

    void Scoring ()
    {
               
                //max acceptable range between input and desired frame (in frames)
                const int absoluteDifference = 30;

                if ((Input.GetKeyDown("up")) && (animClipName == "Up"))
                {

                    foreach(int element in upStartFrames)
                    {
                        if (Math.Abs(element -inputFrame) <= absoluteDifference)
                        {
                            currentScore++;
                            print("You have scored a point! Current score: " + currentScore);
                            SetCurrentScoreText();
                        }
                        else
                        {
                            currentScore--;
                            print("You missed. Current score: " + currentScore);
                            SetCurrentScoreText();
                        }
                    }
                } else if ((Input.GetKeyDown("up")) && (animClipName != "Up")){
                            currentScore--;
                            print("Wrong input! Current score: " + currentScore);
                            SetCurrentScoreText();
                }
   
    }

    void SetCurrentScoreText()
    {

        currentScoreText.text = "Points: " + currentScore.ToString();
    }

   

    void TriggerAnimator ()
    {

        if (upStartFrames.Contains(currentFrame)){

            myAnimator.SetTrigger("Up");
            print("Animation called " + animClipName + " triggered at frame " + currentFrame);
            print("Length of current clip: " + animCurrentClipLength + "seconds");
            maxScore++;

            currentDesiredInputText.text = "PRESS THE UP ARROW";


            } else if (downStartFrames.Contains(currentFrame)){

            myAnimator.SetTrigger("Down");
            print("Animation called " + animClipName + " triggered");
            print("Length of current clip: " + animCurrentClipLength + "seconds");
            maxScore++;

            currentDesiredInputText.text = "PRESS THE DOWN ARROW";

            } else if (leftStartFrames.Contains(currentFrame)){

            myAnimator.SetTrigger("Left");
            print("Animation called " + animClipName + " triggered");
            print("Length of current clip: " + animCurrentClipLength + "seconds");
            maxScore++;

            currentDesiredInputText.text = "PRESS THE LEFT ARROW";

            } else if (rightStartFrames.Contains(currentFrame)){

            myAnimator.SetTrigger("Right");
            print("Animation called " + animClipName + " triggered");
            print("Length of current clip: " + animCurrentClipLength + "seconds");
            maxScore++;

            currentDesiredInputText.text = "PRESS THE RIGHT ARROW";


            } else {

            myAnimator.Play("Idle");
            currentDesiredInputText.text = "DON'T PRESS ANYTHING";

            }

       


    }

       

       
}

After a bunch of googling, it seems clear that Unity thinks this array ( animCurrentClipInfo) is size zero, and that the problem is related to this bit that I’ve taken from the Unity API. But I can’t understand why it reads the array as being size 0 (and hence always out of range) when there is a base layer with 5 animation clips in it.

Any help would be appreciated. I’m really at a loss!

Please dont write this.myAnimator.GetCurrentAnimatorClipInfo(0);
C# might fail at this.
Rather use :

animCurrentClipInfo = myAnimator.GetCurrentAnimatorClipInfo(0);

Also, make sure there is a value in myAnimator, because its declared before the start, but I cannot see you defining it or assigning any values to it.

Cheers!

Sorry, the following statement is false – ‘this’ or without is the same thing.

Any luck with resolving this, otherwise?

Hi, thanks for the replies. @iamvideep_1 , this script was on an empty gameobject so I made the ‘myAnimator’ public and dragged another object into the slot.

removing ‘this’ didn’t change anything, but I did manage to solve it through trial and error: I deleted my existing animation controller, and remade it. But instead of using an ‘Idle’ animation as my base state, I just made all animations transition from ‘Any state’.

I have no idea why this fixed anything, though. Everything was the same aside from this (that I can see), so it must be how mecanim is reading arrays if you’re always transitioning from a base state…

thanks again for the replies!

Oh thats nice! You figured it out that you need to reference the animator and also the animations inside it need not be empty. Also, idle wont work usually for animations is what I have noticed in a couple of cases.

Please mark this as solved.

Cheers!