Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
430 views
in Technique[技术] by (71.8m points)

unity3d - Music player in c# unity doesn't work with other scenes

Okay, so I have a toggle button, which controlls the music volume. And it works fine, but when i go to an other scene, and go back - the toggle doesn't work(doesn't change music volume). Here is the code:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class Music : MonoBehaviour
{
    AudioSource audioSource;
    private float volume = 1f;
    Toggle toggle;
    private void Awake()
    {
        SetMusicSingletone();
    }
    private void Start()
    {
        audioSource = GetComponent<AudioSource>();
        toggle = FindObjectOfType<Toggle>();
    }
    private void Update()
    {
        audioSource.volume = this.volume;
    }
    public void ToggleMusic()
    {
        if (!toggle.isOn)
        {
            this.volume = 0f;
        }
        else if (toggle.isOn)
        {
            this.volume = 1f;
        }
    }
    private void SetMusicSingletone()
    {
        var music = FindObjectsOfType<Music>();
        if (music.Length > 1)
        {
            Destroy(gameObject);
        }
        else
        {
            DontDestroyOnLoad(gameObject);
        }
    }
}

The toggle uses method ToggleMusic()


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Alright so the problem is: You have referenced the ToggleMusic method from this instance of Music in your toggle .. then you change scenes and come back .. but due to the singleton thing you destroy the Music instance linked to this new Toggle -> Toggle does nothing now.

You already have a singleton pattern so why not directly make use of it:

public class Music : MonoBehaviour
{
    private static Music _singleton;
    public static Music Singleton => _singleton;

    [SerializeField] private AudioSource audioSource;

    private bool volumeOn;
    public bool MusicIsOn => volumeOn;
    
    private void Awake()
    {
        if (_singleton)
        {
            Destroy(gameObject);
            return;
        }
        
        DontDestroyOnLoad(gameObject);
        _singleton = this;

        if(!audioSource) audioSource = GetComponent<AudioSource>();

        ToggleMusic(true);
    }

    public void ToggleMusic(bool on)
    {
        audioSource.volume = on ? 1f : 0f;
        volumeOn = on;
    }

    public void ToggleMusic()
    {
        ToggleMusic(!volumeOn);        
    }
}

And then on your toggle instead of assigning a callback via the Inspector rather do

public class MusicToggle : MonoBehaviour
{
    [SerializeField] private Toggle toggle;

    private void Awake ()
    {
        if(!toggle) toggle = GetComponent<Toggle>();

        toggle.onValueChanged.AddListener(OnValueChanged);

        toggle.isOn = Music.Singleton.MusicIsOn;
    }

    private void OnValueChanged (bool on)
    {
        Music.Singleton.ToggleMusic(on);
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
...