Noticias

¡RECUERDA QUE SI ERES UN NUEVO USUARIO, DEBES PRESENTARTE PARA PODER PUBLICAR MENSAJES! | TENEMOS CANAL OFICIAL DE TELEGRAM: t.me/unity3dspain

Temas recientes

Mover un selector entre bloques colocados irregularmente

Iniciado por Whiter, Junio 06, 2019, 07:35:02 PM

Tema anterior - Siguiente tema
Buenas tardes, mi problema es el siguiente.
 
Estoy intentando encontrar la forma de mover un selector utilizando teclas (WASD) entre bloques colocados de forma irregular.
 

 
La idea es que si pulsas W, vaya al más cercano hacia arriba, al pulsar D al mas cercano hacia la derecha y así con el resto de teclas.

He mirado que se pueden crear grids, pero no he visto como utilizarlas con bloques separados.



Gracias de antemano.

Hay muchas maneras de solventar este "puzzle". Unas más complejas y otras más sencillas.
 
De entrada, esto es una matriz fija o pueden haber más columnas/filas?
 
Puede haber más de un objeto alrededor a distinta altura? Es decir, hay solo una posibilidad de objeto para los dos ejes o más de una?
 
 

Cita de: iRobb date=1559848663Hay muchas maneras de solventar este "puzzle". Unas más complejas y otras más sencillas.
   
   
      De entrada, esto es una matriz fija o pueden haber más columnas/filas?
   
   
      Puede haber más de un objeto alrededor a distinta altura? Es decir, hay solo una posibilidad de objeto para los dos ejes o más de una?
   
   
       
   


La idea es usarlo para un tower defense, por lo que dependiendo del mapa habrá más o menos columnas y filas, y colocadas de forma diferente.

El juego es en 2D, por lo que todos estarían a la misma altura.

Para sumar otra forma a lo que comentaron, podría ser simplemente crear esas conexiones midiendo las distancias entre todos los puntos, luego determinando si pertenecen a der, izq arriba o abajo, y finalmente quien tenga la menor distancia dentro de uno de estos grupos gana el lugar (esto para un item, hay que hacerlo para todos).
 

 
Las zonas las determinas mediante ángulos, si el ángulo signado entre Vector2.right y el punto de interés (naranja en la figura) ) fuera de α entonces:
 


  •    -45 < α  < 45 --> R


  •    45  < α  < 135 --> W


  •    135 < α  < 180 o -180 < α  < -135 ---> A


  •    -45 < α  < -135 --> S


Una vez que sabés a que zona pertenece tomás al menos distante. Podés optimizar un poco el tema del orden en el que hacés las cosas pero la idea es esa.

He probado a hacerlo, pero no funciona del todo bien. El código es el siguiente:
 
 
 
Primero meto en un array todos los bloques de la escena:
 

allTiles = GameObject.FindGameObjectsWithTag("A");

 
 
 
Luego, con un for los clasifico en 4 listas comparando sus posiciones x e y con el selector.
 

for (int t = 0; t < allTiles.Length; t++)
        {
            if (allTiles[t].transform.position.x > transform.position.x)
            {
                rightTiles.Add(allTiles[t]);
            }
            if (allTiles[t].transform.position.x < transform.position.x)
            {
                leftTiles.Add(allTiles[t]);
            }
            if (allTiles[t].transform.position.y > transform.position.y)
            {
                upTiles.Add(allTiles[t]);
            }
            if (allTiles[t].transform.position.y < transform.position.y)
            {
                downTiles.Add(allTiles[t]);
            }
        }

 
Por ultimo, busco el tile mas cercano de cada una de las listas para meterlo en una variable.

 
 

