Jump to content
Unity Insider Forum

C# - Musikdateien während der Laufzeit in das Programm laden


Buttermilch

Recommended Posts

Guten Abend zusammen,

ich möchte, dass man in meinem Spiel eine externe Audiodatei von dem PC laden kann. Diese brauche ich dort für Game-Objekte welche auf diese reagieren.

Ich habe bereits das ganze Gedöns rund um den Dateipfad fertig, und geladen wird die Datei auch. Allerdings wird beim Abspielen der Datei nur ein schriller, langer Ton erzeugt. Unity gab mir bereits die Meldung, dass ich nur Dateien im " wav " Format nutzen kann. Mit der Datei ist auch alles in Ordnung, ich habe blos keine Ahnung wo der Fehler liegen kann.

Hier meint Script zum laden der Datei:

	public AudioSource audios;

	
	void Start () {
		
		WWW www = new WWW("file:///"+testFileBrowser.output);
		audios = GetComponent<AudioSource> ();
		audios.clip = www.GetAudioClipCompressed();
		while (!www.isDone) {
			print("Processing File" + testFileBrowser.output);
		}
		if (www.isDone) {
			print ("Song is done");
		}
		if (!audios.isPlaying && audios.clip.isReadyToPlay == true) {
			audios.Play ();
		}
	}
	

Hoffe ihr könnt mir helfen :)

Danke im Voraus!

 

EDIT: Manchmal passiert auch einfach gar nichts. Also gar kein Ton.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Vielleicht musst du noch angeben, daß es ein WAV-File ist. Ich sehe hier nur die Doku für die neue Version, da holt man sich den Audioclip dann so:

// Neue Unity Version
AudioClip myclip = WWWAudioExtensions.GetAudioClipCompressed(www, false, AudioType.WAV);

// Alte Unity Version
AudioClip myclip = www.GetAudioClipCompressed(false, AudioType AudioType.WAV);

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 9 Stunden schrieb Zer0Cool:

Vielleicht musst du noch angeben, daß es ein WAV-File ist. Ich sehe hier nur die Doku für die neue Version, da holt man sich den Audioclip dann so:


// Neue Unity Version
AudioClip myclip = WWWAudioExtensions.GetAudioClipCompressed(www, false, AudioType.WAV);

// Alte Unity Version
AudioClip myclip = www.GetAudioClipCompressed(false, AudioType AudioType.WAV);

 

Das hat leider nichts geändert. Ich nutze also immer noch das oben angegebene Script.

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Bei mir funktioniert alles wie erwartet, mit *.wav Endung ohne irgendwelche Probleme, ohne Endung muss ich den Typ mit übergeben. Vielleicht stimmt ja doch etwas mit deinem Audiofile nicht, schau einmal vorn in den Header deiner Datei (einfach mit einem Texteditor öffnen  z.b. Notepad), dieser sollte ungefähr so aussehen:

RIFFÌì	 WAVEfmt

Es gibt auch verschiedene WAV-Formate, normalerweise sollte Unity aber damit klarkommen.

Hier die ganze Klasse.

using UnityEngine;
using System.Collections;

public class LoadAudio : MonoBehaviour {

    public string location;
    private AudioSource audios;

    void Start()
    {
        WWW www = new WWW("file:///" + location);
        audios = GetComponent<AudioSource>();
        audios.clip = www.GetAudioClipCompressed(false, AudioType.WAV);
        while (!www.isDone)
        {
            print("Processing File" + location);
        }
        if (www.isDone)
        {
            print("Song is done");
        }
        if (!audios.isPlaying && audios.clip.isReadyToPlay == true)
        {
            audios.Play();
        }
    }
}


 

Link zu diesem Kommentar
Auf anderen Seiten teilen

So hier eine stark verbesserte Version (Coroutine), diese blockiert nicht den Mainthread beim Laden. Ich vermute zudem wir haben die Zuweisung "GetAudioClipCompressed" viel zu früh gemacht. Diese darf erst ausgeführt werden, wenn das File fertig geladen wurde...

using UnityEngine;
using System.Collections;

public class LoadAudio : MonoBehaviour
{

    public string location;
    private AudioSource audios;

    IEnumerator Start()
    {
        audios = GetComponent<AudioSource>();

        print("Processing File: " + location);
        WWW www = new WWW("file:///" + location);

        yield return www;

        audios.clip = www.GetAudioClipCompressed(false, AudioType.WAV);

        print("Song is loaded.");

        if (audios.clip.loadState != AudioDataLoadState.Loaded)
        {
            print("Audioclip LoadState Problem: " + audios.clip.loadState);
        } else
        {
            audios.Play();
        }

    }
}

Wenn er beim LoadState noch Probleme macht, dann muss man zusätzlich noch darauf warten ...

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 41 Minuten schrieb Zer0Cool:

So hier eine stark verbesserte Version (Coroutine), diese blockiert nicht den Mainthread beim Laden. Ich vermute zudem wir haben die Zuweisung "GetAudioClipCompressed" viel zu früh gemacht. Diese darf erst ausgeführt werden, wenn das File fertig geladen wurde...


