Hi all, first time poster and C# beginner so please don’t destroy me 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!