Was ist der Unterschied zwischen UnityEngine.Random und System.Random?

24

Was ist der Unterschied zwischen diesem

int randomNumber = UnityEngine.Random.Range(0, 10);

und das

// on top of the class
private System.Random _rnd = new System.Random();

// inside a methode of the same class
int randomNumber = _rnd.Next(0, 10);

Ich weiß, System.Randommuss immer auf der Oberseite Ihrer Klasse initialisiert werden, was vorbei ist, UnityEngine.Randomwird nicht benötigt. Ich weiß auch, dass System.Randomdas mit einer internen "Uhr" funktioniert und die "Zufallszahl" darauf basiert.

Meine Frage ist nun, gibt es einen anderen Unterschied zwischen UnityEngine.Randomund System.Randomund welcher Code ist besser für ein Unity-Projekt zu verwenden?

H. Pauwelyn
quelle

Antworten:

23

Der wohl wichtigste Unterschied ist, dass Unity Random.Rangeetwas einfacher zu bedienen ist, da es statisch ist. Die C # -Basisklassenbibliothek System.Randombietet Ihnen jedoch mehr Kontrolle und Isolation.

Es ist möglich, dass sie auch andere Implementierungen unter der Haube verwenden (obwohl ich vermute, dass die von Unity Randomnur in Bezug auf das System implementiert ist Random), aber das ist wahrscheinlich kein nennenswertes Problem. Grundsätzlich handelt es sich bei beiden wahrscheinlich um die gleiche Art von Zufallszahlengenerator: einen Pseudozufallsgenerator, der auf der Iteration einer durch einen Startwert definierten Sequenz basiert.

Das Kontrollproblem ist relevanter, da Sie in einigen Kontexten möglicherweise verschiedene Zufallsströme für verschiedene Dinge verwenden möchten. Beispielsweise möchten Sie in einem Netzwerkkontext mit schrittweisen Sperren möglicherweise den Startwert für die Generierung zufälliger Ereignisse mit Auswirkungen auf das Spiel für alle Spieler im Spiel korrigieren, aber Sie interessieren sich möglicherweise nicht so sehr für den reinen Zufallszahlenstrom visuelle Ereignisse und können ermöglichen, dass dieser Stream auf eine traditionellere Weise erzeugt wird (z. B. mit der Systemverfügbarkeit beim Start des Spiels).

Wenn Sie Zufallszahlen in mehreren Threads generieren möchten, möchten Sie möglicherweise für jeden Thread unterschiedliche zufällige Objekte verwenden, um Wettlaufsituationen zu vermeiden. Dies kann vorkommen, wenn Ihre Spielelogik über viele Threads läuft und Sie beispielsweise auch über ein Gameplay-Wiedergabesystem verfügen.

Am Ende ist es nicht unbedingt besser , das eine oder andere zu verwenden, sondern es gibt Vor- und Nachteile. Verwenden Sie eine Instanz von, wenn Sie die Folge von Zahlen von anderen potenziellen zufälligen Folgen isolieren müssen, die möglicherweise auftreten, oder wenn Sie eine lokalisierte Kontrolle über den Startpunkt der Folge benötigen System.Random. Wenn Sie nur einen schnell und schmutzig zufälligen Wert für einen Wegwerfgebrauch oder ein anderes nicht wirkungsvolles Szenario benötigen, Randomist Unitys vereinfacht wahrscheinlich in Ordnung.

Josh
quelle
3
Einige Spiele speichern den Startwert, wenn der Spieler das Spiel speichert. Auf diese Weise führen dieselben Aktionen zu denselben Konsequenzen. Es wird davon abgehalten, zu scummen, und wenn Sie zu einem späteren Zeitpunkt vergessen haben, zu speichern, können Sie einfach dorthin zurückkehren, wo Sie zuvor waren. Das letzte XCOM hat das getan.
GregRos
3
@GregRos Gute Anmerkung, aber es kann eine andere Art von Save-Scumming einführen, wie in diesem Artikel beschrieben. Anstatt den gleichen Zug zu wiederholen, bis ein Erfolg erzielt wurde, probiert der Spieler verschiedene Zugsequenzen aus, bis die Züge, die ihn am meisten interessieren, das Land betreffen bei erfolgreichen Würfen in der vorgegebenen Reihenfolge. Es hat sich herausgestellt, dass es in jedem System Möglichkeiten gibt, mit saves zu sparen. Scummers Gonna Scum, daher ist es manchmal sinnvoll, mit dem Flow zu arbeiten, wie es XCOM getan hat .
DMGregory
10