for (int i = 0; i < rightTiles.Count; i++)
            if (rightTiles[i].transform.position.x < minval)
            {
                if (rightTiles[i].transform.position.y < transform.position.y + 1 && rightTiles[i].transform.position.y > transform.position.y - 1)
                {
                    minval = rightTiles[i].transform.position.x;
                    lowestIndex = i;
                }
            }
        if(lowestIndex == -1)
        {
            minval = 1000000;
            //Más a la izquierda de todas. (Menor valor y de la lista izquierda)
            for (int i = 0; i < leftTiles.Count; i++)
                if (leftTiles[i].transform.position.x < minval)
                {
                    if (leftTiles[i].transform.position.y < transform.position.y + 1 && leftTiles[i].transform.position.y > transform.position.y - 1)
                    {
                        minval = leftTiles[i].transform.position.x;
                        lowestIndex = i;
                    }
                }
                rightTile = leftTiles[lowestIndex];
        }
        else rightTile = rightTiles[lowestIndex];
       
       
       
        minval = 1000000;
        lowestIndex = -1;
        for (int i = 0; i < leftTiles.Count; i++)
            if (leftTiles[i].transform.position.x < minval)
            {
                if (leftTiles[i].transform.position.y < transform.position.y + 1 && leftTiles[i].transform.position.y > transform.position.y - 1)
                {
                    minval = leftTiles[i].transform.position.x;
                    lowestIndex = i;
                }
            }
        if (lowestIndex == -1)
        {
            minval = -1000000;
            //Más a la derecha de todas. (Mayor valor y de la lista derecha)
            for (int i = 0; i < rightTiles.Count; i++)
                if (rightTiles[i].transform.position.x > minval)
                {
                    if (rightTiles[i].transform.position.y < transform.position.y + 1 && rightTiles[i].transform.position.y > transform.position.y - 1)
                    {
                        minval = rightTiles[i].transform.position.x;
                        lowestIndex = i;
                    }
                }
            leftTile = rightTiles[lowestIndex];
        }
        else leftTile = leftTiles[lowestIndex];
       
       
        minval = 1000000;
        lowestIndex = -1;
        for (int i = 0; i < upTiles.Count; i++)
            if (upTiles[i].transform.position.y < minval)
            {
                if (upTiles[i].transform.position.x < transform.position.x + 1 && upTiles[i].transform.position.x > transform.position.x - 1)
                {
                    minval = upTiles[i].transform.position.y;
                    lowestIndex = i;
                }
            }
        if (lowestIndex == -1)
        {
            minval = 1000000;
            //Más a la derecha de todas. (Mayor valor y de la lista derecha)
            for (int i = 0; i < downTiles.Count; i++)
                if (downTiles[i].transform.position.y < minval)
                {
                    if (downTiles[i].transform.position.x < transform.position.x + 1 && downTiles[i].transform.position.x > transform.position.x - 1)
                    {
                        minval = downTiles[i].transform.position.y;
                        lowestIndex = i;
                    }
                }
            upTile = downTiles[lowestIndex];
        }
        else upTile = upTiles[lowestIndex];
        #endregion
        #region DownTiles
        minval = 1000000;
        lowestIndex = -1;
        for (int i = 0; i < downTiles.Count; i++)
            if (downTiles[i].transform.position.y < minval)
            {
                if (downTiles[i].transform.position.x < transform.position.x + 1 && downTiles[i].transform.position.x > transform.position.x - 1)
                {
                    minval = downTiles[i].transform.position.y;
                    lowestIndex = i;
                }
            }
        if (lowestIndex == -1)
        {
            minval = -1000000;
            for (int i = 0; i < upTiles.Count; i++)
                if (upTiles[i].transform.position.y > minval)
                {
                    if (upTiles[i].transform.position.x < transform.position.x + 1 && upTiles[i].transform.position.x > transform.position.x - 1)
                    {
                        minval = upTiles[i].transform.position.y;
                        lowestIndex = i;
                    }
                }
            downTile = upTiles[lowestIndex];
        }
        else downTile = downTiles[lowestIndex];

 
Lo que hago es primero ver cual dentro de la lista tiene el valor mas pequeño en caso de arriba y derecha y el mas grande en caso de abajo e izquierda.

Luego, para que no coja un bloque que esta a la derecha pero muy arriba, le pongo que este como máximo una unidad por arriba o por abajo del eje contrario.
 
Y por ultimo, al pulsar WASD la posición se cambiara por la posición del bloque.

 
 

if (Input.GetKeyDown(KeyCode.W))
        {
            transform.position = upTile.transform.position;
            ClasifyTiles();
        }
        else if (Input.GetKeyDown(KeyCode.S))
        {
            transform.position = downTile.transform.position;
            ClasifyTiles();
        }
        else if (Input.GetKeyDown(KeyCode.D))
        {
            transform.position = rightTile.transform.position;
            ClasifyTiles();
        }
        else if (Input.GetKeyDown(KeyCode.A))
        {
            transform.position = leftTile.transform.position;
            ClasifyTiles();
        }

 
 
 
 
 
Al iniciar, y hacer el primer calculo, parece ir sin problemas.

Pero según vas moviéndote, empieza a dar errores de out of range, saltar a bloques que no debería saltar, o en vez de saltar al mas cercano, saltar al mas lejano.
 
 
 
 
 
He estado dándole muchas vueltas al código pero no he conseguido arreglarlo, agradecería la ayuda.

Etiquetas: