Audioclip.Play() plays audio in all cases except one
The Situation - I have two scripts, one calls the other:
Script 1 - The calling script - named *tutorial_start.c*s - Initializes the game on Awake by turning off some game objects (these get turned back on later as the player proceeds), Play audio clip 1, when that has finished call a method in Script 2, play audio clip 2.
Script 2 - The called script - named HitTheHouseLIghts.cs - Has two functions, one turns off lights and plays a sound effect, the other turns on lights and plays another sound effect.
The Problem - When called by the first script, this method turns off the lights but fails to play the audio. In other cases it plays the audio as expected.
I call the function HitTheHouseLights.KillLights which should:
Load an audio clip.
Play it (it's a big light switch sound effect).
Deactivate (SetActive(false) a group of point lights that are all children of an empty game object so that they just go out and make the player's environment dark.
Playing the sound effect works fine in all cases except for when this method is called by the first script. For example, I have objects in the room that act as light switches with this script on them. When the player "clicks" on the object, this script is called, the sound effect is played and the lights go out.
It also works great in the opposite case. The player clicks a switch and the other method is called so the other sound effect is played and the lights go on.
This works in all cases, while the initial audio is playing, after it is complete, etc., except when the first script calls this method in the second. I have debug statements in the method and they fire just fine, and show me everything correctly, but when the first script calls the second I just don't hear the sound play over the speakers. In all other cases the sound does play.
The Code What I believe to be the relevant code in Script 1 (tutorial_start.cs) is in the Update function - hitlights.KillLights(); - Line 46.
Script 1 - tutorial_start.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class tutorial_start : MonoBehaviour {
// Assign these in the Inspector
public GameObject loc_mkr1;
public GameObject Hangar_Regular_Nav_Props;
AudioSource asource;
public AudioClip aclip1;
public AudioClip aclip2;
public HitTheHouseLights hitlights;
public Light light_up;
public GameObject[] tut_markers;
//Private variables
private bool clip1played;
private bool dim_lights;
private void Awake()
{
loc_mkr1.SetActive(false);
Hangar_Regular_Nav_Props.SetActive(false);
foreach(GameObject g in tut_markers)
{
g.SetActive(false);
}
}
// Use this for initialization
void Start () {
asource = GetComponent<AudioSource>();
asource.clip = aclip1;
asource.Play();
}
// Update is called once per frame
void Update () {
if (!asource.isPlaying && !clip1played)
{
hitlights.KillLights();
asource.clip = aclip2;
asource.Play();
loc_mkr1.SetActive(true);
clip1played = true;
dim_lights = true;
}
if (dim_lights)
{
Change_light_up();
}
}
void Change_light_up()
{
light_up.intensity = Mathf.Lerp(light_up.intensity, 50f, Time.deltaTime);
if (light_up.intensity > 49)
{
dim_lights = false;
}
}
}
Script 2 - HitTheHouseLights.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HitTheHouseLights : MonoBehaviour {
public AudioSource sound;
public AudioClip lightskill_audio;
public AudioClip lightsup_audio;
public GameObject set_of_house_lights;
public void Start()
{
sound = GetComponent<AudioSource>();
}
public void KillLights() {
sound.clip = lightskill_audio;
Debug.Log("Kill Lights Before the audio sound clip - Sound.clip = " + sound.clip);
sound.Play();
Debug.Log("Kill Lights After the audio sound clip.");
set_of_house_lights.SetActive(false);
}
public void LightsUp()
{
set_of_house_lights.SetActive(true);
sound.clip = lightsup_audio;
sound.Play();
}
}
Why wouldn't the sound effect play when called by the first script?
Answer by JeffreyBennett · Oct 21, 2017 at 09:29 PM
Answered my own question. Here's what happened: I had previously created an empty game object in the hierarchy, and thrown all of the lights onto it as children (the lights that I wanted to turn off/on with the script HitTheLights.cs.) I had also added the script onto that empty object. That worked fine, but when I watched the effect in preview I decided that it needed the sound effect too.
Once I got my sound effect (the big switch sound) I just added that into the script, as you can see above. However, the script turns the lights on/off via the command SetActive(true or false). The audio clip is over a second long, with about a 0.2 second period of silence at the beginning. Once the script kills the empty game object that acts as a parent to the set of lights, it basically kills itself as well, so it either never gets to execute the next line of code (which is to play the audio), or it kills the play of the audio before it is able to finish playing.
Either way, the lights go on and off instantaneously and appear to work normally in the game, but the audio file that needs to play at the same time is terminated prematurely because the parent object got zapped.
To fix this I decided a class (a script) should only be doing one thing anyway (toggle the lights, but not toggle the lights and also playing audio), so I created a new script just for the audio and a new empty game object to put it on. I named it HitTheLightsAudio() and it looks just like its sister script, HitTheLights(), but it separates off the sound.clip and sound.Play lines to itself, and leaves the SetActive for the lights alone. That way, the lights go off, but the sound can still play.
Your answer
Follow this Question
Related Questions
Audio is cut in script 0 Answers
audio is not playing during IEnumerator 1 Answer
audio.play does not work 1 Answer
Need help: new sound isnt played correctly anymore 2 Answers