Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by Mijn · Jun 10, 2018 at 10:36 AM · arrayaudioaudioclipsequencechild-to-gameobject

Play Audio in sequence from children objects

Hi everyone, I am asking your help.. after two days of trying and digging forums and tutorials.. I have in my scene an object called "collector". This object will move around the space and if it collides (trigger enter) with an object tag "sculpts", this become a child of the collector. So far so good..

Each of this "sculpts" objects have an AudioSource with a clip. I need to do that when the collector has one or more child objects, it checks the AudioSources of each child, and play the clips of each child one after the other.. in the order of the child. This is the script I came up with, but I get an error and does not work and I have no idea how to solve this.. Please anyone out here! Help! <3

Here is the code:

 using UnityEngine;
 using System.Collections;
 using System.Collections.Generic;
 
 public class audioSequencer : MonoBehaviour
 {
     private GameObject parentObject;
     private AudioSource[] myAudioSources;
     private AudioClip[] clips;
     private int childCount;
 
     private bool playNow = false;
     private int cnt = 0;
 
 
     private void Awake()
     {
         parentObject = this.gameObject;
 
     }
 
 
     void OnTriggerEnter(Collider other)
     {
         childCount = transform.childCount;
         myAudioSources = parentObject.GetComponentsInChildren<AudioSource>();
         Debug.Log(myAudioSources.Length);
         foreach (AudioSource myAudioSource in myAudioSources)
         {
             clips = parentObject.GetComponentsInChildren<AudioClip>();
         }
     }
 
     private void Update()
     {
 
 
         if (childCount > 0)
         {
             playNow = !playNow;
 
             foreach (AudioSource myAudioSource in myAudioSources)
             {
                 myAudioSource.Stop();
             }
 
         }
 
         if (playNow)
         {
             PlaySounds();
         }
     }
             
 
     public void PlaySounds()
     {
         while (true)
         {
             for (int i = 0; i < myAudioSources.Length; i++)
             {
                 if (!myAudioSources[i].isPlaying && cnt < clips.Length)
                 {
                     myAudioSources[i].clip = clips[cnt];
                     myAudioSources[i].Play();
                     cnt = cnt + 1;
                 }
 
                 if (cnt == clips.Length)
                 {
                     cnt = 0;
                 }
             }
         }
     }
 }

and this is the error I get:

 ArgumentException: GetComponent requires that the requested component 'AudioClip' derives from MonoBehaviour or Component or is an interface.
 UnityEngine.GameObject.GetComponentsInChildren[AudioClip] (Boolean includeInactive) (at /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/GameObjectBindings.gen.cs:142)
 UnityEngine.GameObject.GetComponentsInChildren[AudioClip] () (at /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/GameObjectBindings.gen.cs:159)
 audioSequencer.OnTriggerEnter (UnityEngine.Collider other) (at Assets/Scripts/audioSequencer.cs:30)


Comment
Add comment · Show 2
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image bakir-omarov · Jun 10, 2018 at 11:01 AM 0
Share

Do you need to replay all audio clips of children (for example play 1,2,3... and again 1,2,3...)? Or you just want to play once every audio clip and remove it from sequence (for example play 1,2,3... and wait for new collisions and play them)? I can help you with right code if clarify this moment.

avatar image Mijn bakir-omarov · Jun 10, 2018 at 11:27 AM 0
Share

I am not sure yet, I think the script of Captain_Pineapple works great, but would be cool to know how to have the sequence played once only, just in case. But Having the sequence working at all is SUPER for now! I was so frustrated eheh :-P

3 Replies

· Add your reply
  • Sort: 
avatar image
0
Best Answer

Answer by Captain_Pineapple · Jun 10, 2018 at 11:17 AM

Hey there,

There are some things that you look into:

AudioClips are no Components of Objects. So there is no way to get them by calling GetComponent with AudioClip as Type. Also NEVER implement a while-true loop in a function without a way to break it. You will just loop infinetly with your programm freezing. Also you don't need it since an audiosource that is set to play will just play it clip until it finishes.

i adjusted your script to the way you probably want it to work.

 public class audioSequencer : MonoBehaviour
  {
      private List<AudioSource> myAudioSources;
      //private int childCount;
  
      private int cnt = 0;
  
      public void Start()
     {
         myAudioSources = new List<AudioSource>();
     }
  
      void OnTriggerEnter(Collider other)
      {
          //check if entered object has an audiosource attached:
          if(other.GetComponent<AudioSource>())
          {
              //add to list:
              myAudioSources.Add(other.GetComponent<AudioSource>());
              //check if this is the first object:
              if(myAudioSources.Count == 1)
              {
                  //if yes play it, from here the update will take over playing the clips
                  myAudioSources[0].Play();
              }
          }
      }
  
      private void Update()
      {
         if(myAudioSources.Count > 0)
         {
             //check if current clip has ended:
             if(!myAudioSources[cnt].isPlaying)
             {
                 cnt += 1;
                 //reset count if we reched the end of the current List:
                 if(cnt >= myAudioSources.Count)
                 {
                     cnt = 0;
                 }
                 //play next clip:
                 myAudioSources[cnt].Play();
             }
         }
      }
  }

