Moviendo horizontalmente un rigidbody

FrioneL

Buenas!

Estoy toqueteando un poco Unity sin tener mucha idea, y me ha surgido una dudilla acerca de como mover rigidbodies o elementos en el juego. Lo puse hace una semana en el foro de unity pero nadie me ha contestado, esta en ingles, pero supongo que me entendereis :b

I have a doubt regarding rigidbody2d movement. I've seen people using different ways to move a gameobject with rigidbody:

  • transform.translate
  • setting rigidbody.velocity
  • rigidbody.addForce
  • rigidbody.movePosition

I'm trying to create a Player which is affected by physics (so I'm using a rigidbody). I understood 'transalte' is not accurated as it is not taking into account physics, it just moves the gameObject to the position. Also, I feel setting directly the velocity of the rigidbody is not a good practice.

Then with the other two methods is where I have some doubts. With 'AddForce' the problem I faced is that it accelerated my Player, and I want it to have a constant velocity, so I "solved" the issue incrementing the linear drag, but I don't think this is a good solution, as at the end is still being accelerated but a lot less.

SO, I guess I should use MovePosition, but I also read this is supposed to be used with kinematic rigidBodies, which is not my case. Why is this? I tried to use it but my character is going crazy, going through vertical collisions when I'm just trying to move it horizontally. I don't understand it. Also I saw that the rigidbody2d.position is in game unit scales ¿?

Any tips please? Why is MovePosition going crazy? Which one should I use?

Here is the code in which the MovePosition is not working well (there is the AddForce which is working commented):

public Vector2 kSpeed = new Vector2(0.01f, 0.0f);
 
 void Update ()     {
         if(Input.GetKey(KeyCode.D))
         {
             //rigidbody2D.AddForce(kSpeed); //this works but increasing the kSpeed value
             Vector2 mov = rigidbody2D.position + kSpeed;
             rigidbody2D.MovePosition(mov);
 
     }
 }

When I try to move to right, it gets stuck like in this photo. It goes through the floor, in diagonal, when I'm just updating the x axis of the rigidBody.

The floor has a collider which works perfectly with the AddForce.

Thanks

cabron

Para mover un objeto con física siempre tienes que darle velocidad, no uses fuerza por que eso lo que hace es lanzarlo, ni lo muevas directamente por que eso lo 'teletransporta' pasándose por el forro la simulación física y las colisiones.

1 respuesta
FrioneL

#2 Pero entonces que uso? setVelocity?

Por que no me funciona bien el movePosition? Este ultimo se supone que tiene en cuenta el motor fisico.

1 respuesta
cabron

#3

Hace ya mucho que dejé Unity, pero si no recuerdo mal, lo suyo es que uses un CharacterController para los personajes en lugar de tratarlo como un objeto físico normal, y tienes el método simpleMove que hace lo que buscas.

1 respuesta
FrioneL

#4 Uhm no conocia la existencia de ese componente. Pero por lo que he leido no actua sobre otros rigidBodies, por lo que tendria que sacrificar el motor de fisica con mi personaje y hacer todas las interacciones manualmente, como empujar otro gameobject, estar sobre plataformas que se muevan, etc.

txandy

#1 Yo para mover el personaje utilizo algo tal que así en unity 5

float move = Input.GetAxis("Horizontal");
GetComponent<Rigidbody2D>().velocity = Vector2.right * move * speed

Donde speed es un float que indica la velocidad del jugador.

1 respuesta
FrioneL

#6 Le seteas directamente la velocidad que tiene que tener. No lo veo mal, lo que quiero que alguien me explique porque no funciona el movePosition. Y, por que no has utilizado un CharacterController?

1 respuesta
13500

#7 Por partes.

El characterController es una especie de encapsulamiento de varias funciones, que se usa para mover GameObjects, pero que no hace uso (por defecto) de las físicas de un Rigidbody.
Por tanto, un characterController no es obligatorio para mover un gameObject. Puedes programar a mano algo más simple.

El rigidbody2D.movePosition no esta diseñado para ese propósito. Imagina un juego 2D en el que hay unas plataformas móviles sobre las q el personaje debe saltar. Esas plataformas tienen un RigidBody2D en su superficie (para que el jugador pueda saltar sobre ellas) y un movimiento constante izq-der.
Para ese movimiento constante izq-der esta diseñado el rigidBody.movePosition.

La forma correcta de mover tu personaje es, dentro del FixedUpdate():

//aplica movimiento
rigidbody2D.AddForce(transform.right*kSpeed*Input.GetAxis("Horizontal"), ForceMode.Force);

//limita la aceleración infinita
if( rigidbody2D.velocity.magnitude > (maxSpeed) ){
	rigidbody2D.velocity = rigidbody2D.velocity.normalized * (maxSpeed);
}

//frena al personaje cuando dejas de pulsar, donde el 0.9f y 2.5f son variables en función de la velocidad a la que quieres que se frene
if(Input.GetAxisRaw("Horizontal")==0 && Input.GetAxisRaw("Vertical")==0){
	rigidbody2D.velocity -= (rigidbody2D.velocity * 0.9f) * (Time.deltaTime/2.5f);
}
2 respuestas
FrioneL

#8 Muchas gracias. Tiene buena pinta, aprovecha la aceleracion pero limita tambien la velocidad.

Entonces, cuando utilizamos el CharacterController? He leido que personajes manejables no deberian tener rigidbody.

FrioneL

#8 Hoy he estado toqueteando again. Un par de preguntas:

  • Si pongo esta logica en el FixedUpdate, noto un bajon considerable de fps solo para mover mi personaje horizontalmente y saltar. Que es lo que pasa? Si lo pongo en el Update normal si va bien.

Esto es lo que tengo:

	void FixedUpdate () 
	{
		float axis = Input.GetAxisRaw("Horizontal");
		bool moving = axis != 0.0f;
		anim.SetBool("moving", moving);

	if(moving)
	{
		// Moviendo!
		Vector2 force = Vector2.right*kSpeed*axis;

		transform.localScale = new Vector3(axis, transform.localScale.y, transform.localScale.z);
		rigidbody2D.AddForce(force);
	}

	// Saltando!
	if(Physics2D.Raycast(transform.position, -Vector3.up, collider2D.bounds.extents.y + 0.1f))
	{
		jumpsCount = 0;
	}

	if((Input.GetKeyDown(KeyCode.Space) || Input.GetKeyDown(KeyCode.W)) && jumpsCount < kMaxJumps)
	{
		++jumpsCount;
		rigidbody2D.AddForce(Vector2.up*kJump);
	}
}

El heroe puede saltar kMaxJumps (doble salto, o lo que sea). El raycast es para comprobar que ha tocado tierra y resetear la cuenta.

  • Cuando aplico fuerza para mover horizontalmente, aplico un factor de speed, ponle 10.0f. Si pongo un chivato en la speed del rigidbody, me aparece que esta yendo a 1.2, etc. Es decir, no guarda una relacion con la speed que le estoy yo dando, no se si porque internamente esta calculandolo con otras medidas o que. El caso, como calculas que no quieres pasar de cierta velocidad si ambas cosas aparentemente no guardan relacion entre si?

Mersi!

Usuarios habituales

  • FrioneL
  • 13500
  • txandy
  • cabron

Tags