- Home /
Instanced Prefabs: Audio clip array out of range
Hi guys,
I have prefab characters, each with an audiosource and a tiny script that should play random audioclips from an array. But I always get a "out of range error".
It has to do something with the instantiated prefabs. When i put my script on an object within the scene it works as expected.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Person : MonoBehaviour
{
private Animator ani;
private AudioClip[] yeahs;
public AudioClip[] yeahs2;
private AudioSource speaker;
void Start()
{
ani = GetComponent<Animator>();
ani.SetInteger("level", Random.Range(0, 7));
speaker = GetComponent<AudioSource>();
yeahs = Resources.LoadAll<AudioClip>("Assets/_Audio/yeah/");
Debug.Log("YEAHYEAHYEAH" + yeahs);
}
void Update()
{
new WaitForSeconds(Random.Range(3, 10));
ani.SetInteger("level", Random.Range(0, 8));
speaker.PlayOneShot(yeahs2[Random.Range(0, yeahs2.Length -1)]);
}
}
any tipps appreciated!
cheers
Answer by Legend_Bacon · May 08, 2019 at 12:52 PM
Hello there,
As far as I can tell from this script, you are never populating "yeahs2", which means it effectively has a length of 0.
Of course, as soon as you try to call PlayOneShot() in your Update(), there is nothing to play. So it gives you a null exception.
Since your yeahs2 variable is public, I am guessing you are assigning it somehow in the inspector (or on the prefab itself). Could you share your instantiation code here? There may be something wrong in there...
Other than that, please make sure you understand how the Update() function works in Unity. Your "new WaitForSeconds[...]" line does nothing, for example. Also, I am assuming you don't want to set the Integer of your animator to a random number 60 times per second (the rate at which Update is called), or Play your sound that often.
Hope that helps!
Cheers,
~LegendBacon
Hi!
Yes, the yeas2[] is size 3 and I setup the audioclips within the inspector. Why do you think the WaitforSeconds() does not work? I am triggering the animation controller of my instanciated prefabs with it. As far as I can tell it works. I know that it blocks the update loop, but I don't need a Coroutine in that $$anonymous$$i script.
As mentioned above, if I put the script on an empty gameobject within the scene my code works.
Hello there,
The WaitForSeconds() is not intended to work within "regular" functions. As far as I know, it only works when yielded ( yield return new WaitForSeconds(x);
) from within a coroutine (IEnumerator). It does NOT block the update loop.
Try putting a Debug.Log() in your update before and after the line, and you will see that they both trigger in the same frame (and up to 60 times per second as well).
Additionally, your line does not actually wait for anything here. You are just creating a new instance of the WaitForSeconds class. But since you are not assigning it or using it, it is essentially doing nothing.
Could you also tell us exactly which line the error points to? If it is speaker.PlayOneShot(yeahs2[Random.Range(0, yeahs2.Length -1)]);, then try outputting the length of the yeahs2 array. You will see that on at least one of your objects, this will return an invalid length (0 or 1).
Another thing: When used with Integers, Random.Range()'s $$anonymous$$AX value is actually EXCLUSIV$$anonymous$$ Which means you should have Random.Range(0, yeahs2.Length)
ins$$anonymous$$d of Random.Range(0, yeahs2.Length -1)
. Otherwise the last entry will never be selected by the Random function.
And a last point: You script, when thrown on a gameobject in the scene WILL work as is, but not efficiently, and not necessarily as intended (it won't wait, for example). It will call ani.SetInteger("level", Random.Range(0, 8));
and speaker.PlayOneShot(yeahs2[Random.Range(0, yeahs2.Length -1)]);
60 times a second, which is most likely something you don't want.
I hope that helps!
Cheers,
~LegendBacon