Please note that i did not test the code for functionality and it will only work as inteded when your audioSources do NOT have the loop checkbox set to true.

If something is unclear or does not work as inteded feel free to ask.

Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Mijn · Jun 10, 2018 at 11:25 AM 0
Share

O$$anonymous$$G THAN$$anonymous$$ YOU SO $$anonymous$$UCH! I COULD NOT SLEEP LAST NIGHT BECAUSE OF THIS! I am fairly new to code, so some things are still very unclear to me (like the while-true loop) but I am trying to learn by doing.. and sometimes it gets too hard for my brain to solve.. Your script works perfectly! thank you so much!

just in case: if I want the audio sequence being repeated just once, I would need to move it to a separate void (so not update but lets say, PlaySounds()) and use PlayOneShot ins$$anonymous$$d?

avatar image Captain_Pineapple Mijn · Jun 11, 2018 at 06:27 AM 0
Share

Hey,

glad it helped. If you want everything to play only once implement another List (`playedSources`) to keep track of everything.

Then ins$$anonymous$$d of increasing the counter, add the zero element from the list to playedSources and afterwards remove it from myAudioSources using .RemoveAt(0)

Then again Play the first Clip from the AudiosourcesList BUT only of one exists. With this version the List may get empty.

avatar image
0

Answer by bakir-omarov · Jun 10, 2018 at 12:08 PM

It is hard to understand what you mean by playing once. Because you can collect 4 triggers at once, play all of them by sequence, after it save them for next playing. And play when you will collect some new triggers also. For example:

  • 1) you collected 3 triggers (audiosources), you begin play 1,2,3. - and stop.

  • 2) after 10 seconds you collected 2 more triggers, so it will play : 1,2,3,4,5 - and stop.


If you want to clear your audisources after playing once, and wait for new triggers, then just uncomment playableAudioSources.Clear(); . And it will like:

  • 1) you collected 3 triggers (audiosources), you begin play 1,2,3. - and stop, and delete them from list.

  • 2) after 10 seconds you collected 2 more triggers, so it will play : 4,5 - and stop, and delete them from list.


This will help you :

 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 public class delete : MonoBehaviour
 {
 
     public List<AudioSource> playableAudioSources; // Use List because it is dynamic
     public bool audioPlaying;
 
     void Awake()
     {
         playableAudioSources = new List<AudioSource>();
     }
 
     void OnTriggerEnter(Collider other)
     {
         // checking if trigger has a audiosource, and if we already added it to our list. If added already then it will skip it. Because OnTriggerEnter can be called many times
         if (other.GetComponent<AudioSource>() && !playableAudioSources.Contains(other.GetComponent<AudioSource>()))
         {
             //add to list:
             playableAudioSources.Add(other.GetComponent<AudioSource>());
 
             if (!audioPlaying)
             {
                 audioPlaying = true;
                 StartCoroutine(PlaySounds());
             } 
         }
     }
 
     private IEnumerator PlaySounds()
     {
         // play all audisources one by one, if you will add some new audiosource while playing, it will be added to the end of list and played also
         for (int i = 0; i < playableAudioSources.Count; i++)
         {
             // check if current is not playing
             if (!playableAudioSources[i].isPlaying)
             {
                 playableAudioSources[i].Play();
                 // wait for the end of current audiosource
                 yield return new WaitForSeconds(playableAudioSources[i].clip.length);
             }
         }
 
         //// if you want to clear your audiosources after playing, just use it.
         //playableAudioSources.Clear(); // uncomment me !
 
         // lets say to the game that we finished playing one cicle of audisources, so if we will hit one more trigger, we can play it again
         audioPlaying = false;
 
     }
 }











Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
0

Answer by Mijn · Jun 11, 2018 at 05:13 PM

thanks bakir-omarov! this solution of yours is very nice! I implemented on my current script,it is for SteamVR / HTC Vive. It is attached to the controller. If I press the grip button while ontrigger, I can grab objects. Each grabbed object has the sound played in order (this part all works). When I press the trigger, I release the children (set parent to null again), audio stops but somehow I need to wait (I think) the coroutine to finish the loop before I can properly use it again. Any idea why?

