I'm working on a driving game, and I've been using RigidBody.MovePosition (non-kinematic) to move the car. I've read that this is not the best method for physics reasons, but I've had massive problems moving objects around with the other techniques. So far, it's been working out great, at least with horizontal movement.
However, now I'm trying to turn the car into a hover-car, and it seems MovePosition is terrible with vertical movement. Rather than trying to fight what is likely a losing battle, I'd like to get either AddForce or velocity working. I'm only concerned with the horizontal (for now).
Here are the three versions, along with the results I'm getting.
RigidBody.MovePosition:
Works great, at least for forward movement. Attempting the same technique with Vector3.up results in all kinds of broken and unpredictable behavior with collisions and physics, though.
void Start ()
{
body = GetComponent<Rigidbody> ();
forward_speed = 0f;
forward_max_speed = .9f;
forward_acceleration = .02f;
forward_movement = Vector3.zero;
rotation_multiplier = 2.5f;
}
//////////////////////////////////////////////////
void FixedUpdate ()
{
if (key_up)
{
if (forward_speed < forward_max_speed) forward_speed += forward_acceleration;
}
else if (key_down)
{
if (forward_speed > -forward_max_speed) forward_speed -= forward_acceleration;
}
else
{
if (forward_speed > -.1f && forward_speed < .1f) forward_speed = 0f;
if (forward_speed != 0f) forward_speed = forward_speed * 0.9f;
}
if (key_left) turning_rotation = forward_speed * -rotation_multiplier;
if (key_right) turning_rotation = forward_speed * rotation_multiplier;
// rotation
transform.Rotate (0f, turning_rotation, 0f);
// forward
forward_movement = transform.forward * forward_speed;
body.MovePosition (body.position + forward_movement);
}
RigidBody.velocity:
The car performs great on flat surfaces, but if it goes airborne for any reason, it falls incredibly slowly, basically letting the player fly around (but not the way I intended). Freezing X and Z rotations partially mitigates the flying, but doesn't fix the slow falling, and also causes the car to have strangely intense trouble getting up inclines. I can't fathom why assigning the velocity would mess with gravity. Unity, you've outdone yourself.
void Start ()
{
body = GetComponent<Rigidbody> ();
forward_speed = 0f;
forward_max_speed = 50f;
forward_acceleration = 1f;
forward_movement = Vector3.zero;
rotation_multiplier = .067f;
}
//////////////////////////////////////////////////
void FixedUpdate ()
{
if (key_up)
{
if (forward_speed < forward_max_speed) forward_speed += forward_acceleration;
}
else if (key_down)
{
if (forward_speed > -forward_max_speed) forward_speed -= forward_acceleration;
}
else
{
if (forward_speed > -.1f && forward_speed < .1f) forward_speed = 0f;
if (forward_speed != 0f) forward_speed = forward_speed * 0.9f;
}
if (key_left) turning_rotation = forward_speed * -rotation_multiplier;
if (key_right) turning_rotation = forward_speed * rotation_multiplier;
// rotation
transform.Rotate (0f, turning_rotation, 0f);
// forward
body.velocity = transform.forward * forward_speed;
}
RigidBody.AddForce:
This one almost works, but the car slides around like it's Disney on ice. Fun, but not right. After changing direction, it seems to take a half second for the car's movement or the force direction to catch up with the rotation, so it slides to the side pretty badly. The same thing happens with gas and brakes. There's a noticeable and frustrating delay. I also had the same problem when I tried vertical movement with this - it just refuses to stop at the elevation I tell it to. I've tried all four of the different ForceMode settings, and aside from having to massively adjust the forward_max_speed and forward_acceleration values, they feel mostly the same. AddForce is the same method used in the CharacterFirstPerson scene in the Standard Assets Project, but I noticed the exact same control delay in that project as well. The guy doesn't start and stop on a dime.
void Start ()
{
body = GetComponent<Rigidbody> ();
forward_speed = 0f;
forward_max_speed = 70f;
forward_acceleration = 5f;
forward_movement = Vector3.zero;
rotation_multiplier = .02f;
}
//////////////////////////////////////////////////
void FixedUpdate ()
{
if (key_up)
{
if (forward_speed < forward_max_speed) forward_speed += forward_acceleration;
}
else if (key_down)
{
if (forward_speed > -forward_max_speed) forward_speed -= forward_acceleration;
}
else
{
if (forward_speed > -.1f && forward_speed < .1f) forward_speed = 0f;
if (forward_speed != 0f) forward_speed = forward_speed * 0.9f;
}
if (key_left) turning_rotation = forward_speed * -rotation_multiplier;
if (key_right) turning_rotation = forward_speed * rotation_multiplier;
// rotation
transform.Rotate (0f, turning_rotation, 0f);
// forward
forward_movement = transform.forward * forward_speed;
body.AddForce (forward_movement, ForceMode.Acceleration);
}
What I'd like to do is get either the RigidBody.AddForce or RigidBody.velocity method working properly so everything is on the up and up with the physics engine. Unfortunately, I've run out of ideas and I'm too frustrated with Unity right now to see the problem clearly.