Mecánica de plataformas plataformas móviles

Lo que vas a crear

En este tutorial, aprenderá cómo crear plataformas móviles y se asegurará de que los objetos que las montan conserven su posición relativa. También manejaremos el caso de ser aplastado entre una plataforma y el suelo..

Prerrequisitos

Este tutorial está basado en la serie Basic Platformer Physics. Específicamente, usaremos el código basado en la 8ª parte del tutorial como punto de partida, con algunas modificaciones. Echa un vistazo a la serie de tutoriales, y en particular la última parte. Los principios detrás de la implementación se mantendrán incluso si está utilizando una solución física diferente, pero el código será compatible con la versión presentada en la serie de tutoriales..

Manifestación

Puedes descargar la demo desde los archivos adjuntos del tutorial. Utilizar el WASD teclas para mover el personaje, Espacio para engendrar un personaje clon, y PAG para engendrar una plataforma móvil. El botón derecho del ratón crea un mosaico. Puede usar la rueda de desplazamiento o las teclas de flecha para seleccionar el mosaico que desea colocar. Los controles deslizantes cambian el tamaño del personaje del jugador.

La demo ha sido publicada bajo Unidad 2017.2b4, y el código fuente también es compatible con esta versión de Unity..

Implementación

Plataformas móviles

En primer lugar, vamos a crear un script para una plataforma móvil..

Inicialización

Empecemos por crear la clase del objeto..

clase pública MovingPlatform: MovingObject 

Ahora vamos a inicializar algunos parámetros básicos del objeto en la función init.

public void Init () mAABB.HalfSize = new Vector2 (32.0f, 8.0f); mSlopeWallHeight = 0; mMovingSpeed ​​= 100.0f; mIsKinematic = true; mSpeed.x = mMovingSpeed; 

Establecemos el tamaño y la velocidad, y hacemos que el colisionador sea cinemático, lo que significa que no será movido por objetos normales. También establecemos el mSlopeWallHeight a 0, lo que significa que la plataforma no subirá las pendientes, siempre las tratará como paredes.

Comportamiento

El comportamiento de esta plataforma móvil en particular será precisamente esto: comience el movimiento a la derecha y, cuando se encuentre con un obstáculo, cambie la dirección 90 grados en el sentido de las agujas del reloj.

public void CustomUpdate () if (mPS.pushesRightTile &&! mPS.pushesBottomTile) mSpeed.y = -mMovingSpeed; else if (mPS.pushesBottomTile &&! mPS.pushesLeftTile) mSpeed.x = -mMovingSpeed; else if (mPS.pushesLeftTile &&! mPS.pushesTopTile) mSpeed.y = mMovingSpeed; else if (mPS.pushesTopTile &&! mPS.pushesRightTile) mSpeed.x = mMovingSpeed; UpdatePhysics (); 

Aquí está el patrón visualizado:

Pegando el personaje a la plataforma

En este momento, si un personaje se encuentra en una plataforma, la plataforma simplemente se deslizará desde debajo de ella, como si no hubiera fricción entre los objetos. Trataremos de remediar eso, copiando el offset de la plataforma..

Determinar el objeto padre

En primer lugar, queremos estar conscientes de qué objeto, si lo hay, es nuestro personaje. Vamos a declarar una referencia a ese objeto en el MovingObject clase.

public MovingObject mMountParent = null;

Ahora en el ActualizarFísicaResponse, Si detectamos que estamos chocando con un objeto debajo de nosotros, podemos asignar esta referencia. Vamos a crear una función que asigne la referencia primero..

public void TryAutoMount (MovingObject platform) if (mMountParent == null) mMountParent = platform; 

Ahora vamos a usarlo en lugares apropiados, es decir, donde decimos que nuestro objeto está chocando con otro objeto debajo de él..

