How to delay loading the scene to play the sound?
I'm trying to delay loading a scene so I can play the sound, but the sound stops in the middle or doesn't exist at all and the scene changes immediately
Here is my script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class MeinMenu : MonoBehaviour
{
static AudioSource audioScr;
public void NewGame()
{
SoundManagerScript.PlaySound("clik");
DontDestroyOnLoad(audioScr.gameObject);
SceneManager.LoadScene("level 1");
}
public void LoadGame()
{
SceneManager.LoadScene(PlayerPrefs.GetInt("SavedScene"));
}
}
Happens when the scene loads faster than the sound can finish playing.
When a scene loads by default, it destroys all objects on the previous scene, which includes your audio source.
One way is to mark your audio-source with DontDestroyOnLoad
// Somewhere after your audio source have loaded...
DontDestroyOnLoad(yourAudioSource.gameObject);
Note that this means you are likely to end up with a singular instance of Audio Source, as this audio source (or the game-object attached to it, to be exact) will only be destroyed manually via script.
The other is to just do a coroutine that does nothing until the audio source have finished playing:
IEnumerator LoadSceneWithSoundCoroutine()
{
yourAudioSource.Play();
// Denies loading while audio source is playing.
while (yourAudioSource.isPlaying)
{
yield return null;
}
SceneManager.LoadScene("Your scene")
}
// ...
StartCoroutine(LoadSceneWithSoundCoroutine());
Related
I'm trying to do a simple think: when a button is pressed i load a video using the processing video library, each button is associated with a different video, for example button 1 with video 1, button 2 with video 2, and so on. The code works but every time I call a video, also the same i have already load, rewriting the gloabal variable the consume of CPU grows, reaching the 40% after the thrid loading, after 7 video the consume of CPU is near the 100%. An extraction of the code:
import processing.video.*;
Movie movie;
void setup() {
size(1280, 720, P3D);
background(0);
}
void draw() {
//image(movie, 0, 0, width, height);
if (but1_1==1) {
println("video 1");
movie = new Movie(this, "1.mp4"));
movie.loop();
movie.volume(0);
}
if (but1_2==1) {
println("video 2");
movie = new Movie(this, "2.mp4"));
movie.loop();
movie.volume(0);
}
if (but1_3==1) {
println("video 3");
movie = new Movie(this, "3.mp4"));
movie.loop();
movie.volume(0);
}
}
As you can see, it should not be any reason in based on which the CPU consume grows: the instantiated object movie is always rewritten every time a new video (or the same) is loaded. Any suggestions?
You are loading the movies in loop, which means they don't stop. So the more buttons you press, the more videos are processed at the same time. On every button press, you should stop the movie-playing-process of the old movie first, before you start a new one.
Is there any solution to detect the visibility of an Unity3D game? especially do some specific thing while it's switched to the foreground/background?
MonoBehaviours support two useful hooks:
OnApplicationFocus will be called any time the player gains or loses focus.
OnApplicationPause will be called any time the application is paused or unpaused. Note that it will only be paused if "run in background" is false in player settings, and that most code execution will stop until the app regains focus.
With the above caveats in mind, I usually prefer to use OnApplicationFocus, but both can be useful depending on what exactly you're trying to do.
As far as handling those events, you could make sure that some object in every scene is listening for them. Either attach some sort of singleton object that persists between scenes, or keep an object per scene that handles them appropriately.
Unity's scripting reference provides this example. By attaching this script to an object in some scene, it will throw up a GUI message while the game has lost focus:
public class Example : MonoBehaviour {
public bool paused;
void OnGUI() {
if (paused) {
GUI.Label(new Rect(100, 100, 50, 30), "Game paused");
}
}
void OnApplicationFocus(bool focusStatus) {
paused = focusStatus;
}
}
OnApplicationPause should be what you need.
Example (pulled directly from Unity docs for readability):
using UnityEngine;
using System.Collections;
public class Example : MonoBehaviour {
public bool paused;
void OnGUI() {
if (paused)
GUI.Label(new Rect(100, 100, 50, 30), "Game paused");
}
void OnApplicationPause(bool pauseStatus) {
paused = pauseStatus;
}
}
I use soundeffect to play sound from byte array and all things go alright, but i cant stop playing the sound because no method called stop() in Soundeffect, how i can stop it ?
The code:
private void playFile(byte[] file)
{
try
{
if (file == null || file.Length == 0) return;
SoundEffect se = new SoundEffect(file, microphone.SampleRate, AudioChannels.Mono);
SoundEffect.MasterVolume = 0.7f;
if (stop != 1)
{
FrameworkDispatcher.Update();
se.Play();
}
else
{
//Here should stop, how !
}
}
catch (Exception ee)
{
MessageBox.Show(ee.Message);
}
}
Have you tried calling .Dispose() on your SoundEffect object? According to the documentation,
When a SoundEffect object is destroyed, all SoundEffectInstance
objects previously created by that SoundEffect will stop playing and
become invalid.
Additionally, Microsoft recommends using MediaElement instead, unless you're developing with XNA Game Studio 4.0. So if that applies to you, you may want to consider using MediaElement which does have Play, Pause, and Stop functions.
try using SoundEffectInstance
Sound effect instance
Here's a link to the solution
Sound Effect Instance
More over SoundEffectInstance implements IDisposeable so it will have a dispose() method as well as stop() for the sound effect .
Create a variable for SoundEffectInstance as shown below
SoundEffectInstance soundEffectInstance;
then create an instance of your soundEffect after loading the file..
soundEffectInstance = se.CreateInstance();
after that use this soundEffectInstance to Stop, Play or Pause where ever you want in particular scope.
soundEffectInstance.Play();
Note that SoundEffect is used for fire and forget type instances, if you want to control any particular instance of a SoundEffect you will need to use SoundEffectInstance.
I agree with Benoit Catherinet. If you are trying to stop a particular sound on some event then you must place the stoping code in that event method and for that your SoundEffect instance must be global and not local.
We can better help you if you can explain about what you are trying to achieve.
I have an XNA arcade game which runs over Silverlight environment. The game has a few sound clips which are played in random order as background music.
As stated in http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.media.songcollection.aspx, a developer cannot have full control over Media Player. Particularly, developers cannot create their song collections or add songs to the playback queue. There is a recommendation to play songs one at a time by calling MediaPlayer.Play().
That’s exactly what I'm doing but I experience a performance flaw each time when another song starts playing. The game hangs on for a moment when I call MediaPlayer.Play() despite all sound clips are loaded during game initialization, not in runtime. This happens only on some devices (e.g. HTC Mozart). In contrast, if I disable game sounds and play the same clips in phone’s music player while running the game, there are no performance issues during song changes. I also don’t experience performance problems if we play the clips using SoundEffect class. However, I'm strongly willing to use MediaPlayer for background sound purposes due to 2 reasons:
- SoundEffect doesn’t issue notification when playback is completed
- SoundEffect doesn’t seem to work with .mp3 files, and using .wav files is very expensive
I've also run profiling tests which confirmed that the poor performance time frame starts in a few milliseconds after MediaPlayer.Play() and continues during about 0,4 seconds. During this time my game doesn't execute any heavy-weight operations, just regular game timer's Update() function.
Here is my code snippets:
public void PlayBackgroundMusic(Song song)
{
if ((!(App.Current as App).AppModel.SoundDisabled) && (song != null))
{
if (MediaPlayer.State != MediaState.Stopped)
{
StopBackgroundMusic();
}
MediaPlayer.Play(song);
}
}
public void StopBackgroundMusic()
{
MediaPlayer.Stop();
}
and the handler:
private void OnMediaStateChanged(object sender, EventArgs e)
{
if (MediaPlayer.State != MediaState.Playing)
{
if (!AppModel.SoundDisabled)
{
int index = soundRandomizer.Next(0, sounds.Length - 1);
PlayBackgroundMusic(sounds[index]);
}
}
}
Are there any suggestions?
After all, I found a solution which I'm satisfied with. It eliminates jiggling almost completely. Its idea is to use every MediaPlayer API in a separate thread obtained from thread pool. I'm not aware how it fixes the problem but this really works for me:
public void PlayBackgroundMusic(Song song)
{
if ((!(App.Current as App).AppModel.SoundDisabled) && (song != null))
{
if (MediaPlayer.State != MediaState.Stopped)
{
StopBackgroundMusic();
}
ThreadPool.QueueUserWorkItem((o) =>
{
MediaPlayer.Play(song);
}
}
}
public void StopBackgroundMusic()
{
ThreadPool.QueueUserWorkItem((o) =>
{
MediaPlayer.Stop();
}
}
This is kindof strange, in the code i have one sound effect(i have 24 sound effects in total)if i comment out (23 effects) except loadsound("resources/drink.wav",out drink) and comment out the corresponding "if"'s in "private void button_Click" method, it works fine?? uncomment all sound effects and then 'System.InvalidOperationException'? i have 24 sound effects each no more than 6 sec long. any ideas anyone...is there a limit on the amount of sound files that can be used or maybe i have to clear the stream or something?
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Resources;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Media;
namespace Craggy_Island
{
public partial class MainPage : PhoneApplicationPage
{
// The Resources to play
private SoundEffect drink;//(plus 23 more effects)//there are 23 more here
// Flag that indicates if we need to resume Zune playback upon exiting.
bool resumeMediaPlayerAfterDone = false;
// Constructor
public MainPage()
{
InitializeComponent();
// Timer to simulate the XNA game loop (SoundEffect class is from the XNA Framework)
GameTimer gameTimer = new GameTimer();
gameTimer.UpdateInterval = TimeSpan.FromMilliseconds(33);
// Call FrameworkDispatcher.Update to update the XNA Framework internals.
gameTimer.Update += delegate { try { FrameworkDispatcher.Update(); } catch { } };
// Start the GameTimer running.
gameTimer.Start();
// Prime the pump or we'll get an exception.
FrameworkDispatcher.Update();
// Create and load SoundEffect objects.
LoadSound("Resources/drink.wav", out drink);//there are 23 more here
}
private void LoadSound(String SoundFilePath, out SoundEffect Sound)
{
// For error checking, assume we'll fail to load the file.
Sound = null;
try
{
// Holds informations about a file stream.
StreamResourceInfo SoundFileInfo = App.GetResourceStream(new Uri(SoundFilePath, UriKind.Relative));
// Create the SoundEffect from the Stream
Sound = SoundEffect.FromStream(SoundFileInfo.Stream);
}
catch (NullReferenceException)
{
// Display an error message
MessageBox.Show("Couldn't load sound " + SoundFilePath);
}
}
private void button_Click(object sender, RoutedEventArgs e)
{
Button Current = sender as Button;
try
{
if (Current.Equals(button1))
drink.Play();//(other buttons here for other sound effects)
}
catch (NullReferenceException)
{
MessageBox.Show("Can't play, sound file problem.");
}
}
#region Zune Pause/Resume
private void ZunePause()
{
// Please see the MainPage() constructor above where the GameTimer object is created.
// This enables the use of the XNA framework MediaPlayer class by pumping the XNA FrameworkDispatcher.
// Pause the Zune player if it is already playing music.
if (!MediaPlayer.GameHasControl)
{
MediaPlayer.Pause();
resumeMediaPlayerAfterDone = true;
}
}
private void ZuneResume()
{
// If Zune was playing music, resume playback
if (resumeMediaPlayerAfterDone)
{
MediaPlayer.Resume();
}
}
#endregion Zune Pause/Resume
}
}
If your creating a XNA WP7 application you should be loading your sounds from the ContentManager:
Make sure your sound effect files are set to
Build Acction: Compile
Content Importer: WAV Audio File - XNA Framework
Content Processor Sound Effect - XNA Framework
Load your sound from the ContentManager
Code:
drink = ContentManager.Load<SoundEffect>("Resources/drink.wav");
Try to change the "Compression Quality" property under the "Content Processor" property in "File Properties" of the sound file. In my case the "Best" compression was a problem.