Понедельник, 23 Декабря 2024, 20:03

Приветствую Вас Гость

[ Новые сообщения · Игроделы · Правила · Поиск ]
  • Страница 1 из 1
  • 1
Вкл\выкл музыка
BorsheCДата: Понедельник, 07 Мая 2018, 17:52 | Сообщение # 1
был не раз
Сейчас нет на сайте
Доброго дня. Помогите разобраться:

На главной сцене имеется кнопка вкл\выкл фоновой музыки, при нажатии на которую я меняю спрайт и соответственно останавливаю музыку:
Код
case "music":
    if (main_theme.isPlaying == true) {
     PlayerPrefs.SetInt ("main_theme_play", 1);
     Music.GetComponent<Image> ().sprite = Music_on_off [0];
     main_theme.Pause ();
    } else {
     PlayerPrefs.SetInt ("main_theme_play", 0);
     Music.GetComponent<Image> ().sprite = Music_on_off [1];
     main_theme.Play ();
    }
   
                break;


Так же имеется блокировка создания второго экземпляра объекта main_theme (музыка) по тегу main_audio:

Код
void Start(){
  //Блокировка дублирования музыки
  if (GameObject.FindGameObjectsWithTag ("main_audio").Length == 1) {
    DontDestroyOnLoad (main_theme);
  } else {
   Destroy (main_theme);
  }
}


В чем собственно проблема: при клике по кнопке все прекрасно работает (музыка выключается и включается), но если перейти на другую сцену а потом обратно на главную то main_theme возвращает null и при клике на кнопку возникает ошибка:

MissingReferenceException: The object of type 'AudioSource' has been destroyed but you are still trying to access it.
Your script should either check if it is null or you should not destroy the object.

Целый день бьюсь, не могу понять как решить. помогите пожалуйста. Сильно камнями не кидайтесь, я новичок) Заранее благодарю.
DivESДата: Понедельник, 07 Мая 2018, 18:38 | Сообщение # 2
заслуженный участник
Сейчас нет на сайте
Цитата BorsheC ()
Destroy (main_theme);

BorsheC, так ты же уничтожаешь main_theme на данном участке? А потом пытаешься её воспроизвести. Вот он и ругается)
В методе Start ошибка закралась ^_^
BorsheCДата: Понедельник, 07 Мая 2018, 18:49 | Сообщение # 3
был не раз
Сейчас нет на сайте
Цитата DivES ()
Цитата BorsheC ()
Destroy (main_theme);

BorsheC, так ты же уничтожаешь main_theme на данном участке? А потом пытаешься её воспроизвести. Вот он и ругается)
В методе Start ошибка закралась


