Clasificación isométrica de profundidad para plataformas móviles

Lo que vas a crear

La clasificación en profundidad puede explicarse en términos sencillos como una forma de averiguar qué elemento está más cerca de la cámara y cuál está más lejos, determinando así el orden en el que deben organizarse para transmitir la profundidad correcta en la escena..

En este tutorial, profundizaremos en la clasificación en profundidad para los niveles isométricos a medida que intentemos agregar plataformas móviles. Este no es un tutorial para principiantes en teoría isométrica y no se trata del código. El objetivo es entender la lógica y la teoría en lugar de analizar el código. La herramienta de elección para el tutorial es Unity, y por lo tanto, la clasificación en profundidad esencialmente está cambiando el ordenando de los sprites involucrados. Para otros marcos, puede ser un cambio del orden z o la secuencia del orden de dibujo.

Para comenzar con la teoría isométrica, consulte esta serie de tutoriales. El código y la estructura de la escena siguen mi tutorial isométrico anterior. Consúltelos si encuentra el tutorial difícil de seguir ya que me centraré solo en la lógica en este tutorial.

1. Niveles sin movimiento

Si su nivel isométrico no tiene ningún elemento en movimiento o solo tiene algunos caracteres que caminan sobre el nivel, la clasificación en profundidad es sencilla. En tales casos, los caracteres que ocupan los azulejos isométricos serían más pequeños que los azulejos mismos y fácilmente pueden usar el mismo orden / profundidad de dibujo que el azulejo que ocupan.. 

Vamos a referirnos a niveles inmóviles como niveles estáticos. Hay algunas formas en que se pueden dibujar tales niveles para que se transmita la profundidad correcta. Normalmente, los datos de nivel serán una matriz bidimensional donde las filas y columnas corresponderán a las filas y columnas del nivel. 

Considere el siguiente nivel isométrico con solo dos filas y siete columnas.

Los números en las fichas indican su ordenando o la profundidad o el orden z, es decir, el orden en que deben dibujarse. En este método, estamos dibujando todas las columnas en la primera fila, comenzando con la primera columna con un ordenando de 1. 

Una vez que todas las columnas se dibujan en la primera fila, la columna más cercana a la cámara tiene un ordenando de 7, y nos dirigimos a la siguiente fila. Así que cualquier elemento en la segunda fila tendrá una mayor ordenando que cualquier elemento de la primera fila. 

Así es exactamente como deben organizarse los mosaicos para transmitir la profundidad correcta como un sprite con un valor más alto. ordenando se superpondrá sobre cualquier otro sprites con menor ordenando.

En cuanto al código, esto es solo una cuestión de recorrer las filas y columnas de la matriz de niveles y asignar ordenando secuencialmente en un orden creciente. No se rompería, incluso si intercambiamos filas y columnas, como se puede ver en la imagen de abajo..

Aquí dibujamos una columna completa antes de pasar a la siguiente fila. La percepción de la profundidad se mantiene intacta. Así que la lógica para un nivel estático es dibujar una fila completa o una columna completa y luego pasar a la siguiente mientras se asigna ordenando secuencialmente en un orden creciente.

Añadiendo altura

Si consideramos el nivel como un edificio, actualmente estamos dibujando la planta baja. Si necesitamos agregar un nuevo piso a nuestro edificio, todo lo que tenemos que hacer es esperar hasta que dibujemos toda la planta baja y seguir el mismo método para el siguiente piso.. 

Para la profundidad adecuada, esperamos hasta que se completó la fila completa antes de pasar a la siguiente fila, y de igual modo esperamos hasta que todas las filas se completen antes de pasar al siguiente piso. Entonces, para un nivel con solo una fila y dos pisos, se vería como la imagen de abajo.

Esencialmente, cualquier baldosa en el piso superior tendrá una mayor ordenando que cualquier baldosa en el piso inferior. En cuanto al código para agregar pisos más altos, solo necesitamos compensar el y El valor de las coordenadas de la pantalla para el azulejo, dependiendo de qué piso ocupa.

float floorHeight = tileSize / 2.2f; float currentFloorHeight = floorHeight * floorLevel; // tmpPos = GetScreenPointFromLevelIndices (i, j); tmpPos.y + = currentFloorHeight; tile.transform.position = tmpPos;

los pisoHeight valor indica la altura percibida de la imagen del bloque isométrico en mosaico, mientras que nivel del suelo Indica en qué piso se encuentra el azulejo..

2. Moviendo Azulejos en el Eje X

La clasificación en profundidad en un nivel isométrico estático no fue complicada, ¿verdad? Continuando, decidamos seguir el método de la primera fila, donde asignamos ordenando a la primera fila completamente y luego pasar a la siguiente. Consideremos nuestro primer mosaico o plataforma móvil que se mueve en un solo eje, el eje x. 

