Estoy haciendo un tetris, las piezas son un prefab de 4 cubos agrupados en un GameObject. Antes de bajar o moverse, verifico que la posición a la que se quiere mover no hay nada, haciendo un for por cada hijo del GameObject. Todo funciona perfectamente, las cosas raras ocurren al rotar.
Cuando se hace la rotación, giro 90 grados el GameObject, es entonces cuando no funcionan bien las detecciones,
por ejemplo una pieza sin rotar, que no puede desplazarse a la izquierda,al rotar, desde el punto de origen del GameObject, no tiene ningun bloque a la izquierda, con lo que podría moverse, pues no. Es como si ese bloque, que su transform es -1,0,0. Al buscar su posición sabe que esta a -1x del padre, y en vez de darme la posición real del hijo en el espacio, saca que esta a -1x y por eso detecta que no se puede mover hacia la izquierda, cuando en verdad el bloque si tiene espacio.
No se si me he explicado bien, pero no se como arreglar esto.
A ver a ver... Estas programando un tetris por matrices o por físicas? Porque sería un buen comienzo jajajaja como rotas el objeto? Como están hechos los emparentados? Y que es lo que realmente pasa porque no lo he entendido muy bien jajajaja
por matrices.
Por ejemplo el movimiento automático hacia abajo, mira todos los bloques que forman el Gameobject, y compara su posicion, con el indice del array, para ver si hay algo.
private bool Colision(int modX,int modY)
{
for(int n=0;n<piezaActiva.childCount;n++)
{
if(grid[(int)piezaActiva.GetChild(n).transform.position.x+modX, (int)piezaActiva.GetChild(n).transform.position.y+modY]!=null)
{
return false;
}
}
return true;
}
Si no hay nada, sigue bajando. El problema viene, que roto el GameObject padre, que contiene 4 GO hijos, que son los bloques de la ficha. Entonces el objeto se para por encima de donde debería, Por ejemplo para bajar llamo a la función con colision(0,-1), asi mira que debajo de cada bloque no haya nada, pues con 90º de rotacion, y aunque debajo no haya nada, la ficha se para.
Mmm lo haces por matrices? Entonces las posiciones las mueves con otro método? No veo fallo en este... Entre las horas y que estoy con el movil... Igual se me escapa algo jajajaja de todas formas... Me gustaría saber como mueves el go de la ficha o como las rotas, porque como te he dicho no parece que esté mal este método ya que simplemente pues mira un offset determinado...
para mover simplemente,
piezaActiva.position += new Vector3(0f, -1f, 0f);
actualizo la matriz cuando la pieza ya no se puede mover y sale la otra.
para rotar, sin mas
piezaActiva.transform.Rotate(0f, 0f, 90f);
he probado ha rotar en self y a rotar en world, y nada lo mismo. La ficha hace cosas rarisimas siempre que esta rotada. la misma ficha rotada, se puede quedar a 1 o varios espacios de donde tendria que estar, y la misma ficha rotada 360º o sin rotar, va normal. Lo que roto es el GameObject padre. Tan simple joder y no se que mierdas pasa.
A ver... Si utilizas un rotate... La rotación es automática... Osea que... Porque no mueves las piezas de la ficha en vez de rotar la ficha entera? Yo siempre que puedo intento evitar las rotaciones... Si no... Mira cuando compruebas la posición de abajo, antes de moverlo? Yo imagino que mientras no dé true la colisión seguirás bajando, pero tengo una idea... Puede que al girar la pieza... La diagonal mas larga de la pieza haga que ese ultimo punto -1 en y de true en colisión y deje de bajar... Puede ser? Espero ser de ayuda jajaja
si, una solución seria mover todas las fichas, pero seria mas largo y tedioso. porque tiene que mirar que ficha es para reordenar los bloques, y dependiendo en que rotación este. Tambien me jode no saber porque pasa esto.
El misterio se vuelve mas raro, sigo haciendo pruebas, y rotando y demas, como digo hay problemas con el tema paredes y el suelo, pero no con las fichas, las fichas al posarse, guardo sus transforms en el array, y la siguiente pieza aunque la rote, si que detecta PERFECTAMENTE todas las fichas de alrededor, da igual que las pongas en las posiciones mas raras, funciona perfectamente, osea que no se porque, sin rotacion, no existe un Transform en el array, en la cordenada 1 del eje Y, pero si roto el gameObject, encuentra un Transform en la cordenada 1 del eje Y, aunque no haya pasado nada entre los 2 procesos. Es magia...
Por cierto, muchas gracias por tus respuestas.
EDITO: despues de rotar, hago un for, por todo el array y saco las posiciones donde hay algo, para testear y esta todo correcto, hay transforms en los bordes, asi que no se porque cojones detecta uno donde no lo hay...
No me has respondido a lo de cuando compruebas los offsets jajajaja primero rotas y luego compruebas? Prueba a hacer debug.log cada vez que compruebe la posición de abajo y a ver que pasa... Compruebas si la pieza va chocar antes de rotarla? Hay tantas preguntas.. Jajaja
EDIT: recalco que puede que al rotar compruebe si puede bajar y entonces va a dar colisión, afirmame esto por favor que me tienes en ascuas jajja
Mmm entonces es muy raro... Y por que las colisiones no las miras por el array? Si sabes que eso no te va a dar problemas... Sabiendo donde hay fichas... No veo complicado ir checkeando en el array (no tanto como rotar la ficha moviendo los cubos jajajaja)
Cita de: edgar_94_ date=1483916789No me has respondido a lo de cuando compruebas los offsets jajajaja primero rotas y luego compruebas? Prueba a hacer debug.log cada vez que compruebe la posición de abajo y a ver que pasa... Compruebas si la pieza va chocar antes de rotarla? Hay tantas preguntas.. Jajaja
EDIT: recalco que puede que al rotar compruebe si puede bajar y entonces va a dar colisión, afirmame esto por favor que me tienes en ascuas jajja
Mmm entonces es muy raro... Y por que las colisiones no las miras por el array? Si sabes que eso no te va a dar problemas... Sabiendo donde hay fichas... No veo complicado ir checkeando en el array (no tanto como rotar la ficha moviendo los cubos jajajaja)
Sigo mañana investigando, las colisiones las miro por el array, como puse más arriba, comprueba que tiene alrededor tomando la posición de las piezas, si hay algo, la posición es el índice del array.
Lo muevo todo con corutinas, una que cada X tiempo ha bajando la pieza, antes de bajarla comprueba si puede bajar. Otra corutina responde al input y dependiendo hacia que lado,mira si puede moverse hacia allí y luego se mueve.
Justo después de rotar no comprueba, pero ya te digo que comprueba antes del siguiente frame.
Hola, la verdad por matrices no lo he analizado bastante, lo que yo haria serian usar raycasting y de paso generar las piezas agrupando cuadrados.
haria uno o varios rays (dependiendo de la pieza) hacia abajo, independientemente de la rotacion, el distance del raycast me determina una distancia maxima de desplazamiento (simple deteccion de movimiento en viejos platformers 2D), antes de realizar el movimiento chequeo que haya lugar, si lo hay lo muevo. Por supuesto en este tipo de juegos las dimensiones son sagradas, es decir que me voy a mover por lo menos por multiplos de unidad (por ejemplo), es decir que si la distance del raycast no me da mas que la unidad el bloque se queda bloqueado.
El truco es que cada vez que rotas, dependiendo de la pieza los rays se "renuevan":
El pivot esta justo en el centro ya que al rotar genero nuevos rays, solo por motivos de control.
En esta pieza que es de 3x2 los rays empiezan siendo 3 al rotar son dos y la colision seria algo asi:
Si el maximo desplazamiento es 1, es la ultima bajadita, si es mayor puede seguir bajando.
La longitud de los rays puede ser mucho mas grande, ya que si apretas cierto boton o tecla deberia bajar de un movimiento la pieza
En fin me gustaria pensarlo un poco mas la verdad no lo he planificado demasiado
Saludos
Están ya agrupadas, como he dicho mas arriba, el problema del raycasting es que es mas lento, por eso lo de la matriz.
Bueno he cambiado la forma en la que detecta paredes. Basicamente diciendole que no puede ir mas alla del 0, del 11 (en X) y no menos de 0 en Y. Ahora funciona perfectamente.
Testeando parecía que iba bien. Rotan las piezas y se mueve correcto, se detectan las colisiones y demás, Pero hay veces que entre piezas hay huevo libre y la pieza se queda por encima, detecta que tiene algo debajo, y se queda ahí. He probado a redondear las posiciones después de un movimiento, pero nada,sigue igual.
voy a probar a rehacer todo, sin usar las corutinas.
En un movil podes meter cientos de raycast que no tenes cambios de performance practicamente, es mas, en un tetris podes hacer el raycast cada medio segundo no es necesario hacerlo en todo cuadro
Cita de: lightbug date=1483967598En un movil podes meter cientos de raycast que no tenes cambios de performance practicamente, es mas, en un tetris podes hacer el raycast cada medio segundo no es necesario hacerlo en todo cuadro
En este caso estoy con biztor, en un tetris no es necesario usar raycasting ni físicas, por eso en el primer post le pregunté por ello. Lo bueno de las físicas es que ves en todo momento lo que pasa (por lo general) pero es un agujero de bugs del que si es posible hay que evitar jajaja y por otro lado lo bueno de las matrices es que es matemático y lo controlas tu, lo que pasa es que hay que tener en cuenta que no es lo mismo lo que pasa en la matriz y lo que se muestra en pantalla
Cita de: edgar_94_ date=1483967819En este caso estoy con biztor, en un tetris no es necesario usar raycasting ni físicas, por eso en el primer post le pregunté por ello. Lo bueno de las físicas es que ves en todo momento lo que pasa (por lo general) pero es un agujero de bugs del que si es posible hay que evitar jajaja y por otro lado lo bueno de las matrices es que es matemático y lo controlas tu, lo que pasa es que hay que tener en cuenta que no es lo mismo lo que pasa en la matriz y lo que se muestra en pantalla
Es cierto, aunque con los rays tampoco estas usando fisicas a full, osea, moves tus piezas directamente con transforms de ahi el control, lo unico haciendo raycast para saber cuanto, es decir como funciona un charactercontroller. Un ejemplo seria si queres un movimiento suavizado, con matrices no lo podes hacer, no seria el caso del tetris clasico clasico.
Cita de: lightbug date=1483968272Es cierto, aunque con los rays tampoco estas usando fisicas a full, osea, moves tus piezas directamente con transforms de ahi el control, lo unico haciendo raycast para saber cuanto, es decir como funciona un charactercontroller. Un ejemplo seria si queres un movimiento suavizado, con matrices no lo podes hacer, no seria el caso del tetris clasico clasico.
Con matrices también podrías hacer un movimiento suavizado y fluido, pero tienes que separar la lógica del movimiento y la lógica de la posición (matriz) pero bueno, todo es posible con todos los métodos y de toda forma, solo que en unas hay que tener mas cuidado que en otras kajajaja
Cita de: edgar_94_ date=1483968407Con matrices también podrías hacer un movimiento suavizado y fluido, pero tienes que separar la lógica del movimiento y la lógica de la posición (matriz) pero bueno, todo es posible con todos los métodos y de toda forma, solo que en unas hay que tener mas cuidado que en otras kajajaja
Si tenes razon, no lo habia pensado asi. Ahora, volviendo a las matrices es facil rotar una pieza de cualquier dimension, esta clase de juegos se resuelve mas via codigo que trabajando directamente con gameObjects (rotandolos y detectando colisiones), como los tipicos ejemplos de juegos de terminal en C.
Bueno, sin usar Corutinas, me sigue haciendo las mismas cosas raras, esto es desesperante.
Cita de: biztor date=1483971824Bueno, sin usar Corutinas, me sigue haciendo las mismas cosas raras, esto es desesperante.
Es que no se que lógica vas a utilizar, ahora estoy en el pc y te puedo ayudar mejor...
La lógica que yo tendría sería la siguiente:
El movimiento lo haría por un lado y las posiciones las iría guardando en la matriz... ¿Cómo? Pues antes de moverse hacia la posición x/y vamos a ver si hay alguna ficha ocupando ese espacio en nuestra matriz, ¿la hay? entonces la ficha no puede bajar o no puede moverse, ¿No la hay? Entonces la ficha puede bajar o moverse y actualizamos movimiento... se que esto en Unity suena un poco prehistórico, pero es como se ha programado toda la vida xD
Y todavía estamos hablando de movimiento simple... verás cuando quieras meter un cuadrado de la ficha en un agujero... xD
podría hacer todo el movimiento y detectar colisiones en la matriz, rellenando la matriz con los espacios de la ficha, y después de comprobar todo, que se mueva la ficha física en unity. Pero es que joder, no se porque da tantos problemas si es que es lo mismo, la ficha esta en posiciones absolutas, y solo se mueve 1 unidad de cada vez... Lo haré de noche y os digo, pero algo raro pasa cuando se rota. Por webos tiene que funcionar haciendo toda la lógica en matriz, porque es matematica pura.
Cita de: biztor date=1483973041podría hacer todo el movimiento y detectar colisiones en la matriz, rellenando la matriz con los espacios de la ficha, y después de comprobar todo, que se mueva la ficha física en unity. Pero es que joder, no se porque da tantos problemas si es que es lo mismo, la ficha esta en posiciones absolutas, y solo se mueve 1 unidad de cada vez... Lo haré de noche y os digo, pero algo raro pasa cuando se rota. Por webos tiene que funcionar haciendo toda la lógica en matriz, porque es matematica pura.
exacto, si lo haces así tiene que funcionar si o si. Estoy expectante a tus respuestas xD
Cita de: biztor date=1483973041podría hacer todo el movimiento y detectar colisiones en la matriz, rellenando la matriz con los espacios de la ficha, y después de comprobar todo, que se mueva la ficha física en unity. Pero es que joder, no se porque da tantos problemas si es que es lo mismo, la ficha esta en posiciones absolutas, y solo se mueve 1 unidad de cada vez... Lo haré de noche y os digo, pero algo raro pasa cuando se rota. Por webos tiene que funcionar haciendo toda la lógica en matriz, porque es matematica pura.
claro, esa es la idea de usar matrices en primer lugar, por eso decia que se resuelve todo en el mismo codigo.
Si lo haces con matrices (creo que es la mejor opción) lo importante es que tengas claro qué bloque utilizas como centro del objeto. O sea, al rotar a la derecha creo que tiene que haber un bloque que no se mueva mientras que el resto tienen que 'girar' 90 grados a la derecha.
Cada tipo de pieza estaría formado por un conjunto de varios Vector2, el origen en (0,0) más unos cuantos offsets. Viendo como se comportan las coordenadas al ir girando a la derecha creo que no sería muy complicado automatizar el cálculo para que, partiendo de cualquier tipo de pieza base y sabiendo en qué punto de la matriz está el origen, obtener dónde estarán el resto de bloques al girar la pieza.
(//<fileStore.core_Attachment>/monthly_2017_01/estoyeneltrabajoperdiendoeltiempo.png.97ba9224063bfc9d6836784dd13d18e5.png)
Cita de: musaranya date=1483981805Si lo haces con matrices (creo que es la mejor opción) lo importante es que tengas claro qué bloque utilizas como centro del objeto. O sea, al rotar a la derecha creo que tiene que haber un bloque que no se mueva mientras que el resto tienen que 'girar' 90 grados a la derecha.
Cada tipo de pieza estaría formado por un conjunto de varios Vector2, el origen en (0,0) más unos cuantos offsets. Viendo como se comportan las coordenadas al ir girando a la derecha creo que no sería muy complicado automatizar el cálculo para que, partiendo de cualquier tipo de pieza base y sabiendo en qué punto de la matriz está el origen, obtener dónde estarán el resto de bloques al girar la pieza.
Muchas gracias, ya llegue a casa, a ello me pongo.
Cita de: musaranya date=1483981805Si lo haces con matrices (creo que es la mejor opción) lo importante es que tengas claro qué bloque utilizas como centro del objeto. O sea, al rotar a la derecha creo que tiene que haber un bloque que no se mueva mientras que el resto tienen que 'girar' 90 grados a la derecha.
Cada tipo de pieza estaría formado por un conjunto de varios Vector2, el origen en (0,0) más unos cuantos offsets. Viendo como se comportan las coordenadas al ir girando a la derecha creo que no sería muy complicado automatizar el cálculo para que, partiendo de cualquier tipo de pieza base y sabiendo en qué punto de la matriz está el origen, obtener dónde estarán el resto de bloques al girar la pieza.
Explicacion perfecta para rotar ;) el asunto está en que le salen errores a la hora de comprobar si puede mover la ficha... Y creo que el problema que tendría ahora con las colisiones... es que si el cuadrado de la ficha que se encuentra arriba lo comprueba igual que el resto, no le dejará bajar porque abajo tiene un cuadrado ocupado (de la misma ficha) y ahora mismo no se me ocurren formas de evitarlo... quizás utilizar la Y más baja para filtrar y que no compruebe los cuadrados mas altos... algo asi se me ocurre, pero a estas horas ya no soy persona xD
no, voy hacer como antes, ficha activa no se registra en grid hasta que se inmoviliza, así se soluciona las comprobaciones. lo que voy hacer es hacer el movimiento y la rotacion asignando las posiciones directamente a las transforms de las partes de la ficha.
Para rotar, creía que tendría que ver que ficha era para programar la rotación, pero como ha puesto el compañero se puede hacer una formula para todas, que ya tengo sacado, se redistribuyen los bloques a sus posiciones esperadas y listo. Espero que funcione.
Esto me pasa por llevar tantos meses sin hacer nada. La poca costumbre ...
Tambien hay otra solucion, los bloques que se mueven, son 1s en la matriz, los bloques vacios son 0s y los bloques posicionados -1s... valen cualquier otros numeros xD pero bueno, sería comprobar si en los bloques de abajos se encuentra algun -1 o así ;P
No es tanto problema el comprobar las colisiones, vos tenes un grid de n x m que es el escenario completo, 0's vacios 1's llenos (o true y false como quieras) y de la figura actual podes tener tu 1 local (por asi decirlo, distinto a los 1's estaticos del nivel) asi cuando rotas y/o desplazas la pieza chequeas si se sobrepone a un 1 de la matriz de n x m si lo hace no lo bajas, corres o rotas cualquiera sea el caso.
lo que tengo es una matriz de transforms, para luego al hacer linea, solo tengo que mirar las lineas que se tienen que borrar y destruir el transform asignado.
Bueno parece que ya funciona!!!! , bufff. Algún bug o algo debe pasar usando rotate al Gameobject padre. Calculando donde tienen que estar los bloques, y asignándolos a esa posición, hace que funcione correctamente. El padre solo sirve de contenedor, y se queda en un sitio fijo, cuando la ficha ya no se mueve, lo destruyo, y las fichas pasan a estar en otro grupo, donde guardo todas las fichas colocadas.
Todavía queda, a ver si lo acabo mañana o pasado. Muchas gracias a todos, seguramente tendré que preguntar algo mas. Me ha servido de mucho, lo que habéis planteado aquí.
El problema que veo con el método que propuse es el tipo de pieza 'cuadrado'. Si no recuerdo mal en tetris el cuadrado no tiene que rotar, pero si lo hacemos como yo decía (tomando un bloque como origen y girando los demás) entonces el cuadrado rotará. No sé si es el comportamiento deseado o es que en tipos de pieza totalmente simétricos hay que desactivar la rotación
EDIT: disculpar no había leído los comentarios de la página 2