Unity 3D C # – ¿Cambios entre mundos?

Digamos que quiero replicar Planeshifting de Legacy of Kain: Soul Reaver en Unity.

Hay 2 reinos: reino espectral y reino Material.

El reino espectral se basa en el reino Material, solo tiene la geometry distorsionada y ciertos objects se desvanecen / se vuelven no interactivos.

En Soul Reaver, se usa como medio para ir a áreas en las que normalmente no sería posible en Material (geometry distorsionante), para usar otras potencias (como atravesar rejas).

Mi pregunta es: ¿es posible implementar esto en Unity 3D? (Necesitaría la escena (nivel) o los objects para tener 2 estados de alguna manera que podría cambiar entre / distorsionar a time real.)

Absolutamente, hay varios enfoques que podrías usar.

  • Puedes usar una escena para cada uno. Esto implicaría una posible duplicación de trabajo, pero podría build cada escena a partir de prefabricados para minimizar eso.

    Esto causará que haya algún time de carga cuando cambie de un reino a otro, aunque puede eliminarlo con LoadSceneAsync() .

  • Podrías labelr todos los objects de cada reino con una label para ese reino, y usar GameObject.SetActive(bool active) para voltear todos los objects de un reino y volver a activar los objects de otro reino.

    Una vez más, esto significaría que tendrían que buildse dos versiones de todo, pero dependiendo de cuán combadas estén, esa podría ser la forma más fácil de hacerlo. Esto haría que el cambio entre reinos sea relativamente instantáneo.

  • Progamatic distorsiona los objects en la escena cuando cambias entre reinos. Este puede ser el mejor enfoque si el grado de distorsión no es extremo.

    Etiquete cada object de juego que necesitará modificarse, use FindGameObjectsWithTag(string tagname) para get una list de todos esos objects, itere sobre ellos y realice los cambios necesarios. Puede intercambiar sombreados / texturas o incluso mallas en cada object del juego al pasar de un modo a otro.

    Esto puede introducir una pequeña pausa en el juego dependiendo de la cantidad de manipulación que se tenga que hacer con cada object del juego. Podrías disfrazarlo fácilmente con algún tipo de efecto de transición.

Esto es una especie de extensión de la respuesta de @ jackmott, similar a sus sugerencias, pero diferente.

En lugar de utilizar GameObject.SetActive() para voltear los estados de todo en la escena, en su lugar, sugiero usar sombreadores, banderas de materiales y su propio método que señala objects como visibles o invisibles dependiendo del estado actual del renderizado. (Esto también está ligeramente relacionado con el punto 3, también lo hace programáticamente).

Los beneficios son que solo necesita crear su escena una vez, y los objects que solo son visibles en un "reino" no se renderizan inteligentemente cuando el jugador no se encuentra en ese reino.

Eche un vistazo a Camera#SetReplacementShader() . Al forzar a la camera principal a utilizar un sombreador diferente para representar cada object en la escena, puede cambiar entre el reino material (los objects usan sus propios sombreadores) y el reino espectral (los objects se representan utilizando un SpectralShader personalizado que necesitará crear ) que hará el cambio de color, borrosidad y distorsión de vértice.

No puedo encontrar mi captura de pantalla en este momento (en la computadora incorrecta), pero tengo algo similar configurado para mi propio proyecto en este momento. Me permite dibujar contornos de enemigos a través de las panetworkinges (si el jugador tiene esa habilidad activa), no dibujar enemigos que son invisibles (¡pero obtendrán contornos!), O dibujarlos como blobs sin iluminar (visibles a través de las panetworkinges). Utilizo el último para cosas como icons de notificación, por ejemplo, un rojo ! que se cierne sobre un punto objective.

El estado que está activo depende de qué camera está renderizando actualmente, qué banderas de attributes tiene y el enemigo que se está renderizando. Tuve que hacer un poco de hacking para que esto funcione, pero tengo un sistema de notificación de events que OnPreRender un evento durante OnPreRender (esto solo ocurre en el object al que está conectada la camera, no para cada object que se está procesando) para notificar cada object a punto de representar los detalles específicos de la representación que se está realizando (¿puede el jugador ver a través de las panetworkinges, la camera es un dispositivo de eliminación de visualización, y así sucesivamente)? Los objects que deberían ser invisibles apagan su renderizador, los objects que deberían volver a encenderlo, y un par de otros indicadores se voltean mediante Material#SetOverrideTag .

Las tags de Shader Pass son muy importantes cuando se trata de SetOverrideShader: cuando se ejecuta el shader reemplazado, se observan las tags del shader original. Si el shader reemplazado tiene la misma label con el mismo valor, se ejecuta el pase. Consulte Representación con sombreadores reemplazados .

Esta será una vía muy difícil de seguir, pero también será la que tendrá el mejor resultado con la mayor flexibilidad y el menor esfuerzo invertido en la creación de niveles. Y casi con security el método empleado por Legacy of Kain. La parte más difícil será crear el sombreador personalizado. La mía, para mis tres o cuatro efectos simples, tiene cientos de líneas de longitud (¡el pase de esquema solo es 165!)