PDA

Ver la versión completa : Unity Plataforma con colisión solo desde arriba (de un solo sentido)



Estopero
22/06/2017, 08:25
Buenas!

Pues estoy experimentando con unity y me he encontrado con este asunto, he visto distintas soluciones por ahí pero me gustaría confirmar que no hay una forma built-in en unity para realizarlo.

El caso es que para un juego de plataformas 2.5D, necesito que algunas plataformas se puedan atravesar saltando desde abajo pero que el personaje al caer sobre ellas se mantenga.

En el modo 2D he visto que existe un componente muy chulo llamado Platform Effector 2D que te permite definir precisamente eso, decidir de qué lado de una plataforma existe colisión, sin embargo para 3D o 2.5D no veo que exista lo mismo, sabéis si existe algo similar?

Es posible usar componentes de 2D en un juego 2.5D que todo estará en Z=0 ? (O al menos eso creo xD)

Imagino que al final habrá que programarlo, pero si existe una solución más fina pues mejor!

Muchas gracias!

futu-block
22/06/2017, 21:18
creo que tengo entendido que 2.5D es totalmente 2D sino que usa esprites diseñados en 3D

Eskema
23/06/2017, 07:42
No la hay, lo que sea te lo comes tu con papas XD

Estopero
23/06/2017, 08:51
No la hay, lo que sea te lo comes tu con papas XD

Oooooooooooooooh, bueno pues... A programar! Muchas thanks! XD


creo que tengo entendido que 2.5D es totalmente 2D sino que usa esprites diseñados en 3D

Pues esa esperanza tenía yo :D, pero se ve que no es tan fácil xD

DarkDijkstra
23/06/2017, 11:08
Hmmm, simplemente podrías activar o desactivar el flag "trigger" en los colisionadores de las plataformas según el personaje esté subiendo o bajando, no?

Es decir, creas un script para las plataformas del estilo:



...
Collider collider;

void Start() {
collider = GetComponent<Collider>();
}

void Update() {
// tendrías que tener una referencia de alguna manera a la velocidad del prota, yo aquí me lo invento, tendrás que verlo en tu caso
collider.isTrigger = hero.velocity.y > 0;
}
...


Otra opción es directamente deshabilitar el collider si el prota está subiendo (lo de volverlo "trigger" es por si quieres saber además cuando está atravesando la plataforma porque quieras hacer algo) en plan: collider.enabled = hero.velocity.y < 0;

El código te lo estoy poniendo así de memoria, pero con la idea no creo que te sea nada difícil implementarlo

chipan
23/06/2017, 13:04
Hmmm, simplemente podrías activar o desactivar el flag "trigger" en los colisionadores de las plataformas según el personaje esté subiendo o bajando, no?

Es decir, creas un script para las plataformas del estilo:



...
Collider collider;

void Start() {
collider = GetComponent<Collider>();
}

void Update() {
// tendrías que tener una referencia de alguna manera a la velocidad del prota, yo aquí me lo invento, tendrás que verlo en tu caso
collider.isTrigger = hero.velocity.y > 0;
}
...


Otra opción es directamente deshabilitar el collider si el prota está subiendo (lo de volverlo "trigger" es por si quieres saber además cuando está atravesando la plataforma porque quieras hacer algo) en plan: collider.enabled = hero.velocity.y < 0;

El código te lo estoy poniendo así de memoria, pero con la idea no creo que te sea nada difícil implementarlo

Creo que con ese algoritmo podría darse el caso de que el personaje se quedase atascado en medio de la plataforma si la direccion del salto cambia antes de atravesarla por completo ¿no?; creo que sería mas simple que las plataformas solo fuesen colisionables si estan mas abajo que el personaje ¿no?

DarkDijkstra
23/06/2017, 13:06
Creo que con ese algoritmo podría darse el caso de que el personaje se quedase atascado en medio de la plataforma si la direccion del salto cambia antes de atravesarla por completo ¿no?; creo que sería mas simple que las plataformas solo fuesen colisionables si estan mas abajo que el personaje ¿no?

