Saludos!
Lo sé, y en el fondo sabes lo que faltan tus juegos de cartas o juegos tres en uno. Sistemas de sigilo!
Y, por supuesto, cualquier sistema de sigilo que se respete debería poder tener en cuenta la iluminación del entorno que rodea al jugador. Me sorprendió desenterrar el tema y encontrar una cantidad anormalmente pequeña de información. Por lo tanto, me apresuro a compartir los frutos.
Hoy no desarrollaremos un sistema completo de sigilo para el jugador, consideraremos puramente interacciones con la iluminación.
Método 1: colisionadores
Una forma simple y no muy intensiva en recursos.
Agregamos un colisionador esférico a cada fuente de luz. Lo hacemos un disparador. Establecemos las dimensiones aproximadamente iguales al radio de luz.
El resto es tan claro como una sombra. Estamos escribiendo un script simple, donde en OnTriggerEnter () colocamos la activación del cálculo de la luz (para que las fuentes de luz no funcionen "inactivas" cuando el jugador no está cerca).
El cálculo de iluminación en sí estará ubicado en Actualización (). En esencia, este es el Physics.Raycast habitual (). Si golpea al jugador, el jugador está en la zona de luz. Si no cae, significa que el jugador está detrás de obstáculos y, por lo tanto, a la sombra.
También puede agregar aquí el cálculo de la distancia entre el jugador y la fuente de luz. Por lo tanto, para determinar la iluminación, utilizaremos un flotador simple, que variará según la distancia a las fuentes de luz. Y puedes usarlo donde tu corazón lo desee.
Ejemplo
En el punto 1, la iluminación está cerca del máximo. En el punto 2, la iluminación es mínima: hay un obstáculo entre la luz y el punto. En el punto 3, la iluminación es promedio. ¡Y eso no es todo! Puede agregar colisionadores de activación a varias "zonas de sombra" donde el jugador debe esconderse. En las mejores tradiciones de Manhunt. Del mismo modo, puede marcar las zonas brillantes con el colisionador, simulando, por ejemplo, la luz de un foco.
Ventajas:
- Fácil de personalizar luces puntuales.
- Bastante económico en términos de recursos, si no envía spam a las fuentes de luz.
Desventajas
- La luz puntual y la luz direccional están muy ajustadas. Si por primera vez es suficiente colocar el colisionador en el campo de luz (para aumentar la visibilidad del jugador en la entrada), entonces la segunda es un verdadero horror. Debes colocar colisionadores en cada sombra (para reducir la visibilidad del jugador en la entrada), o comprobar constantemente usando Physics.Raycast () entre el jugador y el "sol": se encuentra debajo de los rayos o en la sombra.
- Una gran cantidad de colisionadores abarrotan la escena, lo que complica la física.
- Se debe tener cuidado con las fuentes de luz que se cruzan.
- La luz dinámica (intensidad móvil o cambiante) debe agregarse por separado a través de scripts.
Método 2: RenderTexture
Que estamos haciendo aqui De hecho, obtenemos una "captura de pantalla" de la cámara, y no necesariamente de la cámara principal. Y luego analizamos el color de la captura de pantalla para descubrir cómo la luz brillante cae sobre el sujeto.
Para empezar, necesitamos un objeto del cual "leeremos" la luz. Cree una esfera o plano regular, hágalo pequeño (escala 0.1), colóquelo cerca del piso, hágalo blanco, retire el colisionador:
Agregue una cámara (asegúrese de eliminar el oyente de audio y verifique que la etiqueta MainCamera no valga la pena). Atadlo a nuestro objeto. Lo ponemos un poco más alto, lo dirigimos hacia abajo. Exponemos en la configuración no la pantalla principal. Hacerlo ortográfico es para tu gusto.
Al final, lo posicionamos de modo que mire nuestro objeto y solo a él.
Al final, configure la máscara de selección de las cámaras primaria y secundaria para que la primaria no muestre nuestros objetos "ligeros", mientras que las secundarias solo los ven, sin saturar nada más.
Y aquí comienza la diversión. Adjuntamos el guión a la cámara:
public Camera cam; // RenderTexture tex; Texture2D _tex; void Start () { // "". // , - . // Depth 0 - . tex = new RenderTexture (1, 1, 8); // RenderTexture "" , // , . _tex = new Texture2D (1, 1, TextureFormat.RGB24, false); } void Update () { // "" cam.targetTexture = tex; cam.Render (); // RenderTexture.active = tex; // Texture2D _tex.ReadPixels (new Rect (0, 0, 1, 1), 0, 0); _tex.Apply (); Color col = _tex.GetPixel (0, 0); float vis = (col.r + col.g + col.b) / 3; }
En la salida, obtenemos un vis de flotación, que, en esencia, es una representación numérica del nivel de iluminación incidente en nuestro objeto. Si la fuente está cerca - el objeto es blanco - vis es 1. Si está oscuro - el objeto es negro - vis es ~ 0.
No necesitamos hacer la operación anterior en cada cuadro, por lo que incorporamos un segundo temporizador pequeño:
float interval = 0; void Update () { interval += Time.deltaTime; if (interval < 1) return; interval = 0; // }
Luego, vinculamos todo nuestro sistema al jugador para que se mueva con él. ¡Y nuestra variable vis devuelve automáticamente la luz alrededor del jugador!
Este sistema se puede usar no solo junto con el reproductor. Puede colocarlo en cualquier lugar y a su gusto, creando una especie de sensores de luz. Como regla, hay formas más efectivas de implementarlos, pero ¿siempre es bueno tener alternativas?
Las ventajas son obvias, hablemos de las desventajas.
Desventajas
- Cada "detector de luz" (si hay más de uno) requiere una cámara separada.
- Texture2D.ReadPixels (): bueno, extremadamente lento. Incluso si lo hace una vez por segundo, y no todos los cuadros, incluso si divide las funciones de escritura y lectura de texturas en cuadros diferentes, todavía hay diseños a 40-110 ms.
- Este sistema no tiene en cuenta algunos casos raros. Por ejemplo, una linterna brilla sobre un personaje. El personaje está bien iluminado, pero la luz cae sobre él y detrás de él, y no hacia abajo, respectivamente, nuestro detector de luz muestra un bajo nivel de iluminación. Puedes resolver el problema, por ejemplo, colocando el detector no en el piso, sino al nivel del cofre del personaje. Luego, debe colocar dos cámaras en lados opuestos para leer la luz desde ambos lados. Lo que ralentizará el sistema a la mitad.