Cuando digo que el movimiento está en el eje x, debe darse cuenta de que estamos hablando del sistema de coordenadas cartesiano y no del sistema de coordenadas isométricas. Consideremos un nivel con solo una planta baja de tres filas y siete columnas. Consideremos también que la segunda fila solo tiene una única ficha, que es nuestra ficha móvil. El nivel se verá como la imagen de abajo..

El azulejo oscuro es nuestro azulejo móvil, y el ordenando se asignará será 8 ya que la primera fila tiene 7 fichas. Si la baldosa se mueve en el eje x cartesiano, entonces se moverá a lo largo de la zanja entre las dos filas. En todas las posiciones que pueda ocupar a lo largo de ese camino, los azulejos en la fila 1 tendrán una menor ordenando

Del mismo modo, todas las fichas en la fila 2 tendrán una mayor ordenando, independientemente de la posición del azulejo oscuro a lo largo de dicho camino. Así que a medida que seguimos un método de primera fila de asignación ordenando, No necesitamos hacer nada para el movimiento en el eje x. Ahora, eso fue fácil.

3. Moviendo Azulejos en el Eje Y

Los problemas comienzan a surgir cuando comenzamos a considerar el eje y. Consideremos un nivel en el que nuestra baldosa oscura se mueve a lo largo de una zanja rectangular, como se muestra a continuación. Puedes ver lo mismo en el Problema en movimiento Escena de la unidad en la fuente..

Usando nuestro primer enfoque de fila, podemos proporcionar un ordenando para nuestra baldosa móvil basada en la fila que actualmente ocupa. Cuando el mosaico está entre dos filas, se le asigna un ordenando basado en la fila de la que se está moviendo. En ese caso, no puede seguir el orden secuencial. ordenando en la fila en la que se está moviendo. Esto esencialmente rompe nuestro enfoque de clasificación de profundidad.

Clasificación en bloques

Para resolver esto, necesitamos dividir nuestro nivel en bloques diferentes, entre los que se encuentra el bloque problema, que se rompe bajo nuestro primer enfoque de fila, y el resto son bloques que pueden seguir el primer enfoque de fila sin romper. Considere la imagen de abajo para una mejor comprensión.

El bloque de mosaico 2x2 representado por el área azul es nuestro bloque problema. Todos los otros bloques pueden seguir la primera fila. No se deje confundir por la imagen, ya que muestra un nivel que ya está ordenado correctamente utilizando nuestro enfoque de bloque. El bloque azul consiste en las dos fichas de columna en las filas entre las que se mueve nuestra baldosa oscura y las baldosas inmediatamente a la izquierda.. 

Para resolver el problema de la profundidad del bloque problemático, podemos usar el primer enfoque de la columna solo para este bloque. Entonces, para los bloques verde, rosa y amarillo, usamos primero la fila, y para el bloque azul, usamos el primer enfoque de la columna. 

Tenga en cuenta que todavía tenemos que asignar secuencialmente ordenando. Primero el bloque verde, luego el bloque rosa a la izquierda, luego el bloque azul, ahora viene el bloque rosa a la derecha y finalmente el bloque amarillo. Rompemos el orden solo para cambiar a la primera aproximación de la columna mientras estamos en el bloque azul.

Alternativamente, también podemos considerar el bloque 2x2 a la derecha de la columna de mosaico en movimiento. (Lo interesante es que, en este caso, ni siquiera necesita cambiar de enfoque, ya que la ruptura de bloques ya resolvió nuestro problema). La solución se puede ver en acción en la BlockSort escena.

Esto se traduce en código como abajo.

vacío privado DepthSort () Vector2 movingTilePos = GetLevelIndicesFromScreenPoint (movingGO.transform.position); int blockColStart = (int) movingTilePos.y; int blockRowStart = (int) movingTilePos.x; profundidad int = 1; // ordenar filas antes del bloque para (int i = 0; i < blockRowStart; i++)  for (int j = 0; j < cols; j++)  depth=AssignDepth(i,j,depth);   //sort columns in same row before the block for (int i = blockRowStart; i < blockRowStart+2; i++)  for (int j = 0; j < blockColStart; j++)  depth=AssignDepth(i,j,depth);   //sort block for (int i = blockRowStart; i < blockRowStart+2; i++)  for (int j = blockColStart; j < blockColStart+2; j++)  if(movingTilePos.x==i&&movingTilePos.y==j) SpriteRenderer sr=movingGO.GetComponent(); sr.sortingOrder = depth; // asignar una nueva profundidad ++; // incrementar la profundidad else depth = AssignDepth (i, j, depth);  // ordenar las columnas en la misma fila después del bloque para (int i = blockRowStart; i < blockRowStart+2; i++)  for (int j = blockColStart+2; j < cols; j++)  depth=AssignDepth(i,j,depth);   //sort rows after block for (int i = blockRowStart+2; i < rows; i++)  for (int j = 0; j < cols; j++)  depth=AssignDepth(i,j,depth);   

4. Moviendo Azulejos en el Eje Z

