How to control audio in another scene on/off in unity - unity3d

I am making a game now, it's almost done. now I am trying to control the audio on and off by button or toggle button.
The problem is, I put my audio source gameobject in the splashscreen that is in the 1st scene. and I put the audio or music button in the Setting scene which is inside the 3rd scene. I already make the c# script to control the audio but when I've tried to insert the AudioSource, but it can't since it's from a different scene. I've tried to put the AudioSource in the same scene but the audio didn't start except I go to settings scene first.
Here is the script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Music : MonoBehaviour
{
static Music instance = null;
public AudioSource Backsound;
private void Awake()
{
if (instance != null)
{
Destroy(gameObject);
}
else
{
instance = this;
GameObject.DontDestroyOnLoad(gameObject);
}
}
public void backsoundOnOff()
{
AudioSource bgsound = Backsound.GetComponent<AudioSource>();
if (bgsound.mute = true){
bgsound.mute = false;
}
else {
bgsound.mute = true;
}
}
}

You have already solved half the problem by using GameObject.DontDestroyOnLoad
The object does indeed exist in both scenes. Now you just need to fetch it.
In the first scene where the created the object, Change the tag of the object. Instead of using one of the exiting tags, create a new tag for it called something such as "MenuMusic". Make sure you assign it after creating it, unity does not assign it automatically
Now, in the 3rd scene, in the game object that needs to access it, create a private field "_music"
in your Start function, add
void Start() {
_music = GameObject.FindGameObjectsWithTag("MenuMusic");
}
You will now have the same instance of Music from scene 1

I would highly recommend referencing the sound script that you have into some sort of game manager. Usually how i work is i have one generic script that controls a multitude of options that i usually call the GameManager. This sets player controls, visual options and sound. From here you can simply set bool whether the player wants the music on and off. If this option wants to change you can reference the GameManager at any point in any script.
//Game Manager code
public void SoundControl(bool soundOff)
{
If(soundOff == true)
{
//Sound Off Control
}else
{
//Sound on Control
}
}
//Reference to game Manager
GameManager manager;
public void TurnOffSound()
{
//Turn sound off through manager
manager =
GameObject.FindGameObjectWithTag("Manager").GetComponent<GameManager>
().SoundControl(true);
}
I find this to be the easiest way to control any options through one script that you can reference anywhere.

Related

Why the sound effect does not work in unity

Why the sound effect does not work in unity?
when I try to add a sound effect, it doesn't work
This is my script to move to the next scene using buttons:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class LevelLoader : MonoBehaviour
{
public Animator transition;
public float transitionTime = 1f;
public void LoadNextLevel()
{
StartCoroutine(LoadLevel(SceneManager.GetActiveScene().buildIndex + 1));
}
public AudioClip impact;
IEnumerator LoadLevel(int LevelIndex)
{
transition.SetTrigger("Start");
yield return new WaitForSeconds(transitionTime);
SceneManager.LoadScene(LevelIndex);
AudioSource.PlayClipAtPoint(impact, transform.position);
}
}
You're making the audio play, and then immediately loading in a different scene. The object that is playing the audioclip also unloads.
You could offset the two by making NewGame() a coroutine instead, with a small timed offset between the PlayClipAtPoint() call and the LoadScene() call.
As Alex Leest said, you are loading new scene right after audio play.
When unity scene loading started, all gameobject except DontDestroyOnLoad Object are destroyed.
So, you may add code below to your Audio Manage class.
(Also, you should ensure that your Audio Manager class always has only one instance in your whole program for not cause bugs)
private void Awake()
{
DontDestroyOnLoad(this);
}

Problem with dontDestroyOnLoad in different scene