using UnityEngine;
using System.Collections;

public class LoadAudio : MonoBehaviour
{

    public string location;
    private AudioSource audios;

    IEnumerator Start()
    {
        audios = GetComponent<AudioSource>();

        print("Processing File: " + location);
        WWW www = new WWW("file:///" + location);

        yield return www;

        audios.clip = www.GetAudioClipCompressed(false, AudioType.WAV);

        print("Song is loaded.");

        if (audios.clip.loadState != AudioDataLoadState.Loaded)
        {
            print("Audioclip LoadState Problem: " + audios.clip.loadState);
        } else
        {
            audios.Play();
        }

    }
}

Wenn er beim LoadState noch Probleme macht, dann muss man zusätzlich noch darauf warten ...

Danke für deine Antwort. Das Problem ist jedoch nicht ganz gelöst...

Als ich nun das Spiel startete wurde immer noch keine Musik gespielt. Danach wollte ich in der Konsole nach Fehlermeldungen schauen, und genau dann als ich diese skalliert habe, fing die Musik an zu spielen. Immer wenn ich die Konsole dann neu skallierte, fing der Song von vorne an.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich kenne dein Projekt nicht (wenn dein Spiel bei Starten relativ lange dauert etc., dann kann das Laden eines Files schon einmal eine Weile dauern), aber wenn du das Skript von oben verwendest (d.h. in der Startmethode eines Skriptes auf einem Objekt) und deine Audiosource nicht auf "Loop" steht, dann sollte die Datei nur 1x abgespielt werden. Ansonsten halt einmal prüfen was das Skript in der Console ausgibt und ob "audios.Play()" 1x ausgeführt wird.

Alternativ könntest du das Laden des Files auch einmal in eine eigene Coroutine auslagern.

using UnityEngine;
using System.Collections;

public class LoadAudio : MonoBehaviour
{

    public string location;
    private AudioSource audios;

    void Start()
    {
        audios = GetComponent<AudioSource>();
            WWW www = new WWW("file:///" + location);
        IEnumerator coroutine = LoadWWW(www);
        StartCoroutine(coroutine);
    }

    IEnumerator LoadWWW(WWW www)
    {
        print(Time.realtimeSinceStartup + ": Processing File" + location);
        while (!www.isDone)
            yield return null;
        print(Time.realtimeSinceStartup + ": File is loaded.");

        audios.clip = www.GetAudioClipCompressed(false, AudioType.WAV);
        while (audios.clip.loadState != AudioDataLoadState.Loaded)
            yield return null;
        print(Time.realtimeSinceStartup + ": Audio is ready.");
        audios.Play();
    }
}
}

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 16 Stunden schrieb Zer0Cool:

Ich kenne dein Projekt nicht (wenn dein Spiel bei Starten relativ lange dauert etc., dann kann das Laden eines Files schon einmal eine Weile dauern), aber wenn du das Skript von oben verwendest (d.h. in der Startmethode eines Skriptes auf einem Objekt) und deine Audiosource nicht auf "Loop" steht, dann sollte die Datei nur 1x abgespielt werden. Ansonsten halt einmal prüfen was das Skript in der Console ausgibt und ob "audios.Play()" 1x ausgeführt wird.

Alternativ könntest du das Laden des Files auch einmal in eine eigene Coroutine auslagern.


using UnityEngine;
using System.Collections;

public class LoadAudio : MonoBehaviour
{

    public string location;
    private AudioSource audios;

    void Start()
    {
        audios = GetComponent<AudioSource>();
            WWW www = new WWW("file:///" + location);
        IEnumerator coroutine = LoadWWW(www);
        StartCoroutine(coroutine);
    }

    IEnumerator LoadWWW(WWW www)
    {
        print(Time.realtimeSinceStartup + ": Processing File" + location);
        while (!www.isDone)
            yield return null;
        print(Time.realtimeSinceStartup + ": File is loaded.");

        audios.clip = www.GetAudioClipCompressed(false, AudioType.WAV);
        while (audios.clip.loadState != AudioDataLoadState.Loaded)
            yield return null;
        print(Time.realtimeSinceStartup + ": Audio is ready.");
        audios.Play();
    }
}
}

 

Ich habe nun dieses Skript benutzt und jetzt klappt alles. Ich habe keinen Plan warum die anderen nicht funktionierten...

Jedenfalls, vielen Dank! :D

Link zu diesem Kommentar
Auf anderen Seiten teilen

Dann ist ja gut ;). Na der Hauptunterschied ist, daß ich zusätzlich noch auf den Status den Clips warte und erst wenn dieser "Loaded" ist die Datei abspiele. Die Methode wie ich auf "www" warte soll angeblich äquivalent sein. Ansonsten ist es auch (wie ich finde)  sauberer die Start-Methode nicht als Coroutine zu verwenden (obwohl diese Variante aus der Unity-Doku stammt).

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

Dieses Thema ist jetzt archiviert und für weitere Antworten gesperrt.

×
×
  • Neu erstellen...