else if (superposición.y == 0.0f) if (other.mAABB.Center.y> mAABB.Center.y) mPS.pushesTopObject = true; mSpeed.y = Mathf.Min (mSpeed.y, 0.0f);  else TryAutoMount (otro); mPS.pushesBottomObject = true; mSpeed.y = Mathf.Max (mSpeed.y, 0.0f);  continuar 

El primer lugar es cuando comprobamos si los objetos están tocando..

si < 0.0f)  mPS.pushesTopObject = true; mSpeed.y = Mathf.Min(mSpeed.y, 0.0f);  else  TryAutoMount(other); mPS.pushesBottomObject = true; mSpeed.y = Mathf.Max(mSpeed.y, 0.0f); 

El segundo lugar es cuando se superponen..

Ahora que hemos cubierto esto, manejemos el movimiento de nuestro objeto. Vamos a modificar el Actualizaciónfísica función del tutorial anterior.

Vamos a declarar una variable de clase para el desplazamiento que necesitamos para mover nuestro personaje.

vector2 mOffset público;

Ahora vamos a reemplazar el antiguo desplazamiento local con la clase uno.

mOffset = mSpeed ​​* Time.deltaTime;

En caso de que el objeto esté en una plataforma, agreguemos el movimiento de la plataforma al desplazamiento.

mOffset = mSpeed ​​* Time.deltaTime; if (mMountParent! = null) if (HasCollisionDataFor (mMountParent)) mOffset + = mMountParent.mPosition - mMountParent.mOldPosition; else mMountParent = null; 

Tenga en cuenta que también estamos comprobando si todavía estamos en contacto con el objeto. Si ese no es el caso, entonces establecemos la mMountParent a nulo, para marcar que este objeto ya no está montado en ningún otro.

A continuación, vamos a mover la posición de nuestro objeto por ese desplazamiento. No vamos a utilizar nuestro Movimiento Función, pero simplemente cambiar la posición. Así que en la verificación de colisión entre los objetos, que tiene lugar justo después de la Actualizaciónfísica, obtendremos el resultado de las posiciones en este marco en lugar de la anterior.

mOffset = mSpeed ​​* Time.deltaTime; if (mMountParent! = null) if (HasCollisionDataFor (mMountParent)) mOffset + = mMountParent.mPosition - mMountParent.mOldPosition; else mMountParent = null;  mPosición + = RoundVector (mOffset + mReminder); mAABB.Center = mPosition;

Ahora vamos a la ActualizarPhysicsP2, que se llama después de que se hayan resuelto las colisiones entre los objetos. Aquí deshacemos nuestro movimiento anterior, que no se ha comprobado para ver si es válido o no.

public void UpdatePhysicsP2 () mPosition - = RoundVector (mOffset + mReminder); mAABB.Center = mPosition;

A continuación, procedemos a ActualizarFísicaResponse Para aplicar un movimiento de superposición con otros objetos. Aquí, anteriormente estábamos modificando la posición directamente, pero ahora, en cambio, modifiquemos la posición mOffset, por lo que este cambio de posición se resuelve más tarde cuando usamos nuestro Movimiento función.

if (smallestOverlap == Mathf.Abs (overlap.x)) float offsetX = overlap.x * speedRatioX; mOffset.x + = offsetX; offsetSum.x + = offsetX; si (superposición.x < 0.0f)  mPS.pushesRightObject = true; mSpeed.x = Mathf.Min(mSpeed.x, 0.0f);  else  mPS.pushesLeftObject = true; mSpeed.x = Mathf.Max(mSpeed.x, 0.0f);   else  float offsetY = overlap.y * speedRatioY; mOffset.y += offsetY; offsetSum.y += offsetY; if (overlap.y < 0.0f)  mPS.pushesTopObject = true; mSpeed.y = Mathf.Min(mSpeed.y, 0.0f);  else  TryAutoMount(other); mPS.pushesBottomObject = true; mSpeed.y = Mathf.Max(mSpeed.y, 0.0f);  

