Controlador de personajes 2D en unidad (tratando de recuperar los juegos de plataformas de la vieja escuela)

11

En estos días estoy tratando de crear un controlador de caracteres 2D con unidad (usando física). Soy bastante nuevo en los motores físicos y es realmente difícil obtener la sensación de control que estoy buscando. Estaría muy feliz si alguien pudiera sugerir una solución para un problema que estoy encontrando:

Este es mi FixedUpdate en este momento:

public void FixedUpdate()
{
    Vector3 v=new Vector3(0,-10000*Time.fixedDeltaTime,0);
    _body.AddForce(v);

    v.y=0;
    if(state(MovementState.Left))
    {
        v.x=-_walkSpeed*Time.fixedDeltaTime+v.x;
        if(Mathf.Abs(v.x)>_maxWalkSpeed) v.x=-_maxWalkSpeed;
    }
    else if(state(MovementState.Right))
    {
        v.x= _walkSpeed*Time.fixedDeltaTime+v.x;
        if(Mathf.Abs(v.x)>_maxWalkSpeed) v.x=_maxWalkSpeed;
    }

    _body.velocity=v;

    Debug.Log("Velocity: "+_body.velocity);
}

Estoy tratando de mover el cuerpo rígido aplicando una gravedad y una fuerza lineal para izquierda y derecha. He configurado un material físico que no hace rebotar y 0 fricción cuando se mueve y 1 fricción con el modo detenido. El principal problema es que tengo colisionadores con pendientes y la velocidad cambia de subir (más lento), bajar la pendiente (más rápido) y caminar en un colisionador recto (normal). ¿Cómo podría solucionarse esto? Como ve, estoy aplicando siempre la misma velocidad para el eje x.

Para el jugador lo tengo configurado con una esfera en la posición de los pies que es el cuerpo rígido al que estoy aplicando fuerzas.

Cualquier otro consejo que pueda hacerme la vida más fácil con esto es bienvenido :).

PD Al llegar a casa, me di cuenta de que podía resolver esto aplicando una fuerza constante paralela a la superficie por la que camina el jugador, pero no sé si es el mejor método.

No está mal
fuente
44
Los juegos de plataformas de la vieja escuela usaban "física de dibujos animados" ajustada a mano para la mecánica de salto y el control directo de la velocidad (es decir, sin física) para el movimiento de caminar. Si puedes reescribir el controlador de personaje, hazlo, porque va a ser difícil meter y pinchar una simulación de física blanda en los movimientos nítidos que tenían los juegos de la vieja escuela.
Patrick Hughes
El problema de escribir uno personalizado es que se pierde la detección de colisión. Y no es fácil reconstruirlo sin usar raycast (dependiendo del entorno, etc., podría ser un montón de ellos). ¿Cómo manejas estas situaciones?
Notbad
Puede tener colisionadores sobre cosas que todavía están personalizadas animadas, cuando utiliza cuerpos rígidos cinemáticos. Garantizaría que en la mayoría de las situaciones realmente no quieres la física / fuerzas del mundo real, etc. para este tipo de aplicación. Si está buscando un ángulo más técnico, quizás investigue Human IK
Runonthespot el
1
Def zanja física en esta situación.
Ray_Garner

Respuestas:

7

Si está buscando imitar los juegos de plataformas de la vieja escuela, el primer paso es abandonar la física por completo. Terminarás luchando contra el sistema de física para obtener el movimiento decididamente no realista de un juego de plataformas de la vieja escuela. Eche un vistazo a este reemplazo de CharacterController que abandona la física por completo para tener una buena idea de una forma de implementarlo.

prime31
fuente
3

Probablemente sería más feliz con lo que mheona recomienda. Pero si vas a usar la física de Unity, entonces probablemente quieras usarla ForceMode.VelocityChange.

Ejemplo:

public void FixedUpdate()
{
    var v = Vector3.zero;
    if(state(MovementState.Left))
    {
        v.x=-_walkSpeed*Time.fixedDeltaTime+v.x;
        if(Mathf.Abs(v.x)>_maxWalkSpeed) v.x=-_maxWalkSpeed;
    }
    else if(state(MovementState.Right))
    {
        v.x= _walkSpeed*Time.fixedDeltaTime+v.x;
        if(Mathf.Abs(v.x)>_maxWalkSpeed) v.x=_maxWalkSpeed;
    }

    _body.AddForce(v, ForceMode.VelocityChange);

    Debug.Log("Velocity: "+_body.velocity);
}

