Answers for "Top Down car/vehicle movement"
http://answers.unity.com/questions/1095197/top-down-carvehicle-movement.html
The latest answers for the question "Top Down car/vehicle movement"Answer by ijidau
http://answers.unity.com/answers/1095277/view.html
Ok, this is a little bit complicated but I experimented and figured out a solution.
It works by finding a Quaternion from the combination of horizontal and vertical input. This is the target rotation. The rotation is then smoothly transitioned from it's current rotation to the target rotation over a period of time (turnRate). A relative force is added to get the rigidbody to move forward in the direction it is facing. This works, with some help from a conditional to prevent it resetting target rotation to up (2D top down forwards) if the input is zero.
However, If you apply force to a rigidbody and the rotation doesn't match this 'direction', it will appear to drift like a spaceship without friction. Disable lines 37 onwards to see what I mean. So, you need to calculate the sideways drift occurring, then apply some form of traction force to counter this. Basically you need to simulate that the tyres should not be allowed to slide sideways. This is the most complicated part of the script, but hopefully the included comments clarify how this works.
N.B. the RigidBody2D in my test has gravity scale set to zero (it's a top down game, so doesn't need gravity) and it has a linear drag of 1 (simulates rolling friction), angular drag of 0.05.
using UnityEngine;
using System.Collections;
public class CarDriveInDirection : MonoBehaviour {
private Rigidbody2D rb;
private float hInput = 0.0f;
private float vInput = 0.0f;
public float speed = 200.0f;
public float turnRate = 3.0f;
Quaternion targetRotation;
void Start()
{
rb = GetComponent<Rigidbody2D>();
targetRotation = Quaternion.identity;
}
void Update()
{
hInput = Input.GetAxis("Horizontal");
vInput = Input.GetAxis("Vertical");
}
void FixedUpdate()
{
Vector3 move = new Vector3(hInput, vInput, 0);
if(move.x != 0.0f || move.y != 0.0f)
{
targetRotation = Quaternion.LookRotation(Vector3.forward, move);
transform.rotation = Quaternion.RotateTowards(transform.rotation, targetRotation, turnRate);
rb.AddRelativeForce(Vector3.up * speed * Time.fixedDeltaTime);
}
// Get a left or right 90 degrees angle based on the rigidbody current rotation velocity
float steeringRightAngle;
if(rb.angularVelocity > 0) {
steeringRightAngle = -90;
} else {
steeringRightAngle = 90;
}
// Find a Vector2 that is 90 degrees relative to the local forward direction (2D top down)
Vector2 rightAngleFromForward = Quaternion.AngleAxis(steeringRightAngle, Vector3.forward) * Vector2.up;
// Calculate the 'drift' sideways velocity from comparing rigidbody forward movement and the right angle to this.
float driftForce = Vector2.Dot(rb.velocity, rb.GetRelativeVector(rightAngleFromForward.normalized));
// Calculate an opposite force to the drift and apply this to generate sideways traction (aka tyre grip)
Vector2 relativeForce = (rightAngleFromForward.normalized * -1.0f) * (driftForce * 10.0f);
rb.AddForce(rb.GetRelativeVector(relativeForce));
}
}Mon, 09 Nov 2015 05:50:49 GMTijidau