Ahora podemos volver a la ActualizarPhysicsP2, donde simplemente llamamos al ActualizarFísicaResponse y Movimiento Funciona como lo hicimos anteriormente, para obtener el estado de posición correcto.

mPosition - = RoundVector (mOffset + mReminder); mAABB.Center = mPosition; UpdatePhysicsResponse (); if (mOffset! = Vector2.zero) Move (mOffset, mSpeed, ref mPosition, ref mReminder, mAABB, ref mPS);

Arreglar la orden de actualización

Debido a la forma en que ordenamos las actualizaciones de física, si el objeto secundario se actualiza antes que el principal, el niño perderá constantemente el contacto con la plataforma cuando se desplace hacia arriba o hacia abajo..

Para solucionar esto, cada vez que configuramos el mMountParent, Si la plataforma está detrás del elemento secundario en la cola de actualización, intercambiamos esos dos, por lo que el objeto principal siempre se actualiza primero. Hagamos esa modificación en el TryAutoMount función.

public void TryAutoMount (MovingObject platform) if (mMountParent == null) mMountParent = platform; if (platform.mUpdateId> mUpdateId) mGame.SwapUpdateIds (esto, plataforma); 

Como puede ver, si el ID de actualización del objeto de plataforma es mayor que el secundario, el orden de actualización de los objetos se intercambia, eliminando el problema.

Eso es todo cuando se trata de pegar el personaje a la plataforma móvil..

Detectar ser aplastado

Detectar ser aplastado es bastante simple. En el ActualizarFísicaResponse, Necesitamos ver si la superposición de un objeto cinemático nos mueve hacia una pared.. 

Cuidemos primero el eje X:

if (smallestOverlap == Mathf.Abs (overlap.x)) float offsetX = overlap.x * speedRatioX; mOffset.x + = offsetX; offsetSum.x + = offsetX; si (superposición.x < 0.0f)  mPS.pushesRightObject = true; mSpeed.x = Mathf.Min(mSpeed.x, 0.0f);  else  mPS.pushesLeftObject = true; mSpeed.x = Mathf.Max(mSpeed.x, 0.0f);  

Si el objeto está en nuestro lado derecho y ya estamos empujando contra una pared izquierda, entonces llamemos un Aplastar Función, que implementaremos más adelante. Haz lo mismo por el otro lado..

si (superposición.x < 0.0f)  if (other.mIsKinematic && mPS.pushesLeftTile) Crush(); mPS.pushesRightObject = true; mSpeed.x = Mathf.Min(mSpeed.x, 0.0f);  else  if (other.mIsKinematic && mPS.pushesRightTile) Crush(); mPS.pushesLeftObject = true; mSpeed.x = Mathf.Max(mSpeed.x, 0.0f); 

Repitámoslo para el eje Y.

si < 0.0f)  if (other.mIsKinematic && mPS.pushesBottomTile) Crush(); mPS.pushesTopObject = true; mSpeed.y = Mathf.Min(mSpeed.y, 0.0f);  else  if (other.mIsKinematic && mPS.pushesTopTile) Crush(); TryAutoMount(other); mPS.pushesBottomObject = true; mSpeed.y = Mathf.Max(mSpeed.y, 0.0f); 

los Aplastar La función simplemente moverá el carácter al centro del mapa para la demostración..

public void Crush () mPosition = mMap.mPosition + new Vector3 (mMap.mWidth / 2 * Map.cTileSize, mMap.mHeight / 2 * Map.cTileSize); 

El resultado es que el personaje es teletransportado cuando es aplastado por una plataforma.

Resumen

Este fue un breve tutorial porque agregar plataformas móviles no es un gran desafío, especialmente si conoce bien el sistema de física. Tomar prestado todo el código de la serie de tutoriales de física, en realidad fue un proceso muy suave. 

Este tutorial ha sido solicitado varias veces, ¡así que espero que lo encuentre útil! Gracias por leer y nos vemos la próxima vez.!