2016-12-15 4 views
0

私はC#のでユニティ5.3で働いているコードエディタとしてユニティ5.3 - トグルサウンドオン/オフ

これらは私が持っているものです:

私は私のプロジェクトで2つのシーンを持っています:homeおよびoptions。私は両方のシーンでbgオブジェクトを持っています。両方のbgオブジェクトはAudio Sourceコンポーネントを持っています。これは同じ背景音楽を含んでいますplay on awakeです。私はこれらの背景音楽のためのコードを使用しない、私はUnityのAdd Componentボタンをクリックし、Audio Sourceを加えなさい。

は、これは私が欲しいものです:

Optionsシーンは全てのシーンのためにオン/オフBGMを切り替えることができます。したがって、OptionsシーンにはbtnOnbtnOffが存在します。

私はこのエラーを持っている:An object reference is required to access non-static member UnityEngine.AudioSource.volume

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

public class AudioManager : MonoBehaviour { 
    public Button btnOn; 
    public Button btnOff; 

    // Use this for initialization 
    void Start() { 
     btnOn = GetComponent<Button>(); 
     btnOff = GetComponent<Button>(); 

     btnOn.onClick.AddListener(() => PlayAudio()); 
     btnOff.onClick.AddListener(() => StopAudio()); 
    } 

    void PlayAudio() 
    { 
     AudioSource.volume = 0.5f; 
    } 

    void StopAudio() 
    { 
     AudioSource.volume = 0f; 
    } 
} 

これが問題である:

これは、オーディオManager.csで私のコードです。たぶん、これは私のコードにpublic AudioSource audioSourceを書き込まないためです。しかし、私がこれを書いた場合、別のオーディオをGet Componentボックスに追加しなければならず、1つのシーンに2倍のAudio Sourceが表示されます。私は何をすべきか? AudioManager[DontDestroyOnLoad]としてマークされていない、あなたのおかげであなたは、両方のシーンでとしてbgオブジェクトを持っていたよう

答えて

2

、それはあなたがシーンをロードするたびに発生しますStart()機能です(その後、私はあなたにも、両方のシーンで1 AudioManagerを持っていると仮定します)。

ですから、private AudioSourceを宣言し、あなたのシーンであなたのBGオブジェクトを見つけ、それにGetComponentを呼び出すことによって、それの参照を取得することができます

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

public class AudioManager : MonoBehaviour 
{ 
    public Button btnOn; 
    public Button btnOff; 

    private AudioSource audioSource; 

    // Use this for initialization 
    void Start() 
    { 
     btnOn = GetComponent<Button>(); 
     btnOff = GetComponent<Button>(); 

     btnOn.onClick.AddListener(() => PlayAudio()); 
     btnOff.onClick.AddListener(() => StopAudio()); 

     audioSource = GameObject.Find("bg").GetComponent<AudioSource>(); 
    } 

    void PlayAudio() 
    { 
     audioSource.volume = 0.5f; 
    } 

    void StopAudio() 
    { 
     audioSource.volume = 0f; 
    } 
} 
+0

それはこのエラーがあります: 'とNullReferenceException:オブジェクト参照object' –

+0

のインスタンスに設定されていない、あなたのシーンの階層構造のスクリーンショットを投稿できますか? – Whatever

+0

こちらをご覧ください(https://www.dropbox.com/s/bainn1z8wd1ft1w/Capture.JPG?dl=0) –

1

あなたはANのプロパティを割り当てる必要があるため、エラーが発生します個々のオブジェクト。ボリュームはソース間で共有されません。このため、インスペクタで割り当てるフィールドが必要になるか、GetComponentという参照を取得する必要があります。

オプションを処理するために別のシーンを使用するのは間違っていませんが、それはちょっと不器用です。現在のシーンをアンロードする(DontDestroyOnLoadとしてマークされていないすべてのオブジェクトおよびそれらに関連付けられた情報を破棄する)必要があります。その後、オプションがロードされ、前のシーンがロードされます。音楽をアンロードすると再生が停止する可能性が最も高くなります。再生を開始すると、最初から再生が開始されます。これらのオブジェクトの設定は失われていません(ボリューム、トラックの変更など)。

上記のDontDestroyOnLoadは、同じオブジェクトで変更を加えるために役立ちますが、そのようなオブジェクトが存在するシーンがロードされるたびに重複を処理する必要があります。OnLevelWasLoaded(documentation現時点では欠けているものです)、破壊する物体を決定する瞬間です。

もう1つのポイントは、現在公共のButtonフィールドがあることです。これにより、インスペクタを介した割り当てが可能になりますが、それはStart(上書きすると新しいオブジェクトが同じオブジェクトに割り当てられる最初のボタンコンポーネント)になります。これらのフィールドをプライベートにするか、少なくとも割り当てられていないことを確認します。しかし、シーン間で設定を永続させる方法については、少し話題になっています。

アイデアを伝えるためのコードですが、現在テスト環境にアクセスできないため、テストされていないことを警告してください。このソリューションは、シーン間で永続的なオブジェクトを使用します。別のシーンがロードされた後、エディタを介してこのオブジェクトに確立された接続が失われることに注意してください。

public class AudioManager : MonoBehaviour 
{ 
    private AudioSource source; 

    // Called regardless of whether the object is enabled or not. 
    // Should not be called in a new scene. 
    private void Awake() 
    { 
    // Protect this object from being destroyed so its volume 
    // is maintained between scenes. 
    DontDestroyOnLoad(this.gameObject); 
    source = GetComponent<AudioSource>(); 
    }  

    public void DestroyPossibleDuplicates() 
    { 
    AudioManager[] managers = FindObjectsOfType(typeof(AudioManager)) as AudioManager[]; 
    foreach (AudioManager manager in managers) 
    { 
     // Use something to determine whether a manager is a duplicate. 
     // It must not be this, but have something in common; a name perhaps? 
     if ((manager != this) && (manager.gameObject.name == this.gameObject.name)) 
     { 
     // Destroy the duplicates so their sound won't interfere. 
     Destroy(manager.gameObject); 
     } 
    } 
    } 

    private void BindToInterface() 
    { 
    Slider[] sliders = FindObjectsOfType(typeof(Slider)) as Slider[]; 
    foreach (Slider slider in sliders) 
    { 
     // Determine whether the specified slider should have effect on this object. 
     // If the slider's name contains this object's name assume it should. 
     if (slider.gameObject.name.indexOf(this.gameObject.name)!=-1) 
     { 
     slider.onValueChanged.addListener((float value)=> 
     { 
      // In this case a slider is used for more control over the volume. 
      // Different elements require other logic to function. 
      source.volume = value; 
     }); 
     } 
    } 
    } 

    // If my memory serves correct this method is only called on objects 
    // that were in the scene before it started loading. 
    // Just to be safe, don't have it do anything depending on this difference. 
    private void OnLevelWasLoaded() 
    { 
    DestroyPossibleDuplicates(); 
    BindToInterface(); 
    }  
} 
+0

「タイプ文字列にindexOfの定義が含まれておらず、文字列型の拡張メソッドindexOfが見つかりませんでした」 –

+0

最近、小文字で始まる関数名を使用する他のプログラミング言語を使用していました。 'IndexOf'はそのトリックを行うべきです。 'Contains'もうまくいくはずです(実際に意図されていた通り、C#はそれを忘れていました)。 – Yemachu

+0

あなたのコードには2つのエラーがあります。それが最初のものです。これは2番目のタイプです: 'Type UnityEngine.UI.Slider.SliderEventにaddListenerの定義がなく、拡張メソッドがありません。タイプUnityEngine.UI.Slider.SliderEvent'のaddListener –