I am making a game that has two scenes (menu scene and game scene). In the menu scene, I create an empty game object just for my music, which includes (audio source (music), button to mute the music, and my script.
Here's the script:
public class Music : MonoBehaviour
{
public static Music Instance;
public AudioSource mainMusic;
public GameObject musicOffImage;
// Keep The Muic Playing In Diffrent Scene
void Awake()
{
if (!Instance)
Instance = this;
else
Destroy(this.gameObject);
DontDestroyOnLoad(this.gameObject);
}
// Method Mute Button
public void MusicOnOff()
{
if (mainMusic.isPlaying)
{
mainMusic.Pause();
musicOffImage.SetActive(true);
}
else
{
mainMusic.UnPause();
musicOffImage.SetActive(false);
}
}
}
With that script, I can play music in different scenes without reloading the music, and the button is working too, but the problem is when I go to the game scene and I back up to the menu scene, somehow the button didn't work. I think it's about the Destroy game object, but I am not sure how to fix it. Any help would mean a lot to me. Thanks.
I assume that everything the Music scripts needs is a child of it so that it is always fine.
However, after Destroy of the instance from the new scene, your buttons from the new scene loose the reference to the Music instance.
Since you have a Singleton there anyway you could as well (ab)use it and have this attached to your button itself
public MusicButton : MonoBehaviour
{
public void MusicOn()
{
Music.Instance.MusicOnOff();
}
}
And reference that instead in your button.
Also the image could e.g. register itself to the Music.Instance like e.g.
public MusicImage : MonoBehaviour
{
private void Start()
{
Music.Instance.musicOffImage = gameObject;
gameObject.SetActive(Music.Instance.mainMusic.isPlaying);
}
}
Alternative
In your question you said all objects are child's of an empty object, however the only object that gets DontDestroyOnLoad is the Music one. The others will get destroyed and reloaded so all these references might get lost as well. You might probably rather DontDestroyOnLoad the entire empty object and only hide/show the button in certain scenes.

Unity, I have problem with DontDestroyOnLoad to keep tracking in different scence

im new in unity and i have a problem
I am making a game that have 2 scence(Main Menu Scence and Game Scence), i put my music on Main Menu scence. I make a empty game object and i attach audio source there(music) , and i also attach script like this :
First script
public static KeepTheMusicOn Instance;
void Awake()
{
if (!Instance)
Instance = this;
else
Destroy(this.gameObject);
DontDestroyOnLoad(this.gameObject);
}
With that script i can keep music play in second scence wihtout restart the music, and in the main menu scence i have settings that have button to mute the music , the button will run my second script .
Second Script:
public AudioSource mainMusic;
public void Update()
{
DontDestroyOnLoad(mainMusic);
}
public void MusicOnOff()
{
if (mainMusic.isPlaying)
{
mainMusic.Pause();
}
else
{
mainMusic.UnPause();
}
}
My problem is when i start the game so im in my main menu scence i can mute the music with the button, but when i go to game scence and i back to menu, the button dont do anything.
So that is my problem, i hope anyone can help me. Sorry for my bad english.
Sounds like when switching scenes you destroy the button. When you them go back to the main menu you destroy the duplicate instance of your audio controller thing => references configured in the Button are lost.
In your case since you use a public Singleton anyway you could as well (ab)use it and put a component on the Button itself instead (thus the reference can not get lost) and do something like e.g.
[RequireComponent(typeof(Button))]
public class MusicButton : MonoBehaviour
{
[SerializeField] private Button button;
private void Awake()
{
if(!button) button = GetComponemt<Button>();
// dynamically add the callback
// it won't appear in the editor but get called in onClick
button.onClick.AddListener(OnClicked);
}
private void OnClicked()
{
KeepTheMusicOn.Instance.MusicOnOff();
}
}
If you prefer seeing it in the editor you can ofcourse as well rove it from Awake, make the OnClicked public and reference it in the button's onClick event manually.

Use bluetooth game controller to play/stop video in unity vr

I have created a vr app in unity using google vr sdk. Currently i could click on the screen to start the video. When i use the vr headset, i need to use the bluetooth controller to play/stop the video. Can someone help me do this?
You need to identify how unity map your controller buttons, once you identify what button do you want to press and how unity mapped in his Input Manager (Edit->Project Settings->Input) you just need to call you function from the Update like this:
void Update()
{
if(Input.GetButtonUp("Fire1"))
{
playVideoFuncion();
}
}
Where playVideoFunction() is your own fuction.
In this example I used "Fire1" but maybe in your case is different.
For example for the Xbox Controller you have this configuration explained in Xbox 360 Controller Input on Unity
If you can't find anything related on your controller you can do something like:
void Update()
{
if(Input.GetButtonUp("Fire1"))
{
Debug.Log("Fire 1 Pressed");
}
if(Input.GetButtonUp("Fire2"))
{
Debug.Log("Fire 1 Pressed");
}
if(Input.GetButtonUp("0"))
{
Debug.Log("Button 0 pressed");
}
// Add more buttons and logs
}
There are maybe other ways to identify the input from random controllers but I don't know how. I needed the mapping for the Xbox controller and that page was useful.
You can create a script and attach to the video player so that when a user clicks on the player the commands are run. I assume you already have the unity package for Google VR(GVR). Add the following sample script and modify to suit your need.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class VideoPlayer : MonoBehaviour {
private bool _isPlaying;
// Use this for initialization
void Start () {
_isPlaying = false
}
// Update is called once per frame
void Update () {
if (GvrController.ClickButtonUp && _isPlaying) {
PlayVideo();
}
else if (GvrController.ClickButtonUp && !_isPlaying){
StopVideo ();
}
}
public void PlayVideo{
//Logic to Play Video
}
public void StopVideo{
//Logic to Stop Video
}
}

Issue with playing background audio for different scenes in unity3d

In my game, I have two scene.
What I want to achieve is if user navigates from one scene to another, background audio specific to each should be played from start(audio length=0)
But all my efforts are in vain.
I tried using 'Pause' Method of audioSound
I tried
create a new game object and assign this scene background score to it and play
destroy gameObject created for another scene if there was any
But it doesn't give the result that I want.
I searched for finding how to play audioClip from start and stop other audioClip playing but didn't find any.
I know I'm not supposed to ask for code on stack overflow but if anyone has achieved this or has some pseudo code request you to provide it
I'm not sure I understand your question properly, since it seems the simplest scenario for background music.
If you really want a change of audioclip in every scene, let's say Scene A must play Clip A and Scene B must play Clip B, and both clips should be played as soon as a scene is loaded, you just need to create a game object in both scenes with an Audio Source component, with the Play On Awake flag active, and then just assign the appropriate clip for the scene (i.e.: assign Clip A in the Audio Clip field of the Audio Source component of Scene A game object, and do the same with Clip B for Scene B).
That's pretty much it.
If you looking at the detail code then you can try this code.
First : Make a script "SoundFxScript.cs" // You can modified as you want
Insert this code :
public class SoundFxScript : MonoBehaviour {
//Background Music
public AudioSource Scene1_Sound;
public AudioSource Scene2_Sound;
// Use this for initialization
void Start () {
PlayBackgroundMusic ();
}
// Update is called once per frame
void Update () {
}
public void PlayBackgroundMusic() {
if (UnityEngine.SceneManagement.SceneManager.GetActiveScene ().name == "Scene1") {
Scene1_SoundPlay();
} else if (UnityEngine.SceneManagement.SceneManager.GetActiveScene ().name == "Scene2") {
Scene2_SoundPlay();
}
}
public void Scene1_SoundPlay() {
Scene1_Sound.Play ();
Scene2_Sound.Stop ();
}
public void Scene2_SoundPlay() {
Scene1_Sound.Stop ();
Scene2_Sound.Play ();
}
// Step Fifth
public void LoadTheScene (string Scenename) {
UnityEngine.SceneManagement.SceneManager.LoadScene (Scenename);
sf.PlayBackgroundMusic ();
}
}
Second : Make Gameobject name = "SoundMusic" at the first scene and add component script SoundFxScript.cs. In gameobject "SoundMusic" you can add you background music for scene1 and scene2.
Third : Make a singleton file Singleton.cs
Insert this code :
public class Singleton : MonoBehaviour {
static Singleton instance = null;
void Start ()
{
if (instance != null)
{
Destroy(gameObject);
return;
}
DontDestroyOnLoad(gameObject);
instance = this;
}
}
Fourth : at gameobject "SoundMusic" add component script "Singleton.cs"
Fifth : How To Call In Another Scene (Load Scene). This method is inside SoundFxScript.cs
Example You have a method to call a load scene. Try this method :
Call it with : LoadTheScene("Scene2") // Call scene2
In here you can call your SoundFxscript.cs Component from any script you have.
Example :
SoundFxScript sf;
sf = GameObject.Find ("SoundMusic").GetComponent<SoundFxScript> ();
And you can use method LoadTheScene to load a new scene and the background music will RePlay again according to the what Scene is it.
That's All.