(for some reason it won't load the code as comment but only as answer..)

 using System.Collections;
     using System.Collections.Generic;
     using UnityEngine;
     
     public class VRControllerInput : MonoBehaviour
     {
     
         protected List<Collectable> heldObjects;
     
         private Valve.VR.EVRButtonId gripButton = Valve.VR.EVRButtonId.k_EButton_Grip;
         private Valve.VR.EVRButtonId triggerButton = Valve.VR.EVRButtonId.k_EButton_SteamVR_Trigger;
         protected SteamVR_TrackedObject trackedObj;
         public SteamVR_Controller.Device device { get { return SteamVR_Controller.Input((int)trackedObj.index); } }
     
     
         public List<AudioSource> playableAudioSources; // Use List because it is dynamic
         public bool audioPlaying;
         public static bool needsToStop;
     
     
         private void Awake()
         {
             trackedObj = GetComponent<SteamVR_TrackedObject>();
             heldObjects = new List<Collectable>();
             playableAudioSources = new List<AudioSource>();
      
         }
     
         private void OnTriggerStay(Collider other)
         {
             Collectable collectable = other.GetComponent<Collectable>();
     
             if (collectable != null)
             {
                 if (device.GetPressDown(gripButton))
                 {
                     collectable.PickUP(this);
                     heldObjects.Add(collectable);
                     needsToStop = false;
     
                     // checking if trigger has a audiosource, and if we already added it to our list. If added already then it will skip it.
                     if (collectable.GetComponent<AudioSource>() && !playableAudioSources.Contains(collectable.GetComponent<AudioSource>()))
                     {
                         //add to list:
                         playableAudioSources.Add(other.GetComponent<AudioSource>());
     
                         if (!audioPlaying)
                         {
                             audioPlaying = true;
     
                             StartCoroutine(PlaySounds());
                             
                         }
                     }
                 }
             }
         }
     
     
         private void Update()
         {
     
             if (heldObjects.Count > 0)
             {
                 if (device.GetPressDown(triggerButton))
                 {
      
                     for (int i = 0; i < heldObjects.Count; i++)
                     {
                         heldObjects[i].Release(this);
                     }
     
                     for (int i = 0; i < playableAudioSources.Count; i++)
                     {
                         playableAudioSources[i].Stop();
                     }
     
                     heldObjects = new List<Collectable>();
                     playableAudioSources = new List<AudioSource>();
                 }
             }
         }
     
         private IEnumerator PlaySounds()
         {
             for (int i = 0; i < playableAudioSources.Count; i++)
             {
                 if (!playableAudioSources[i].isPlaying)
                 {
                     playableAudioSources[i].Play();
                     // wait for the end of current audiosource
                     yield return new WaitForSeconds(playableAudioSources[i].clip.length);
                 }
     
                 //// if you want to clear your audiosources after playing, just use it.
                 //playableAudioSources.Clear(); // uncomment me !
     
                 // lets say to the game that we finished playing one cicle of audisources, so if we will hit one more trigger, we can play it again
                 audioPlaying = false;
             }
         }
     }
 
 





Comment
Add comment · Show 6 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image bakir-omarov · Jun 11, 2018 at 05:36 PM 0
Share

You don't want to stop playing all sequenced sounds after deleting them from child, you want to continue playing current loop(sequence), and then stop and wait for another action(ontriggerenter) ? Or what you want?

avatar image Mijn bakir-omarov · Jun 11, 2018 at 05:49 PM 0
Share

at the moment when I delete the child, the audio stop (I can not hear it), but somehow if I grab an object (make a new child) too quickly, the sound of this object is not played. It seems to me, that I have to wait the coroutine to "stop play the length of the sound before". Sorry if Im not super clear, I do not have yet the proper vocabulary for scripting.. your script as it was works great. I just want to break the coroutine (I guess) if children are detach (so if there are no children, after button press trigger, audio and coroutine for audio play or waiting for new audio should stop).

avatar image bakir-omarov Mijn · Jun 11, 2018 at 06:53 PM 0
Share

but somehow if I grab an object (make a new child) too quickly, the sound of this object is not played.

So you want to play it? if you released all objects , and instantly grabbed one or several of them, you want to play it again?

Show more comments

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

122 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

AudioClip[] bug 1 Answer

Make the audio manager select from an array of sounds 1 Answer

Need help to play a random explosion sound from an array. 1 Answer

Play sound from an array, not random, and only once 3 Answers

Best Way to Sequence AudioClips in an Array 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges