Jump to content
Unity Insider Forum

Abfrage AudioSource.isPlaying in Update oder als StartCoroutine


delspeedy

Recommended Posts

Hallo @all

 

Wollte mal nachfragen wie ihr Abfragen löst die nur sehr ungenau überprüft werden müssen.

In meinen Fall geht es darum, ob ein Sound noch abgespielt wird, oder schon beendet ist.

Habe es derzeit über StartCoroutine gelöst.

 

void Start ()
{
...

StartCoroutine (CheckIsMusicPlaying (1.25f))
}

IEnumerator CheckIsMusicPlaying (float waitSeconds)
{
while (!stopMusic)
{
yield return new WaitForSeconds (waitSeconds);
if (!audioScoures[lastAudioClip].isPlaying)
{
PlayRandomMusic();
}
}


void PlayRandomMusic ()
{
  Debug.Log ("audioScoure: " + audioScoures [lastAudioClip].clip.name + "ended");
  int tempAudioClip = lastAudioClip;
  while (tempAudioClip == lastAudioClip) {
 tempAudioClip = Random.Range (0, audioScoures.Length);
  }
  lastAudioClip = tempAudioClip;
  audioScoures [lastAudioClip].Play ();
  Debug.Log ("Play audioScoure: " + audioScoures [lastAudioClip].clip.name);
}
[size=4]

[/size]

 

Thx & bye

delspeedy

Link zu diesem Kommentar
Auf anderen Seiten teilen

Mit Coroutine würd ich das nicht machen, das ist wie mit Atombomben auf Spatzen geschossen xD

Ich hätte das jetzt mit einem Timer gemacht.

 

float timer = 0.0F;
float time = 3.0F; //wie oft soll überprüft werden? 3 = 3 Sekunden

void Update()
{
  if(timer < Time.time)
  {
  //dein random music code
  timer = Time.time + time;
  }
}

Link zu diesem Kommentar
Auf anderen Seiten teilen

Da fehlt glaube ich die Time.deltaTime.. irgendwie.. :ph34r:

Mach' es einfach so:

function Update ()
{
	if (!audio.isPlaying)
       {
		audio.clip = otherClip;
		audio.Play();
	}
}

Da wird ja nur eine bool-Variable abgefragt. Kleiner oder größer ( für die Zeit ) ist wahrscheinlich zeitaufwendiger für den Computer als einen boolschen Wert zu überprüfen.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Wird ebenfalls pausiert. Time.time ist 0 wenn das Spiel gestartet wird und erhöht sich stetig. Gib doch mal in irgend einer Update() Funktion

Debug.Log(Time.time);

ein und teste es selbst. Verwende diese Art des Timings sehr oft und bin sehr zufrieden damit.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Der Corouztinen Vorschlag ist bisher das was am wenigsten Performance ziehen sollte, da dadurch keine extra Update Methode erforderlich ist. Update ist langsamer als eine solche Couroutinen da Unity intern Update per Reflection Invoke oder vergleichbarem aufruft.

 

Nach der Couroutine wäre der nächst beste Vorschlag einfach isPlaying direkt in Update abzufragen, da ich bezweifle dass dies ein signifikant teuer Aufruf ist und man ihn sicher hunderte male pro Frame ausführen kann ohne dabei einen merkbaren Leistungseinbruch zu bemerken.

 

Auch wäre es machbar zusätzlich zur Coroutine sowas zu machen:

 

Invoke("AudioClipStopped", audioClip.length);
...

void AudioClipStopped()
{
 ...
}

 

Wobei man hier innerhalb von AudioClipStopped überprüfen sollte ob er wirklich gestippt wurde, nur um sicher zu gehen.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Vielen Dank für Eure zahlreichen Infos hierzu. :D

Habe mal getestet wie lange "if(!audiosource.isPlaying)..." in der Update Methode verbraucht

 

2GHz mobile CPU/Im Editor/For-Schleife - Time for !isPlaying x 10000: 00:00:00.0014351

 

 stopwatch.Start(); 
 for (int i = 0; i < 10000; i++)
 {
  if (!audioScoures[lastAudioClip].isPlaying)
  {
   PlayRandomMusic();
  }
 }
 stopwatch.Stop();
 Debug.Log ("Time for !isPlaying x 10000: " +stopwatch.Elapsed);
 stopwatch.Reset();

 

Leider messe ich natürlich die Schleife und den Array-Zugriff mit.

Auf Dauer sollte die Coroutine merklich CPU Zeit sparen. Vor allem wenn man sehr viele Ereignisse timen möchte.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Du misst da aber nicht nur isPlaying sondern auch PlayRandomMusic, ist das beabsichtigt? Und interessiert dich wirklich wieviel zeit 10000 Durchgänge insgesamt beanspruchen?

 

Nichts gegen Coroutinen, aber ich hab den Eindruck hier wird zu früh optimiert ;)

Link zu diesem Kommentar
Auf anderen Seiten teilen

Habe 10000 Schleifendurchläufe um den Durchschnittswert einer Abfrage besser berechnen zu können.

PlayRandomMusic wird in dem Beispiel nie aufgerufen, da die Zeitspanne zu kurz ist um ans Ende des Musikstücks zu gelangen.

 

Wollte nicht optimieren sondern wissen ob man Ereignisse die nur "ungenau" abgefragt werden müssen, so implementiert werden können.

isPlaying hat sich nur eben gerade angeboten - bezieht sich aber generell auf Ereignisse die überprüft werden müssen.

 

p.s Wann benutzt man "StartCoroutine_Auto" - ist nicht in der Unity-Doku

Link zu diesem Kommentar
Auf anderen Seiten teilen

InvokeRepeating scheint in der Tat schneller als Coroutinen ( Platz 2 ) und Update ( #3 ) zu sein.

Trotzdem finde ich den Code leichter verständlich und weniger abstrakt, wenn man Update benutzt, denn man sieht ganz klar und deutlich, dass sich da in Update( ) was tut.. --Eine gestartete Coroutine oder Invoke gerät in richtig großen Projekten ggf. schnell mal in Vergessenheit, wobei gerade in großen Projekten der Performance-Gewinn unter Umständen nötig ist, den man durch Invoke oder Coroutinen hätte. :lol:

Tja.. die Qual der Wahl.. :D

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

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

×
×
  • Neu erstellen...