質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.41%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

1回答

779閲覧

シーンが変わっても、BGMの調整をしていきたい。

mimo2525

総合スコア1

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

0クリップ

投稿2023/11/22 15:12

プログラミング初心者です。
現在、タイトル画面からオプション画面にシーンごと移動して、音量の調整を行えるようにしたいです。
オプション画面のみであれば、音量の調整はできますが、シーンを移動するとできなくなってしまいます。
破壊された audioSourceBGMを読む込み、読み取れていないのかなと思います。破壊される前の一番最初のオブジェクトを読めるようにしたいです。(推察です。)
下にコードを乗せています。

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

public class Titol : MonoBehaviour
{
private AudioSource audioSourceSE;
private AudioSource audioSourceBGM;
public AudioClip se;
public AudioClip bgm;

public Slider seSlider; public Slider bgmSlider; public static Titol Instance; private void Awake() { audioSourceSE = gameObject.AddComponent<AudioSource>(); audioSourceBGM = gameObject.AddComponent<AudioSource>(); audioSourceBGM.loop = true; audioSourceBGM.clip = bgm; audioSourceBGM.Play(); // 初回のみInstanceをセット if (Instance == null) { Instance = this; DontDestroyOnLoad(gameObject); } else { Destroy(audioSourceBGM); // 既存のBGMを停止 Instance = this; // 新しいオブジェクトをInstanceにセット DontDestroyOnLoad(gameObject); } // シーンがロードされたときに呼び出されるデリゲートを追加 SceneManager.sceneLoaded += OnSceneLoaded; // スライダーの初期値を設定 seSlider.value = audioSourceSE.volume; bgmSlider.value = audioSourceBGM.volume; } public void SettingPlaySE() { audioSourceSE.PlayOneShot(se); } public void StartBottan() { SceneManager.LoadScene("GameSelect"); SettingPlaySE(); } public void SetumeiBottan() { SceneManager.LoadScene("setumei"); SettingPlaySE(); } public void GmeiBottan() { SceneManager.LoadScene("gyarari-"); SettingPlaySE(); } public void OmeiBottan() { SceneManager.LoadScene("opputyon"); SettingPlaySE(); } public void AmeitBottan() { SceneManager.LoadScene("titl"); SettingPlaySE(); } // 修正: OnLevelWasLoadedを非推奨から変更 private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { // シーンが切り替わるたびにBGMを再生 if (Instance != null) { Instance.PlayBGM(); } } // 修正: PlayBGMを非staticメソッドに変更 public void PlayBGM() { if (!audioSourceBGM.isPlaying) { audioSourceBGM.Play(); } } public void OnSEVolumeChanged(float volume) { audioSourceSE.volume = volume; } // BGMの音量をスライダーから変更 public void OnBGMVolumeChanged(float volume) { audioSourceBGM.volume = volume; }

}

シーン移動して、スライダーをいじると。
エラーはこのように出ます。
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.

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

C#

1 Destroy(audioSourceBGM); // 既存のBGMを停止

これ、既存のBGMではなく、新しく生成したBGMを破棄しています。
以下のようにするとどうでしょうか?

C#

1 Destroy(Instance.audioSourceBGM); // 既存のBGMを停止

追記:
BGMManagerにスライダーをアサインするのではなく、スライダーのスクリプトを作ってそちらからBGMManagerを参照するほうがいいと思います。
また、「BGMのあるオブジェクト」を破棄したくない(コメント参照)ので、新しいほうが破棄する形にしています。
使用する際は、BGMSliderをスライダーのゲームオブジェクトにアタッチしてください。
また、スライダーに登録する関数をBGMManager.SetBGMVolume()からBGMSlider.SetBGMVolume()に変更してください。
(スライダーに直接、BGMManager.SetBGMVolume()を登録しないでください)
動作未確認なので、エラーや不具合は適宜修正してください。

C#

1using UnityEngine; 2using UnityEngine.UI; 3 4public class BGMManager : MonoBehaviour 5{ 6 private AudioSource audioSourceBGM; 7 public AudioClip bgm; 8 9 public static BGMManager Instance; 10 11 private void Awake() 12 { 13 if (Instance == null) 14 { 15 Instance = this; 16 DontDestroyOnLoad(gameObject); 17 18 audioSourceBGM = gameObject.AddComponent<AudioSource>(); 19 audioSourceBGM.loop = true; 20 audioSourceBGM.clip = bgm; 21 audioSourceBGM.Play(); 22 } 23 else 24 { 25 // すでに存在する場合は即座に破棄する 26 Destroy(gameObject); 27 } 28 } 29 30 public void PlayBGM() 31 { 32 if (!audioSourceBGM.isPlaying) 33 { 34 audioSourceBGM.Play(); 35 } 36 } 37 38 // BGMSliderから呼び出す用 39 // ※こちらはスライダーに直接登録しない。代わりにBGMSliderのSetBGMVolume()を登録する 40 public void SetBGMVolume(float volume) 41 { 42 audioSourceBGM.volume = volume; 43 } 44 45 // BGMSliderから呼び出す用 46 public float GetBGMVolume() 47 { 48 return audioSourceBGM.volume; 49 } 50}

C#

1using UnityEngine; 2using UnityEngine.UI; 3 4public class BGMSlider : MonoBehaviour 5{ 6 private void Start() 7 { 8 GetComponent<Slider>().value = BGMManager.Instance.GetBGMVolume(); 9 } 10 11 // こちらをスライダーに登録 12 public void SetBGMVolume(float volume) 13 { 14 BGMManager.Instance.SetBGMVolume(volume); 15 } 16}

イメージ説明

投稿2023/11/23 04:57

編集2023/11/26 02:31
fiveHundred

総合スコア9993

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mimo2525

2023/11/23 10:12

返答ありがとうございます。 どうやら自分が間違えていたようで。申し訳ないです。 何度かスクリプトやオブジェクトと、既存のBGMを読み込んでいたんですけど。 シーン移動すると、audioSourceBGMのアサインが取れてしまっていることが問題のようです。
fiveHundred

2023/11/23 10:34

すみませんが、状況がよく分かりません。 audioSourceBGMを破棄してしまっているが原因ではないのですか?
mimo2525

2023/11/23 10:45

audioSourceBGMを破棄されたことではないと思われます。
mimo2525

2023/11/23 10:49

現在は、BGMスクリプトのみ独立させて、スクリプトを検討しているのですが。 using UnityEngine; using UnityEngine.UI; public class BGMManager : MonoBehaviour { private AudioSource audioSourceBGM; public AudioClip bgm; public static BGMManager Instance; // UI上のスライダー public Slider bgmVolumeSlider; private void Awake() { if (Instance == null) { Instance = this; DontDestroyOnLoad(gameObject); audioSourceBGM = gameObject.AddComponent<AudioSource>(); audioSourceBGM.loop = true; audioSourceBGM.clip = bgm; audioSourceBGM.Play(); // スライダーのアサインが外れている場合、手動でアサイン if (bgmVolumeSlider == null) { // シーン内で対象のスライダーを見つけてアサイン bgmVolumeSlider = GameObject.Find("YourSliderObjectName").GetComponent<Slider>(); } // スライダーが見つかった場合、初期値を設定 if (bgmVolumeSlider != null) { bgmVolumeSlider.value = audioSourceBGM.volume; } } else { // もし新しいオブジェクトにスライダーがない場合、再度アサイン if (bgmVolumeSlider == null) { bgmVolumeSlider = GameObject.Find("YourSliderObjectName").GetComponent<Slider>(); } // スライダーが見つかった場合、初期値を設定 if (bgmVolumeSlider != null) { bgmVolumeSlider.value = audioSourceBGM.volume; } Destroy(gameObject); } } public void PlayBGM() { if (!audioSourceBGM.isPlaying) { audioSourceBGM.Play(); } } // スライダーの値が変更されたときに呼び出されるメソッド public void SetBGMVolume(float volume) { audioSourceBGM.volume = volume; } シーンの移動をすると、スライダーのアサインが抜けてしまいそこでエラーが出ている状況です。
fiveHundred

2023/11/23 11:33

> audioSourceBGMを破棄されたことではないと思われます。 どういう理由でそう思ったのですか? 提示のコードでも「Destroy(gameObject);」という、「オブジェクト全体を破棄する」内容が堂々と書かれているので、とても信頼できないのですが。
fiveHundred

2023/11/23 11:53

現状だと、破棄されず残っているゲームオブジェクトを(即座に破棄されてしまった)新しいゲームオブジェクトと勘違いしてしまっているのだと思いますが、どうでしょうか。
mimo2525

2023/11/23 11:55

返答ありがとうございます。 シーン移動をおこなっても、生成される前のBGMのあるオブジェクトはありました。 スライダーでの音量調整はできていませんが、直接BGMの音量調整はできていたので、根拠にしています。
mimo2525

2023/11/23 12:00

一番古いオブジェクトはずっと残り、たしかに新しいオブジェクトはすぐに破壊されています。
fiveHundred

2023/11/23 12:54

であれば、「BGMのあるオブジェクト」が一番古いオブジェクトということになります。 今気づいたのですが、古いオブジェクトを破棄してしまうと、BGMが最初から再生し直すことになってしまうので、むやみに破棄しないほうがいいですね。 続きは回答に追記します。
mimo2525

2023/11/23 14:15

上記のアドバイスありがとうございます。スライダーの設定は思っている感じに近づくことができました。 しかし、以下のようなエラーが出てしまいます。 NullReferenceException: Object reference not set to an instance of an object BGMManager.SetBGMVolume (System.Single volume) (at Assets/BDM.cs:44) UnityEngine.Events.InvokableCall`1[T1].Invoke (T1 args0) (at <30adf90198bc4c4b83910c6fb1877998>:0) UnityEngine.Events.UnityEvent`1[T0].Invoke (T0 arg0) (at <30adf90198bc4c4b83910c6fb1877998>:0) UnityEngine.UI.Slider.Set (System.Single input, System.Boolean sendCallback) (at ./Library/PackageCache/com.unity.ugui@1.0.0/Runtime/UI/Core/Slider.cs:540) UnityEngine.UI.Slider.set_value (System.Single value) (at ./Library/PackageCache/com.unity.ugui@1.0.0/Runtime/UI/Core/Slider.cs:267) BGMSlider.Start () (at Assets/BGMSlider.cs:12)
mimo2525

2023/11/23 14:15

上記のコードをもとに自分で組みなおしています。 using UnityEngine; using UnityEngine.UI; public class BGMSlider : MonoBehaviour { private void Start() { // BGMManager.Instanceがnullでないことを確認 if (BGMManager.Instance != null) { // BGMManagerのGetBGMVolume()で取得した値をスライダーの値に設定 GetComponent<Slider>().value = BGMManager.Instance.GetBGMVolume(); } else { Debug.LogError("BGMManager.Instanceがnullです。"); } } // こちらをスライダーに登録 public void SetBGMVolume(float volume) { // BGMManager.Instanceがnullでないことを確認 if (BGMManager.Instance != null) { BGMManager.Instance.SetBGMVolume(volume); } else { Debug.LogError("BGMManager.Instanceがnullです。"); } } } using UnityEngine; using UnityEngine.UI; public class BGMManager : MonoBehaviour { private AudioSource audioSourceBGM; public AudioClip bgm; public static BGMManager Instance; private void Awake() { if (Instance == null) { Instance = this; DontDestroyOnLoad(gameObject); audioSourceBGM = gameObject.AddComponent<AudioSource>(); audioSourceBGM.loop = true; audioSourceBGM.clip = bgm; audioSourceBGM.Play(); } else { // すでに存在する場合は即座に破棄する Destroy(gameObject); } } public void PlayBGM() { if (!audioSourceBGM.isPlaying) { audioSourceBGM.Play(); } } public void SetBGMVolume(float volume) { audioSourceBGM.volume = volume; } // BGMSliderから呼び出す用 public float GetBGMVolume() { return audioSourceBGM.volume; } }
fiveHundred

2023/11/24 02:39

エラーメッセージに「Assets/BDM.cs」とありますが、それは何ですか? (MonoBehaviourの)クラス名と.csのファイル名は同じにしないといけないはずですが。
mimo2525

2023/11/24 14:10

返答ありがとうございます。 クラス名と.csのファイル名を同じにしてきました。 いろいろ調べた結果、シーン移動を挟むとスライダーのスクリプトが抜けてしまっています。 それでエラーが出てしまっていることが分かりました。
mimo2525

2023/11/24 18:25

表現に誤りがありました。 シーンをまたぐと、スライダーのon value change がアサイン取れてしまう。
mimo2525

2023/11/24 21:07

BGMManagerがDon't Destroy On Loadを使用していることにより、シーンを切り替えたときにもオブジェクトが破棄されずに残り、その結果、重複したスライダーのon value changeがアサインされてしまっているのかなと考えましたけど。
fiveHundred

2023/11/25 02:49

以下のようにしていませんか? - BGMManagerとBGMSliderを同じゲームオブジェクトにアタッチする - BGMSliderのゲームオブジェクトをDontDestroyOnLoadに登録する BGMSliderはシーン移動で破棄される前提で書いているので、上記のようなことをすると正しく動作しません。 BGMSliderはオプション画面のシーン上のスライダーにアタッチし、それとは別のゲームオブジェクトにBGMManagerがある、という形になります。
mimo2525

2023/11/25 03:53

返答ありがとうございます。 -BGMManagerとBGMSliderを同じゲームオブジェクトにアタッチする →画像を添付しますが、おそらくしていないと思います。 https://88.gigafile.nu/1130-d27b31ea028358aedf164c20c3494a616 - BGMSliderのゲームオブジェクトをDontDestroyOnLoadに登録する →BGMSliderのスクリプトを確認した結果。DontDestroyOnLoadはなかったです。
fiveHundred

2023/11/25 04:04

ゲームオブジェクトの名前だけで分かるはずありませんが、「BGM」にBGMManagerを、「Slider」の片方にBGMSliderをアタッチしているということであっていますか? そうであれば、「BGM」と「Slider」のインスペクターはどうなっていますか?
fiveHundred

2023/11/25 05:14

> また、スライダーに登録する関数をBGMManager.SetBGMVolume()からBGMSlider.SetBGMVolume()に変更してください。 上記が行われておらず、BGMManagerのままです。 BGMSliderのほうのSetBGMVolumeに変更してください。
mimo2525

2023/11/25 14:29

上記のコードを試しましたが、シーンをまたぐと、スライダーのon value change がアサイン取れてしまいました。
mimo2525

2023/11/25 19:43

スライダーのコードです。 using UnityEngine; using UnityEngine.UI; public class BGMSlider : MonoBehaviour { public Slider bgmSlider; // BGMManagerのインスタンスをInspectorで設定するか、スクリプト内で取得するなどしてください。 public BGMManager bgmManager; private void Start() { // Sliderの初期値をBGMの音量に合わせる bgmSlider.value = bgmManager.GetBGMVolume(); // Sliderの値が変更されたときにBGMの音量を変更するメソッドを登録する bgmSlider.onValueChanged.AddListener(SetBGMVolume); } // Sliderの値が変更されたときに呼ばれるメソッド private void SetBGMVolume(float volume) { // BGMの音量を変更する bgmManager.SetBGMVolume(volume); }
fiveHundred

2023/11/26 02:33 編集

画像で追記するので確認してください。
mimo2525

2023/11/26 02:32

根気強く返事をしていただきありがとうございます。 私の理解力が乏しくて、説明の手間をかけさせてしまいすみません。
fiveHundred

2023/11/26 02:40

すみません、画像の指摘は原因と関係なかったかもしれません。 他に考えられる点として「public BGMManager bgmManager;」は「BGMManager.Instance」で取得するので不要です。 むしろ、「public BGMManager bgmManager;」を用意してしまったせいで、これのアサインの有無で問題になっているのだと思います。 「BGMManager.Instance」であれば、(BGMManagerがあれば)常に取得できるはずです。
mimo2525

2023/11/26 02:49

画像の通りしてみましたが、変化はなかったです。
mimo2525

2023/11/26 02:59

スライダーのコードはこれにしています。 using UnityEngine; using UnityEngine.UI; public class BGMSlider : MonoBehaviour { private void Start() { GetComponent<Slider>().value = BGMManager.Instance.GetBGMVolume(); } // こちらをスライダーに登録 public void SetBGMVolume(float volume) { BGMManager.Instance.SetBGMVolume(volume); } } いろいろ変えたりして試しており、コードは度々変えています。
fiveHundred

2023/11/26 03:40

すみません、現在のエラーメッセージはどうなっていますか?
mimo2525

2023/11/26 16:19

エラーです。 NullReferenceException: Object reference not set to an instance of an object BGMManager.SetBGMVolume (System.Single volume) (at Assets/scpri/BGMManager.cs:42) UnityEngine.Events.InvokableCall`1[T1].Invoke (T1 args0) (at <30adf90198bc4c4b83910c6fb1877998>:0) UnityEngine.Events.UnityEvent`1[T0].Invoke (T0 arg0) (at <30adf90198bc4c4b83910c6fb1877998>:0) UnityEngine.UI.Slider.Set (System.Single input, System.Boolean sendCallback) (at ./Library/PackageCache/com.unity.ugui@1.0.0/Runtime/UI/Core/Slider.cs:540) UnityEngine.UI.Slider.set_value (System.Single value) (at ./Library/PackageCache/com.unity.ugui@1.0.0/Runtime/UI/Core/Slider.cs:267) BGMSlider.Start () (at Assets/BGMSlider.cs:8)
fiveHundred

2023/11/27 02:20

すみません、私でも原因は分かりませんでした。 エラー発生個所は「audioSourceBGM.volume = volume;」らしいので、audioSourceBGMが無さそうなのですが、Awake()でaudioSourceBGMを生成しているので、そんなことはないはずなのですよね。 また、こちらでも(私が回答した)スクリプトを試しましたが、特に問題はありませんでした。 一応、そのプロジェクトファイルを.unitypackage形式で送付しますので、確認してみてください。 https://drive.google.com/file/d/1QMeUQmLQG-WMgJH2KyMCNoFfIEaIsDld/view?usp=sharing
mimo2525

2023/11/27 02:34

作っていただきありがとうございます。 新しいプロジェクトで試しに動かしてみます。
mimo2525

2023/11/27 02:40

プロジェクトは、ボタンでシーン移動(BGMはとぎれないようにしている。)するものですか?
fiveHundred

2023/11/27 02:44

はい、そうなっています。
mimo2525

2023/11/27 02:44

すみません。スライダーがありました。
mimo2525

2023/11/27 02:46

提供していただいたものでしたら、シーン移動を挟んでも音量調整は自由にできます。
mimo2525

2023/11/27 02:58

シーンチェンジのスクリプトは、ボタンに直接貼っていますか? 自分は空のオブジェクトをつくり、SceneControllerを作って。 ボタンのオブジェクトにそのシーンコントローラーを読ませています。 自分が見た感じの違いはそれだけです。
fiveHundred

2023/11/27 03:08

> シーンチェンジのスクリプトは、ボタンに直接貼っていますか? スクリプトやシーンを見れば分かると思いますが、そのようにしています。
mimo2525

2023/11/27 09:58

解決しました。根気強くアドバイスをしていただきありがとうございます。 スライダー側で習得させる方向で何とかなりました。 using UnityEngine; using UnityEngine.UI; public class BGMSlider : MonoBehaviour { private Slider bgmSlider; private void Awake() { // Sliderコンポーネント取得 bgmSlider = GetComponent<Slider>(); } private void Start() { // BGMの現在のボリューム設定 bgmSlider.value = BGMManager.Instance.GetBGMVolume(); // 呼び出し bgmSlider.onValueChanged.AddListener(volume => BGMManager.Instance.SetBGMVolume(volume)); Debug.Log("BGMSlider Start called. BGMManager.Instance is " + (BGMManager.Instance == null ? "null" : "not null")); } private void OnEnable() { //再割り当て bgmSlider.onValueChanged.AddListener(volume => BGMManager.Instance.SetBGMVolume(volume)); } private void OnDisable() { //リスナーを削除 bgmSlider.onValueChanged.RemoveListener(volume => BGMManager.Instance.SetBGMVolume(volume)); } }
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.41%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問