Zufalls Animationen abspielen?

  • Hallo


    Das ist kein Compilierungsfehler, lediglich eine nett gemeinte Warnung, dass der Animation Blueprint per Default Multithreaded ist zur Optimierung. Die random Methode die du aufrufst ist allerdings nicht Thread safe, zumindest hat sie das nicht definiert und deswegen die Warnung.

    Du kannst das Multithreading direkt im AnimationBP deaktivieren unter Classsettings->Optimization. Das würde ich die allerdings nicht empfehlen, denn dann läuft das auf einem Thread was die Performance negative beinflussen kann.

    Der Eventgraph wird nicht auf mehreren Threads ausgeführt, deswegen dort auch die ganze Logik wo du die Methode auch problemlos aufrufen kannst.
    Allerdings hätte ich jetzt gesagt das sollte trotzdem problemlos funktionieren? Hast du es ausprobiert?


    Gruss

  • Es ist ja kein Fehler, sondern "nur" eine Warnung, dass das Ganze nicht Threadsicher ist.


    Wie beschreibt man das nun am besten?


    Nehmen wir mal an, du greifst von zwei, oder auch mehr, Threads auf etwas zu. Lesen ist kein Problem. Aber wenn Thread 1 etwas in das Objekt schreibt, dann muss dafür gesorgt werden, dass in dem Moment natürlich von keinem anderen Thread, weder lesen noch schreiben, auf das Objekt zugegriffen werden kann, da sonst die Sicherheit des Schreibzugriffs nicht sicher ist. In diesem Fall ist es dein Random Integer, du kannst hier nicht sicherstellen, falls zwei Threads diesen benutzen, das dann nicht einmal 0 und einmal 1 gleichzeitig herauskommt.


    Nun habe ich Randomwerte in Animationen noch nie benutzt. Aber die Lösung steht eigentlich in der Warnung. Offensichtlich gibt es eine Option, in der du den Zugriff von mehreren Threads abschalten kannst.

  • Danke für eure Erklärungen,

    was ist ein Thread?

    Und nein, mein Beispiel funktioniert nicht, es wird keine Zufallszahl generiert, die dann eine zufällige Animation abspielt, schade, warum eigentlich nicht?

    wie würde es stattdessen gehen?

    eigentlich einfacher Gedanke, den ich umsetzen will, aber stellt sich schwierg dar.

  • Was ist ein Thread?


    Ich versuche es mal. Windows ist Multitaskingfähig. Das bedeutet, dass jedes Programm in einem eigenen Task läuft. Das gilt aber nicht notgedrungen für jedes einzelne Programm, sondern auch innerhalb eines Programms können mehrere Prozesse parallel ablaufen. Also an einer Stelle werden zum Beispiel irgendwelche Berechnungen gemacht, an anderer Stelle horcht ein Server zum Beispiel darauf, ob sich jemand ein oder ausloggt usw. Aber bei Spielen zum Beispiel hast du eine Menge NPCs oder mehrere Spieler, sie alle laufen nicht notgedrungen, aber es ist machbar, dass jeder davon seinen eigenen Thread bekommt, sprich unabhängig von dem anderen berechnet, das sind dann einzelne Threads. In der Praxis macht man natürlich nicht für jeden Vogel oder was auch immer einen eigenen Thread auf. Normalerweise hat man bei einigen Programmen so 2, 3 oder 4 Threads. Einer für das Spiel, einer für KI und ein anderer für Physik oder so. Dies wird dann allgemein berechnet und dem entsprechenden Objekt dann zugewiesen usw. Und an der Stelle musst du dann auch für Threadsicherheit sorgen.


    Also die Formulierung ist jetzt nicht ganz vollständig, dementsprechend gibt es da auch Verbesserungsmöglichkeiten in der Erklärung, aber ich denke das Grundprinzip ist soweit klar.


    Warum das bei dir nicht funktioniert kommt darauf an, was du nun genau umsetzen wolltest. Ist das eine Animation, die mehreren NPCs zugeordnet wird, also bewegen sich dann alle NPCs gleich? Dann liegt es an der Threadsicherheit.


    Handelt es sich nur um die Spielfigur oder einem NPC wo dann immer nur die gleiche Animation ausgeführt wird, du darfst nicht vergessen, du hast hier nur einen Wert von wegen 0 oder 1. Beim Computer sind Zufallszahlen nicht wirklich zufällig. Es kann durchaus passieren, dass bei einem Generator 20 oder 30 Mal hintereinander 0 gezogen wird, Und das, wenn du keinen Randomseed eingebaut hast, jedes Mal genau so wenn du das Programm neu startest. Ein Randomseed könnte zum Beispiel sein, dass du die aktuelle Sekunde als Seed übergibst, bevor du das Random ausführst.


    Nun habe ich wie gesagt allerdings noch nie versucht zufällige Animationen zu basteln, von daher weiß ich nicht, welche Möglichkeiten du da in den BPs hast. Die Beschreibung gilt jetzt für Projekte, die ich normalerweise in C# programmiere und allgemein für Zufallsgeneratoren in Programmen.

    • Hilfreich

    Hey zusammen


    Zu diesem Thema gibt ganze Bücher. Zur Ergänzung wieso überhaupt Multithreading nötig ist bezogen mit einem Beispiel der Unreal Engine. Nehmen wir einmal an, du hast einen rechenintensiven Task, das kann zum Beispiel AI sein, Animation, oder kürzlich habe ich Positionsberechnungen für eine Formation durchführen müssen. Als Beispiel stellvertretend sagen wir mal, wir müssen alle Primzahlen bis zu 1'000'000 ausgeben.


    Los geht's, einfach in Blueprint ein Loop bis zu einer Mio:



    Wenn ich das jetzt ausführe freezed das ganze Spiel für ein paar Sekunden und bricht den Loop dann ab. Es wirkt also so als ob das hängen geblieben ist. Das ist also absolut keine Option. Das sieht man auch sonst häufig zum Beispiel bei Ladeanimationen, wenn der Mainthread blockiert ist, bleibt einfach die Animation stehen. Wieso passiert das? Der Mainthread bearbeitet das Sequenziell, also alles andere muss warten bis diese Rechenintensive Operation abgeschlossen ist. Entsprechend friert das Bild ein, keine Inputs mehr möglich etc.


    Wie löst man das jetzt? Mann kann das an den Tick hängen und pro Tick nur eine oder ein paar dieser Zahlen berechnen, sodass der Mainthread nicht blockiert.



    Und siehe da - das Spiel friert nicht mehr ein. Aber nun dauert das ewig. Was vorher eine Minute gedauert hat, dauert nun über eine Stunde. Was nun? Multithreading!

    Dazu der erstelle ich die Klasse PrimeNumberWorker und implementiere Runnable.




    Was immer jetzt in Run ausgeführt wird passiert auf einem eigenen Thread.

    Erstellen und gleich starten kann ich den mit:

    C++: Starten
        Worker = new FPrimeNumberWorker(Iterations);

    Und wieder löschen:

    Code: Löschen
      delete Worker;

    Okay. Wenn ich den jetzt ausführe, keine Einfrieren und die Berechnung dauert wieder etwa eine Minute - Cool :)

    Wie du siehst, hat das Potential für wirklich(!) erhebliche Performanceoptimierung. Kommt aber auch mit starker Limitierungen, so kannst du nicht einfach Daten auf deinem Mainthread lesen oder Schreiben. Ein Teil dieser Problematik hat schon Tomarr erklärt.


    Das war jetzt etwas unnötig ausschweifend. Zurück zum Punkt. Der BP den du gepostet hast funktioniert bei mir. Natürlich siehts nicht gut aus, weil jetzt wechselt der Animation mehrfach pro Sekunden, also jedes Update gibts unter Umständen ein Wechsel.


    Für deinen Zweck gibts den RandomSequencePlayer. Der ist Threadsafe und macht genau was du willst. Er wechselt die Animation random. Du kannst sagen wie oft er dieselbe Animation spielen soll, welche Wahrscheinlichkeit etc. So funktioniert's:



    Auf der rechten Seite kannst du alle die Animation hinzufügen die du möchtest.


    Gruss

  • Phoenix super Antwort danke, das mit dem Thread kommt mir sehr komplex vor.

    Wegen dem Random Sequenzer, den kenn ich, das Problem ist, dass der Sequencer die Animationen loopen lässt, was ich dort nicht abstellen kann, deshalb habe ich einen Umweg gesucht um den Random Sequenzer nicht zu nutzen.