También debe aplicar la gravedad global en la configuración de Física de su proyecto, y para los objetos que desea que caigan más rápido, agregue un componente de Fuerza constante .

ForceMode.Impulsees similar pero se ve afectado por la masa del cuerpo rígido. Lo hace más difícil de sintonizar.

michael.bartnett
fuente
2

Incluso si no te gusta el componente integrado de Character Controller (como a mí), mira el código de ejemplo de Unity para el Tutorial de juego 2D .

El código implementa un juego 2D completo con plataformas móviles, enemigos y cajas con colisión, utilizando el Controlador de personajes.

Pero si ni siquiera quiere echar un vistazo, le sugiero que minimice el uso de la física e intente copiar su comportamiento con su propio código. Dependiendo de qué tipo de juego 2D estés planeando, puede funcionar bastante bien. Por ejemplo, en lugar de aplicar fuerza para Rigidbody.velocitymover a tu personaje con el que podrías meterte directamente Transform.Translate(), lo que mueve el objeto Transform.positionsegún su eje. Se podía determinar el forwardy backen relación con el objeto mismo o tal vez la plataforma o en el suelo Transform.up, para que sepa si es una rampa y tipo de saber su ángulo.

Además, si crea algún tipo de atributo de control de velocidad (por ejemplo, cuánto tiempo se presiona la tecla), puede aplicarlo junto con su dirección mientras traduce para evitar que su personaje camine algo demasiado inclinado sin cierta velocidad, como lo hicieron en Sonic the Hedgehog para Genesis / Mega Drive.

Si eliges seguir usando la física, no puedo ayudarte en absoluto porque no soy tan bueno en eso, pero ten en cuenta que es un comportamiento normal ir 'cuesta arriba' más lento ya que el cuerpo necesita más fuerza para mantenerse al día , como la vida real.

mheona
fuente
Lo primero que leí cuando llegué a la unidad fue ese tutorial. El problema es que la sensación de control es bastante mala. Es por eso que quería encontrar mi propia solución. Por otro lado, cuando comience a usar Transform.Translate () no es tan fácil hacer pendientes y otras cosas. Debes lanzar rayos varias veces (2 o 3 para el piso, más para la dirección en la que te mueves dependiendo del tamaño del héroe) Para dispositivos móviles, la transmisión de rayos no es buena, y menos si tiene que hacer 5..n por iteración de detección de colisión. Quizás podría estar equivocado, pero no lo creo.
Notbad
1

Lo que quieres es el controlador de caracteres incorporado . Al configurar la step offsetpropiedad en este componente, puede hacer que un jugador suba y baje pendientes con facilidad.

NoobsArePeople2
fuente
Perdón por no comentar, sé que hay un controlador de personaje en la unidad y que lo he usado varias veces, pero no me gusta cómo se comporta. Es más adecuado solo para FPS, no un juego de plataformas donde la mecánica de movimiento es una de las cosas más importantes.
Notbad
Creo que una vez que juegas con la configuración en el Controlador de caracteres, funciona bien. ¿Qué encontraste faltante?
NoobsArePeople2
Lo primero que no me gusta es que es lento en relación con los cuerpos rígidos habituales con un poco de rayos. Sabiendo cómo lograrlo, creo que podría hacer un controlador más liviano. Otro problema es que es un comportamiento extraño de cápsula / esfera en los bordes de la plataforma (se puede resolver con más rayos). Es por eso que quiero rodar el mío.
Notbad el
0

ingrese la descripción de la imagen aquíSupongo que es porque la fuerza no es paralela a la plataforma y el resultado termina siendo más bajo en ascenso y más alto en descenso.

Si aplica una fuerza relativa al sistema de coordenadas

AddRelativeForce

Desea mantener una velocidad máxima en "x" y compararla con un escalar, recuerde que la velocidad es un vector y componga vx y vy, en terreno plano vy es cero, pero necesariamente en pendientes es mayor que cero.

La velocidad cambia de acuerdo con la dirección del cuerpo, y su vx relativo cambia con respecto a su vx general

Esto puede modificar su V de una manera que no desea también:

if (Mathf.Abs (v.x)> _ maxWalkSpeed) v.x = _maxWalkSpeed;

Mantener el mismo Vx global puede parecer extraño a la vista. (Aceleraciones no deseadas)

NorbyAriel
fuente