Jaka jest różnica między UnityEngine.Random a System.Random?

24

Jaka jest różnica między tym?

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

i to

// 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);

Wiem, że System.Randomzawsze należy zainicjować na szczycie klasy, co UnityEngine.Randomjest niepotrzebne. Wiem też, że System.Randomdziała z „zegarem” stażysty i na tym opiera się „losowy” numer.

Moje pytanie brzmi: czy jest jakaś inna różnica między, UnityEngine.Randoma System.Randomkod, który lepiej wykorzystać w projekcie Unity?

H. Pauwelyn
źródło

Odpowiedzi:

23

Prawdopodobnie najważniejszą różnicą jest to, że Unity Random.Rangejest nieco łatwiejszy w użyciu, ponieważ jest statyczny. Biblioteka klasy C # System.Randomzapewnia jednak większą kontrolę i izolację.

Możliwe, że używają również różnych implementacji pod maską (chociaż domyślam się, że Unity Randomjest właśnie zaimplementowane pod względem systemu Random), ale prawdopodobnie nie jest to znaczący problem. Zasadniczo oba są prawdopodobnie tym samym rodzajem generatora liczb losowych: pseudolosowym generatorem opartym na iteracji sekwencji określonej przez niektóre nasiona.

Problem kontroli jest bardziej odpowiedni, ponieważ w niektórych kontekstach możesz chcieć użyć różnych losowych strumieni do różnych rzeczy. Na przykład, w kontekście sieciowej fazy blokowania, możesz chcieć naprawić ziarno używane do generowania losowych zdarzeń mających wpływ na rozgrywkę u wszystkich graczy w grze, ale możesz nie przejmować się tak bardzo strumieniem liczb losowych używanych wyłącznie wydarzenia wizualne i mogą pozwolić na rozsiewanie tego strumienia w bardziej tradycyjny sposób (na przykład z czasem działania systemu przy uruchomieniu gry).

Podobnie, jeśli zamierzasz generować losowe liczby w wielu wątkach, możesz chcieć użyć różnych losowych obiektów dla każdego wątku, aby zapobiec warunkom wyścigu. Może się to zdarzyć, jeśli logika gry przebiega przez wiele wątków, a na przykład masz również system rozgrywki.

W końcu niekoniecznie lepiej jest używać jednego lub drugiego ogólnie, ale są plusy i minusy. Jeśli potrzebujesz odizolować sekwencję liczb od innych potencjalnych losowych sekwencji, które mogą się zdarzyć, lub gdy potrzebujesz zlokalizowanej kontroli nad ziarnem sekwencji, użyj instancji System.Random. Jeśli potrzebujesz tylko szybkiej i brudnej losowej wartości do użycia na wyrzuceniu lub w innym nie wpływającym na scenariusz scenariuszu, uproszczone Unity Randomjest prawdopodobnie w porządku.

Josh
źródło
3
Jedną rzeczą, jaką robią niektóre gry, jest zapisanie wartości początkowej, gdy gracz zapisuje grę. W ten sposób te same działania prowadzą do tych samych konsekwencji. To zniechęca do oszczędzania, a jeśli zapomniałeś zapisać w późniejszym czasie, możesz po prostu wrócić do miejsca, w którym byłeś wcześniej. Ostatni XCOM to zrobił.
GregRos
3
@GregRos Dobra uwaga, ale może wprowadzić inny rodzaj oszczędzania energii, jak opisano w tym artykule - w zasadzie zamiast ponawiać ten sam ruch, dopóki nie osiągnie sukcesu, gracz próbuje różnych sekwencji ruchów, aż do ruchów, na których mu zależy większość ziemi na udane rzuty w ustalonej kolejności. Okazuje się, że istnieją sposoby na zapisywanie w dowolnym systemie z zapisywaniem. Scummers Gonna Scum, więc czasem sensownie jest iść z prądem, tak jak to zrobiła XCOM .
DMGregory
10

UnityEngine.Random ma kilka zalet łatwości użycia:

  • Statyczny / globalnie dostępny - nie trzeba tworzyć instancji dla każdego obiektu lub systemu, który wymaga losowości. Większość lub wszystkie skrypty mogą udostępniać ten zasób.

  • Metody wygody - możesz użyć Random.Range (), Random.insideUnitSphere, Random.rotationUniform, Random.ColorHSV (), aby uzyskać ładnie rozłożone losowe wartości różnych przydatnych typów bez konieczności tworzenia własnej matematyki.

(Nie znalazłem żadnego potwierdzenia, czy UnityEngine.Random zapewnia jakiekolwiek gwarancje spójności między platformami inne niż implementacja Mono System.Random - mogą, ale nie muszą być takie same pod maską)

Możesz oczywiście zbudować własną klasę korzystającą z System.Random (lub innej biblioteki lub własnego PRNG), ale fajną rzeczą jest to, że nie musisz - implementacja Unity ma na celu dać ci dobrą podstawę do losowe zachowanie po wyjęciu z pudełka.

To powiedziawszy, są przypadki, w których będziesz chciał użyć innych źródeł losowości:

  • Jeśli używasz wielu wątków, każdy wątek powinien mieć własne źródło pseudolosowości, aby uniknąć rywalizacji (UnityEngine.Random jest dostępny tylko w głównym wątku)

  • Jeśli potrzebujesz deterministycznej sekwencji pseudolosowej (np. Dla generatora poziomu zalążkowego) prawdopodobnie będziesz chciał, aby ten system miał własne źródło pseudolosowości, do którego żaden inny skrypt nie może uzyskać dostępu, aby różnice w kolejności wykonywania nie powodowały pomiń liczby i przełam determinizm, na który liczyłeś. Aby uzyskać więcej informacji, na blogu Unity znajduje się świetny post o rozstawionych losowych liczbach .

  • jeśli potrzebujesz kryptograficznie silnej przypadkowości dla bezpieczeństwa, hazardu lub generowania unikalnych identyfikatorów, powinieneś w tym celu skorzystać ze specjalistycznych bibliotek. Ani UnityEngine.Random, ani System.Random nie zapewniają wystarczających gwarancji jakości.

DMGregory
źródło
Ups, przepraszam JoshPetrie i Jona - poświęciłem chwilę na napisanie tego na telefonie komórkowym, więc nie widziałem twoich odpowiedzi, dopóki go nie opublikowałem. Wygląda na to, że wszyscy zajmowaliśmy podobną ziemię.
DMGregory
Losowość klasy kryptograficznej można znaleźć w RNGCryptoServiceProvider, ale należy pamiętać, że jest ona bardzo wolna i że jest wykluczona ze wszystkich pozbawionych platformy platform .NET platformy Unity.
McGuireV10
6

UnityEngine.Random jest statyczny. Jeśli chcesz utworzyć wiele instancji generatora liczb losowych, możesz użyć System.Random.

Nie ma sposobu, aby wyszukać kod źródłowy dla implementacji Unity, jednak Microsoft zapewnia źródło dla System.Random .

jgallant
źródło
3
Nie to, że źródło Microsoftu nie jest tym, z którego korzysta Unity. Zamiast tego powinieneś spojrzeć na źródło Mono.
Arturo Torres Sánchez