ich habe das hier im AnimBP mir so gedacht, warum geht das nicht?
Warum der Compile Fehler?
ich habe das hier im AnimBP mir so gedacht, warum geht das nicht?
Warum der Compile Fehler?
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.
unegfähr verstanden, mein Beispiel gilt nur für den SpielerCharacter, es soll mal die eine, mal die andere Animation spielen, der Zufall soll entscheiden. Was hat das mit irgendwelchen Threads zu tun? ich habe ja nur eine Figur. Naja.
schau dir mal im AnimBP die Node "Random Sequenz Player" an. Da kannst du div. Animationen einfügen und einen Wert für die Wahrscheinlichkeit der Animation.
Vielleicht bringt es dir ja was.
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.
class DEMO_API FPrimeNumberWorker : public FRunnable
{
public:
FPrimeNumberWorker(const int Iterations);
~FPrimeNumberWorker();
virtual bool Init() override;
virtual uint32 Run() override;
virtual void Stop() override;
private:
int IterationsCount;
FRunnableThread* Thread;
bool bShouldRun;
};
Alles anzeigen
FPrimeNumberWorker::FPrimeNumberWorker(const int Iterations)
{
IterationsCount = Iterations;
Thread = FRunnableThread::Create(this, TEXT("PrimeNumberWorker"));
}
FPrimeNumberWorker::~FPrimeNumberWorker()
{
if (Thread)
{
Thread->Kill();
delete Thread;
}
}
bool FPrimeNumberWorker::Init()
{
return FRunnable::Init();
}
uint32 FPrimeNumberWorker::Run()
{
for (int i = 2; i < IterationsCount; i++)
{
if (UMathLibrary::CheckPrimeNumber(i))
{
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red,
FString::Printf(TEXT("%d"), i));
}
}
return 0;
}
void FPrimeNumberWorker::Stop()
{
FRunnable::Stop();
bShouldRun = false;
}
Alles anzeigen
Was immer jetzt in Run ausgeführt wird passiert auf einem eigenen Thread.
Erstellen und gleich starten kann ich den mit:
Und wieder löschen:
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.
das Problem ist, dass der Sequencer die Animationen loopen lässt, was ich dort nicht abstellen kann,
Ich glaube du musst unter "Max Loop Count" auf 0 stellen. Schon mal probiert?
Ist immer ein wenig irreführend. Bei Partikeln ist es zumindest auch bei vielen Funktionen so dass man den Loopcount auf 0 setzen muss damit es nur 1x passiert.
Bralligator jap, hab ich auf 0 gestellt bzw. ist von Anfang an auf 0, looped trotzdem. Warum auch immer.
Kriegst du es, oder irgend jemand hin, dass nicht immer die selber Animationen abgespielt werden, sondern halt der Zufall eine Auswahl an Animationen hat, die er abspielen kann?
Die Animation selber darf nicht "loop" aktiviert haben.
Es kann durch den Zufall natürlich schon sein, dass paar mal dieselbe Animation gespielt wird, wechselt dann aber sicher.