UnityEngine.Random bietet einige benutzerfreundliche Vorteile:

  • Statisch / global zugänglich - Sie müssen keine Instanz für jedes Objekt oder System erstellen, für das Zufälligkeit erforderlich ist. Die meisten oder alle Ihrer Skripte können diese Ressource gemeinsam nutzen.

  • Praktische Methoden - Sie können Random.Range (), Random.insideUnitSphere, Random.rotationUniform, Random.ColorHSV () verwenden, um gut verteilte Zufallswerte verschiedener nützlicher Typen zu erhalten, ohne Ihre eigenen mathematischen Berechnungen ausführen zu müssen.

(Ich habe keine Bestätigung darüber gefunden, ob UnityEngine.Random plattformübergreifende Konsistenzgarantien bietet, die sich von der Mono-Implementierung von System.Random unterscheiden - sie können unter der Haube identisch sein oder nicht)

Sie können natürlich Ihre eigene Klasse erstellen, die dazu System.Random (oder eine andere Bibliothek oder Ihr eigenes PRNG) verwendet, aber das Schöne daran ist, dass Sie es nicht brauchen - die Implementierung von Unity soll Ihnen eine gute Basis für das Programm bieten zufälliges Verhalten aus der Box.

Es gibt jedoch Fälle, in denen Sie andere Zufallsquellen verwenden möchten:

  • Wenn Sie mehrere Threads verwenden, sollte jeder Thread eine eigene Quelle für Pseudozufälligkeiten haben, um Konflikte zu vermeiden (UnityEngine.Random ist nur für den Haupt-Thread verfügbar).

  • Wenn Sie eine deterministische Pseudozufallssequenz benötigen (z. B. für einen Startpegelgenerator), möchten Sie wahrscheinlich, dass dieses System über eine eigene Pseudozufallsquelle verfügt, auf die kein anderes Skript zugreifen kann, sodass Unterschiede in der Ausführungsreihenfolge dies nicht bewirken Überspringen Sie Zahlen und brechen Sie den Determinismus, auf den Sie sich verlassen haben. Weitere Informationen finden Sie in einem großartigen Beitrag im Unity-Blog über gesetzte Zufallszahlen .

  • Wenn Sie kryptografisch starke Zufälligkeiten für Sicherheit, Glücksspiele oder das Generieren eindeutiger IDs benötigen, sollten Sie zu diesem Zweck spezielle Bibliotheken verwenden. Weder UnityEngine.Random noch System.Random bieten ausreichende Qualitätsgarantien.

DMGregory
quelle
Hoppla, entschuldige mich bei JoshPetrie und Jon - ich habe eine Weile gebraucht, um das auf dem Handy zu tippen, also habe ich deine Antworten erst gesehen, als ich sie gepostet hatte. Sieht so aus, als hätten wir alle einen ähnlichen Weg zurückgelegt.
DMGregory
Informationen zur Crypto-Grade-Zufälligkeit finden Sie unter RNGCryptoServiceProvider. Beachten Sie jedoch, dass dies sehr langsam ist und von allen entfernten .NET-Plattformen von Unity ausgeschlossen wird.
McGuireV10
6

UnityEngine.Random ist statisch. Wenn Sie mehrere Instanzen eines Zufallszahlengenerators erstellen möchten, sollten Sie System.Random verwenden.

Es gibt keine Möglichkeit, den Quellcode für die Unity-Implementierung nachzuschlagen . Microsoft stellt jedoch den Quellcode für System.Random bereit .

jgallant
quelle
3
Nicht, dass die Quelle von Microsoft nicht diejenige ist, die von Unity verwendet wird. Sie sollten sich stattdessen die Mono-Quelle ansehen.
Arturo Torres Sánchez