Ранее у меня было, что при переходе с другой сцены на главную дублировалась музыка( то есть 2 трека играть начало) и именно этим дестроем у меня дублирование исчезло. А как сейчас прописать чтобы только один экземпляр оставался не могу сообразить(
DivESДата: Понедельник, 07 Мая 2018, 18:57 | Сообщение # 4
заслуженный участник
Сейчас нет на сайте
Цитата BorsheC ()
но если перейти на другую сцену

А при переходе музыка продолжает работать? И включение/выключение?
Т.е., ошибка появляется только при переходе опять на главную сцену?

Цитата BorsheC ()
и именно этим дестроем у меня дублирование исчезло

Дублирование или вообще вся музыка? :D
BorsheCДата: Понедельник, 07 Мая 2018, 19:03 | Сообщение # 5
был не раз
Сейчас нет на сайте
При переходе на другую сцену музыка продолжает работать, ибо main_theme DontDestroyOnLoad. А включение/выключение работает до перехода на другую сцену, а по возврату на главную и клику по кнопке вылезает ошибка .

Цитата DivES ()
Цитата BorsheC ()
Дублирование или вообще вся музыка?


Только дублирование, то есть играет 1 трек


Сообщение отредактировал BorsheC - Понедельник, 07 Мая 2018, 19:03
DivESДата: Понедельник, 07 Мая 2018, 19:14 | Сообщение # 6
заслуженный участник
Сейчас нет на сайте
А если добавить дополнительную проверку main_theme != null? (точно не знаю, как конъюнкция в C# обозначается, поэтому &&)
Код
case "music":
    if (main_theme.isPlaying == true && main_theme != null)
BorsheCДата: Понедельник, 07 Мая 2018, 19:22 | Сообщение # 7
был не раз
Сейчас нет на сайте
Я уже прописывал так. Сейчас ради интереса прописал сново
Код
((main_theme.isPlaying == true) && (main_theme != null))
и все равно таже ошибка(((
DivESДата: Понедельник, 07 Мая 2018, 19:25 | Сообщение # 8
заслуженный участник
Сейчас нет на сайте
BorsheC, а вот ты писал, что main_theme при возвращении на главную сцену принимает значение null. Но как тогда трек продолжает играть?
BorsheCДата: Понедельник, 07 Мая 2018, 21:28 | Сообщение # 9
был не раз
Сейчас нет на сайте
Это чудо :D Он же не дестроится. При возвращении на главную сцену в дереве объектов DontDestroyOnLoad main_theme 1 экземпляр , но debug показывает что там null .

Добавлено (07 Мая 2018, 21:28)
---------------------------------------------
Есть еще идеи? ну или как вы реализовываете данную функцию? () тока без синглтона... я их пока не понимаю

DivESДата: Понедельник, 07 Мая 2018, 21:56 | Сообщение # 10
заслуженный участник
Сейчас нет на сайте
BorsheC, а что если обойтись без уничтожения? Просто сделать так, чтобы в любой момент времени в main_theme был один объект музыки. Покажи код того, как создаётся экземпляр main_theme!
pixeyeДата: Понедельник, 07 Мая 2018, 23:21 | Сообщение # 11
Red Winter Software
Сейчас нет на сайте
Цитата BorsheC ()

Есть еще идеи? ну или как вы реализовываете данную функцию? () тока без синглтона... я их пока не понимаю


Придется понимать. То что ты сейчас делаешь грабли постаршнее любого синглтона. Реально. понять синглтон меньше дня, а ты день бьешься над граблями.
Если хочешь максимально просто, лениво и не удобно то делай пустую сцену. В ней делай все свои don't destroy on load - из этой сцены уже переходи в свое меню или игру. Тоесть эта такая загрузочная сцена которая появится один раз за игру.

Дело в том что при загрузке сцены в ней уже есть префабы. Когда там есть код don't destroy on load он сохраняет твой объект, но при перезагрузке сцены это уже будет не тот же самый префаб - там будет точно такая же копия и по этой логике он и ее будет не дестроить и вот у тебя уже две копии. Пустая сцена вначале игры избавит тебя от такой проблемы но это неудобно конечно.


ACTORS - мой фреймворк на Unity
Until We Die - игра над которой работаю

BorsheCДата: Вторник, 08 Мая 2018, 12:49 | Сообщение # 12
был не раз
Сейчас нет на сайте
Цитата DivES ()
Покажи код того, как создаётся экземпляр main_theme!


Да просто на сцене в дереве объектов висит, создается при создании сцены.

Цитата pixeye ()
Если хочешь максимально просто, лениво и не удобно то делай пустую сцену. В ней делай все свои don't destroy on load - из этой сцены уже переходи в свое меню или игру. Тоесть эта такая загрузочная сцена которая появится один раз за игру.


Это конечно мысль, и я уже думал об этом, но хотелось бы просто уничтожить копию и оставить только первый объект который был изначально, а как реализовать не могу сообразить(
DivESДата: Вторник, 08 Мая 2018, 12:58 | Сообщение # 13
заслуженный участник
Сейчас нет на сайте
BorsheC, то есть автоматически создаётся экземпляр? А можно сделать создание экземпляра кодом?
То есть при каждой загрузке новой сцены мы проверяем, есть ли что-то в музыке. Если есть - очищаем и закидываем туда нужный трэк, воспроизводим.
Если нет - просто закидываем трэк и воспроизводим.


Сообщение отредактировал DivES - Вторник, 08 Мая 2018, 13:03
pixeyeДата: Вторник, 08 Мая 2018, 13:09 | Сообщение # 14
Red Winter Software
Сейчас нет на сайте
Цитата BorsheC ()
Это конечно мысль, и я уже думал об этом, но хотелось бы просто уничтожить копию и оставить только первый объект который был изначально, а как реализовать не могу сообразить(


Потому что тут нечего соображать. Это так же странно как соображать как кататься на велосипеде с квадратными колесами : )

Показываю образ мышления.
1) Cделал костыль, Как мне сделать дополнительный костыль чтобы работать с костылем?
2) Есть задача. В игре должна играть фоновая музыка и не прерываться при переходе от сцены к сцене. Как это сделать оптимально и чему мне предстоит научиться если я пока не знаю как?

Опять же - по простому-костыльно.
Допустим у тебя НЕТ на первой сцене префаба с музыкой. Делаем так :

Код
// статик gameobject с музыкой
public static GameObject myMusicGO;

// метод который пихаем в авейк или старт. Он сделает нам музыку если ее нет
void MakeBackgroundMusic(){
// проверяем существует ли статичный геймобджект с музыкой. Если существует то выходим из метода
   if (myMusicGO!=null) return;
     
// проверка неудачна, музыки нет. Делаем из префаба или откуда захочешь и назначаем в статичный myMusicGO
myMusicGO = Instantiate(prefab);
// делаем чтобы он не удалялся
DontDestroyOnLoad(myMusicGO);

}


Ну и если есть желание с чего то начинать а не писать так то вот тебе в помощь


ACTORS - мой фреймворк на Unity
Until We Die - игра над которой работаю



Сообщение отредактировал pixeye - Вторник, 08 Мая 2018, 13:18
BorsheCДата: Вторник, 08 Мая 2018, 15:04 | Сообщение # 15
был не раз
Сейчас нет на сайте
Цитата pixeye ()
pixeye
То что вы написали и есть же синглтон?! вроде ясно и понятно, попробую сделать так. Спасибо. Так же Спасибо DivES. Вопрос закрыт.
pixeyeДата: Вторник, 08 Мая 2018, 15:12 | Сообщение # 16
Red Winter Software
Сейчас нет на сайте
Цитата BorsheC ()
То что вы написали и есть же синглтон?! вроде ясно и понятно, попробую сделать так. Спасибо. Так же Спасибо DivES. Вопрос закрыт.


Нет :) Не синглтон. Просто статичная переменная.

Синглтон это шаблон гарантирующий что не будет существовать более одного экземпляра класса.
Типичный синглтон на юнити с ленивой инициализацией и работой только с Monobehavior.

Код
  public class Singleton<T> : MonoBehaviour  where T: MonoBehaviour
    {

        public static bool isApplicationQuitting;
        private static T _instance;
        private static System.Object _lock = new System.Object();
        
        public static T Instance
        {
            get
            {

                if (isApplicationQuitting)
                    return null;
                
                lock (_lock)
                {
                    if (_instance == null)
                    {
                        _instance = FindObjectOfType<T>();

                        if (_instance == null)
                        {
                            var singleton = new GameObject("[SINGLETON] " + typeof(T));
                            _instance = singleton.AddComponent<T>();
                            DontDestroyOnLoad(singleton);
                        }

                    }

                    return _instance;
                }
            }
        }

        public virtual void OnDestroy()
        {
            isApplicationQuitting = true;
        }
        
        
    }


Теперь можно создавать налево и направо синглтоны пиша что-то вроде

Код
public class AudioManager : Singleton<AudioManager>  {

}


И если ты обратишься к AudioManager через AudioManager.Instance - то он проверит на сцене Аудиоменеджер и если не найдет такого создаст тебе и вернет его


ACTORS - мой фреймворк на Unity
Until We Die - игра над которой работаю



Сообщение отредактировал pixeye - Вторник, 08 Мая 2018, 15:16
BorsheCДата: Вторник, 08 Мая 2018, 15:53 | Сообщение # 17
был не раз
Сейчас нет на сайте
pixeye, вообщем смотри как сделал:

Код

public GameObject main_theme;

void BackgroundMusic()
    {
        // проверяем существует ли статичный геймобджект с музыкой. Если существует то выходим из метода
        if (main_theme != null) return;
        // проверка неудачна, музыки нет. Делаем из префаба или откуда захочешь и назначаем в статичный main_theme
        main_theme = Instantiate(main_theme);
        main_theme.AddComponent<AudioSource>();
        // делаем чтобы он не удалялся
        DontDestroyOnLoad(main_theme);
    }

    void Start(){
        BackgroundMusic();
   //Звук и музыка
   if (PlayerPrefs.GetInt ("main_theme_play") == 0) {
    Music.GetComponent<Image> ().sprite = Music_on_off [1];
    main_theme.GetComponent<AudioSource>().Play();
   } else {
    Music.GetComponent<Image> ().sprite = Music_on_off [0];
                main_theme.GetComponent<AudioSource>().Pause ();
   }


а это уже кнопка
Код
case "music":
    if ((main_theme.isPlaying == true) && (main_theme != null)){
     PlayerPrefs.SetInt ("main_theme_play", 1);
     Music.GetComponent<Image> ().sprite = Music_on_off [0];
     main_theme.Pause ();
    } else {
     PlayerPrefs.SetInt ("main_theme_play", 0);
     Music.GetComponent<Image> ().sprite = Music_on_off [1];
     main_theme.Play ();
    }
   
                break;


Музыка работает, вкл\выкл по кнопке происходит, НО при переходе на новую сцену музыка вырубается. Чего я не так сделал?

Добавлено (08 Мая 2018, 15:46)
---------------------------------------------
заменил public GameObject main_theme на public static GameObject main_theme;

и теперь ошибка
argumentexception the object you want to instantiate is null

Добавлено (08 Мая 2018, 15:53)
---------------------------------------------
все разобрался. сохранил префаб

Код
void BackgroundMusic()
    {
        // проверяем существует ли статичный геймобджект с музыкой. Если существует то выходим из метода
        if (main_theme != null) return;
        // проверка неудачна, музыки нет. Делаем из префаба или откуда захочешь и назначаем в статичный main_theme
        main_theme = Instantiate(main_theme);
        // делаем чтобы он не удалялся
        DontDestroyOnLoad(main_theme);
    }


но теперь сцены другие не запускаются)))
pixeyeДата: Вторник, 08 Мая 2018, 15:56 | Сообщение # 18
Red Winter Software
Сейчас нет на сайте
Цитата BorsheC ()
но теперь сцены другие не запускаются)))