Un movimiento en el eje z es un movimiento falso en un nivel isométrico. Esencialmente es solo movimiento en la pantalla y el eje. Para un nivel isométrico de un solo piso, no hay nada más que hacer para agregar movimiento en el eje z si ya ha realizado el método de clasificación de bloques descrito anteriormente. Puedes ver esto en acción en el SingleLayerWave Escena de la unidad, donde he agregado un movimiento de onda adicional en el eje z junto con el movimiento de la zanja lateral.

Movimiento Z en niveles con pisos múltiples

Agregar un piso adicional a su nivel es solo una cuestión de compensar la pantalla y la coordenada, como se explicó anteriormente. Si la baldosa no se mueve en el eje z, no hay necesidad de hacer nada especial para clasificar en profundidad. Podemos bloquear la planta baja con movimiento y luego aplicar la primera fila en cada planta sucesiva. Puedes ver esto en acción en el BlockSortWithHeight Escena de la unidad.

Un problema de profundidad muy similar surge cuando la baldosa comienza a moverse entre los pisos. Solo puede satisfacer el orden secuencial de un piso utilizando nuestro enfoque y rompería la clasificación en profundidad del otro piso. Necesitamos extender o modificar nuestra clasificación de bloques a tres dimensiones para tratar este problema de profundidad con pisos.

El problema esencialmente será solo los dos pisos entre los que se mueve la baldosa actualmente. Para todos los demás pisos, podemos mantener nuestro enfoque de clasificación actual. Las necesidades especiales se aplican solo a estos dos pisos, entre los cuales podemos determinar primero el piso inferior como abajo, donde tileZOffset es la cantidad de movimiento en el eje z para nuestra baldosa en movimiento.

float whichFloor = (tileZOffset / floorHeight); flotar más bajo = Mathf.Floor (whichFloor);

Esto significa que inferior y inferior + 1 Son los pisos los que necesitan un enfoque especial. El truco es asignar ordenando para ambos pisos juntos, como se muestra en el código a continuación. Esto corrige la secuencia para que los problemas de profundidad se solucionen.

si (piso == abajo) // necesitamos clasificar el piso inferior y el piso justo arriba de ellos juntos en una profundidad de profundidad = (piso * (filas * columnas)) + 1; int nextFloor = floor + 1; if (nextFloor> = totalFloors) nextFloor = floor; // ordenar filas antes del bloque para (int i = 0; i < blockRowStart; i++)  for (int j = 0; j < cols; j++)  depth=AssignDepth(i,j,depth,floor); depth=AssignDepth(i,j,depth,nextFloor);   //sort columns in same row before the block for (int i = blockRowStart; i < blockRowStart+2; i++)  for (int j = 0; j < blockColStart; j++)  depth=AssignDepth(i,j,depth,floor); depth=AssignDepth(i,j,depth,nextFloor);   //sort block for (int i = blockRowStart; i < blockRowStart+2; i++)  for (int j = blockColStart; j < blockColStart+2; j++)  if(movingTilePos.x==i&&movingTilePos.y==j) SpriteRenderer sr=movingGO.GetComponent(); sr.sortingOrder = profundidad; // asignar nueva profundidad profundidad ++; // incrementar profundidad else profundidad = Asignar Profundidad (i, j, profundidad, piso); depth = AssignDepth (i, j, depth, nextFloor);  // ordenar las columnas en la misma fila después del bloque para (int i = blockRowStart; i < blockRowStart+2; i++)  for (int j = blockColStart+2; j < cols; j++)  depth=AssignDepth(i,j,depth,floor); depth=AssignDepth(i,j,depth,nextFloor);   //sort rows after block for (int i = blockRowStart+2; i < rows; i++)  for (int j = 0; j < cols; j++)  depth=AssignDepth(i,j,depth,floor); depth=AssignDepth(i,j,depth,nextFloor);   

Esencialmente, estamos considerando dos pisos como un solo piso y haciendo una clasificación de bloques en ese solo piso. Echa un vistazo al código y la acción en la escena. BlockSortWithHeightMovement. Con este enfoque, nuestra baldosa ahora es libre de moverse en cualquiera de los dos ejes sin romper la profundidad de la escena, como se muestra a continuación.

Conclusión

La idea de este tutorial fue aclarar la lógica de los enfoques de clasificación por profundidad, y espero que hayan comprendido esto. Es evidente que estamos considerando niveles comparativamente simples con una sola pieza en movimiento. 

Tampoco hay pendientes, ya que incluir pendientes hubiera hecho que este sea un tutorial mucho más largo. Pero una vez que haya entendido la lógica de clasificación, puede intentar extender la lógica de pendiente bidimensional a la vista isométrica.

La unidad tiene una economía activa. Hay muchos otros productos que te ayudan a desarrollar tu proyecto. La naturaleza de la plataforma también lo convierte en una excelente opción desde la cual puede mejorar sus habilidades. En cualquier caso, puede ver lo que tenemos disponible en el mercado de Envato..