No te falta razón... no te sobra razón

Si, cierto, más fácil, activa o desactiva según la coordenada Y del prota sea mayor o menor

Ñuño Martínez
23/06/2017, 14:16
Yo estoy trabajando en un motor "de la vieja escuela", y aunque se basa en tilemap hago algo que puede servirte.

Cada casilla del mapa ("plataforma", en tu caso) incluye el estado del "borde", indicando si es sólido o no. Así, cuando muevo un objeto compruebo si la casilla a la que va a entrar tiene el borde correspondiente sólido, y si es así entonces el objeto no puede desplazarse más allá. Por ejemplo, si es el jugador que está saltando, lo que compruebo es si es sólido por abajo, y si está cayendo, compruebo si es sólido por arriba, etc. Te pongo código real:



(* Checks adjacent tile. *)
FUNCTION TmngTileMap.CanMoveUp (aSpr: TmngSprite): BOOLEAN;
VAR
TileX, TileY, bL, bR, bT, bB: INTEGER;
BEGIN
aSpr.GetBoundingBox (bL, bT, bR, bB);
{ Comprueba la tesela ocupada por la parte superior izquierda del sprite. }
TileX := bL DIV fTileWidth;
IF TileX < 0 THEN EXIT (FALSE);
TileY := (bT - 1) DIV fTileHeight;
IF TileY < 0 THEN EXIT (FALSE);
IF (GetAttribute (TileX, TileY) AND tlBottom) <> 0 THEN EXIT (FALSE);
{ Comprueba la tesela ocupada por la parte superior derecha del sprite. }
TileX := bR DIV fTileWidth;
IF TileX >= fWidth THEN EXIT (FALSE);
RESULT := (GetAttribute (TileX, TileY) AND tlBottom) = 0
END;

Hay otros tres métodos para izquierda, derecha y abajo.

Como ves, primero obtengo el bounding box del objeto, después calcula la posición de la tesela, pero en tu caso sería buscar las plataformas cercanas y que estén en la posición correcta (debajo del objeto, por ejemplo). Como ves, sólo compruebo las teselas que están debajo del límite inferior del bounding box, tú sólo deberías comprobar las plataformas que están debajo del plano inferior del bounding box.

Después, en el juego...


{ Check if there is a wall and move sprite if it is possible. }
IF ((sX < 0) AND fMaze.CanMoveLeft (fSpr))
OR ((sX > 0) AND fMaze.CanMoveRight (fSpr)) THEN
fSpr.X := fSpr.X + sX
ELSE
sX := 0;
IF ((sY < 0) AND fMaze.CanMoveUp (fSpr))
OR ((sY > 0) AND fMaze.CanMoveDown (fSpr)) THEN
fSpr.Y := fSpr.Y + sY
ELSE
sY := 0;

sX y sY son la velocidad del objeto.

Si puedes trasladar eso a Unity, ya lo tienes.

DrumpiFast
19/09/2017, 10:03
Sé que el tema es viejo ya, pero quería decir que en principio sí, las herramientas 2D (o al menos las que conozco) se pueden usar en 3D y viceversa. Por mucho que digan (a menos que haya cambiado mucho la cosa en el último año) Unity no tiene motor 2D, sino el mismo motor 3D funcionando en un plano único de z.
De hecho, el circle collider se suele usar en las ruedas de los coches en los ejemplos 3D de carreras.

Yo usaría para lo de las colisiones de las plataformas algo similar a lo que se hace para detectar el suelo: usar un trigger en la cabeza, y cuando detecte colisión con una plataforma, la mueva a un layer de colisión diferente en la que el prota no choque, y cuando choque con la que tiene en los pies, se vuelva a la capa de colisión sólida para el prota. Aun quedaría solucionar el tema de los enemigos, pero creo que moviendo a los malos entre sus dos propias capas de colisión (para que puedan seguir interactuando con el prota de forma independiente a las plataformas) puede servirte.
Lo mismo, como el tema de las colisiones lo lleva la gráfica y va integrado en el motor, te da hasta más rendimiento que usando aritmética discreta.