что пишет


ACTORS - мой фреймворк на Unity
Until We Die - игра над которой работаю

BorsheCДата: Вторник, 08 Мая 2018, 16:26 | Сообщение # 19
был не раз
Сейчас нет на сайте
А нет.... пардон.... при старте главной сцены в консоле ошибка argumentexception the object you want to instantiate is null

Добавлено (08 Мая 2018, 16:02)
---------------------------------------------

Код
main_theme = Instantiate(main_theme);


видать как-то не правильно создаю объект. То есть есть переменная main_theme и префаб с таким же именем сохранил.

Добавлено (08 Мая 2018, 16:17)
---------------------------------------------
Победил. создал папку Resourcec и запихал туда префаб и загрузил его

Код
main_theme = Instantiate(Resources.Load("main_theme")) as GameObject;


Спасибо огромное!!!!!!! Очень помогли!!!!!

Добавлено (08 Мая 2018, 16:26)
---------------------------------------------
Ах и да клик по кнопке забыл указать как сделал) для потомков)

Код
case "music":
                main_theme = GameObject.Find("main_theme(Clone)");
                
    if (main_theme.GetComponent<AudioSource>().isPlaying == true){
     PlayerPrefs.SetInt ("main_theme_play", 1);
     Music.GetComponent<Image> ().sprite = Music_on_off [0];
                    main_theme.GetComponent<AudioSource>().Pause ();
    } else {
     PlayerPrefs.SetInt ("main_theme_play", 0);
     Music.GetComponent<Image> ().sprite = Music_on_off [1];
                    main_theme.GetComponent<AudioSource>().Play ();
    }
  • Страница 1 из 1
  • 1
Поиск:

Все права сохранены. GcUp.ru © 2008-2024 Рейтинг