¿Cuál es la diferencia entre UnityEngine.Random y System.Random?

24

¿Cuál es la diferencia entre esto?

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

y esto

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

System.Randomque siempre debe inicializarse en la parte superior de su clase, lo que UnityEngine.Randomno es necesario. También sé que System.Randomfunciona con un "reloj" interno y el número "aleatorio" se basa en eso.

Mi pregunta ahora es ¿hay alguna otra diferencia entre UnityEngine.Randomy System.Randomy el código de bruja es mejor utilizar para un proyecto de la Unidad?

H. Pauwelyn
fuente

Respuestas:

23

Podría decirse que la diferencia más importante es que Unity Random.Rangees un poco más fácil de usar, ya que es estático. La biblioteca de clase base C # System.Random, sin embargo, le ofrece más control y aislamiento.

Es posible que también usen diferentes implementaciones ocultas (aunque supongo que Unity's Randomsolo se implementa en términos del sistema Random), pero eso probablemente no sea una preocupación notable. Básicamente, ambos son probablemente el mismo tipo de generador de números aleatorios: un generador pseudoaleatorio basado en iterar una secuencia definida por alguna semilla).

El problema de control es más relevante, porque en algunos contextos es posible que desee utilizar diferentes secuencias aleatorias para diferentes cosas. Por ejemplo, en un contexto de red de red de paso de bloqueo, es posible que desee corregir la semilla utilizada para generar eventos aleatorios que afecten el juego en todos los jugadores en el juego, pero es posible que no le importe tanto el flujo de números aleatorios utilizados puramente eventos visuales y puede permitir que esa transmisión se siembre de una manera más tradicional (con el tiempo de actividad del sistema en el lanzamiento del juego, por ejemplo).

Del mismo modo, si va a generar números aleatorios en varios subprocesos, es posible que desee utilizar distintos objetos aleatorios para cada subproceso para evitar condiciones de carrera. Esto puede surgir si la lógica de tu juego se encuentra en muchos hilos y también tienes un sistema de reproducción de juego, por ejemplo.

Al final, no es necesariamente mejor usar uno u otro en general, sino que hay ventajas y desventajas. Cuando necesite aislar la secuencia de números de otras posibles secuencias aleatorias que puedan estar sucediendo, o cuando necesite control localizado sobre la semilla de la secuencia, use una instancia de System.Random. Si solo necesita un valor aleatorio rápido y sucio para un uso desechable o algún otro escenario sin impacto, la simplificación de Unity Randomprobablemente esté bien.

Josh
fuente
3
Una cosa que hacen algunos juegos es guardar el valor inicial cuando el jugador guarda el juego. De esa manera, las mismas acciones conducen a las mismas consecuencias. Desalienta guardar escoria, y si olvidó guardar en un momento posterior, puede regresar a donde estaba antes. El último XCOM hizo eso.
GregRos
3
@GregRos Buena nota, pero puede introducir un tipo diferente de escoria de salvamento como se describe en este artículo : básicamente, en lugar de volver a intentar el mismo movimiento hasta que obtengan un éxito, el jugador intenta diferentes secuencias de movimientos hasta los movimientos que más les interesan. en tiradas exitosas en la secuencia predeterminada. Resulta que hay maneras de guardar savecum en cualquier sistema con guardar. Scummers Gonna Scum, así que a veces tiene sentido seguir la corriente como lo hizo XCOM .
DMGregory
10

UnityEngine.Random tiene algunas ventajas de facilidad de uso:

  • Estática / accesible a nivel mundial: no necesita crear una instancia para cada objeto o sistema que necesite aleatoriedad. La mayoría o todos sus scripts pueden compartir este recurso.

  • Métodos de conveniencia: puede usar Random.Range (), Random.insideUnitSphere, Random.rotationUniform, Random.ColorHSV () para obtener valores aleatorios bien distribuidos de varios tipos útiles sin necesidad de obtener sus propias matemáticas.

(No he encontrado ninguna confirmación sobre si UnityEngine.Random ofrece garantías de coherencia multiplataforma diferentes de la implementación Mono de System.Random: podrían ser o no iguales bajo el capó)

Por supuesto, puede crear su propia clase que use System.Random (u otra biblioteca, o su propio PRNG) para hacer esto, pero lo bueno es que no necesita hacerlo: la implementación de Unity está destinada a proporcionarle una buena base para comportamiento aleatorio fuera de la caja.

Dicho esto, hay casos en los que querrás usar otras fuentes de aleatoriedad:

  • Si está utilizando varios subprocesos, cada subproceso debe tener su propia fuente de pseudoaleatoriedad para evitar conflictos (UnityEngine.Random solo es accesible en el subproceso principal)

  • Si necesita una secuencia pseudoaleatoria determinista (por ejemplo, para un generador de nivel sembrado), es probable que desee que ese sistema tenga su propia fuente de pseudoaleatoriedad a la que ningún otro script pueda acceder, de modo que las diferencias en el orden de ejecución no lo hagan omita los números y rompa el determinismo con el que contaba. Para obtener más información, hay una gran publicación en el blog de Unity sobre números aleatorios sembrados .

  • Si necesita una aleatoriedad criptográficamente fuerte para la seguridad, el juego o la generación de ID únicos, debe usar bibliotecas especializadas para este propósito. Ni UnityEngine.Random ni System.Random ofrecen suficientes garantías de calidad.

DMGregory
fuente
Vaya, disculpas a JoshPetrie y Jon: me tomé un tiempo escribiendo esto en el móvil, así que no vi sus respuestas hasta que lo publiqué. Parece que todos hemos cubierto terreno similar.
DMGregory
Para aleatoriedad de grado criptográfico, consulte RNGCryptoServiceProvider, pero tenga en cuenta que es muy lento y que está excluido de todas las plataformas .NET despojadas de Unity.
McGuireV10
6

UnityEngine.Random es estático. Si desea crear múltiples instancias de un generador de números aleatorios, entonces debería usar System.Random.

No hay forma de buscar el código fuente para la Implementación de Unity, sin embargo, Microsoft proporciona la fuente de System.Random .

jgallant
fuente
3
No es que la fuente de Microsoft no sea la utilizada por Unity. Deberías mirar la fuente Mono en su lugar.
Arturo Torres Sánchez