Acceleration and Inertia in Top-Down 2D Game (C#)

Hey everybody!

I’m working on a prototype of a player controller that’s more or less a guy on a bicycle. The game is built in 3D but is for all intents and purposes a top-down 2D driving game. I’m representing the player with a sprite with a box collider

My requirements for the bike are simple, but are proving difficult for me to implement 'cause I’m neither the best physics guy nor the best coder. I’d like help figuring out how to get rolling with these bullet points:

  1. 8-Directional (or even analog) Movement
  2. Acceleration and building momentum while a directional button is being held down (When the biker is pedalling)
  3. A maximum speed at which the bike “tops out” and ceases to accelerate
  4. Deceleration/drag and eventual stop while no directional buttons are being held down (when the biker stops pedalling)

I’ve got something that kinda works here:

using UnityEngine;
using System.Collections;

public class PlayerController : MonoBehaviour 
{
	// Exposed to Editor for Easy manipulation
	public float moveSpeed;			// player's base movement speed

	// START - Use this for initialization
	void Start ()
	{
		// Nothing yet!
	}
	
	// UPDATE is called once per frame
	void Update ()
	{
		// Kinda Works:
		rigidbody.AddForce((Input.GetAxis("Horizontal")), 0,(Input.GetAxis("Vertical")),ForceMode.VelocityChange);
	}
}

This gives me a bit of acceleration and resistance, which is nice. However, there are some problems with this code:

  1. No control over rate of acceleration (I need this exposed to the editor so I can easily tweak it)
  2. Almost immediate stop (no decelerating drift when fingers are off the keys – also ideally exposed to editor)
  3. Using two keys (say Up and Left) at once gives me double speed when moving diagonally.

And I’ve tried modifying this, replacing it, and jury-rigging it with no real success. I’ve also tried toying with Unity’s built-in stuff for acceleration, but it’s eluding me.

Can anyone explain how to get this working? My most strenuous requirement here is that I need to understand what I’m doing pretty well so I can modify it moving forward with the project.

For anyone after a copy/paste script to drop into a 5.1 character to make it move like Mario, here you go. There is currently no slow down but that’s not too hard to add in.

using UnityEngine;
using System.Collections;

public class Bug2 : MonoBehaviour {

	public float moveForce;         
	public float maxSpeed; 	

		private Vector3 v;
		
		void Update () {
			v = new Vector3(Input.GetAxis("Horizontal"), 
                    Input.GetAxis("Vertical"), 0.0f);
		}
		
		void FixedUpdate() {
			GetComponent<Rigidbody2D>().velocity = Vector3.ClampMagnitude 
            (GetComponent<Rigidbody2D>().velocity, maxSpeed);
			GetComponent<Rigidbody2D>().AddForce(v.normalized * moveForce);	
		}
}
  1. You need to multiply the vector by your moveSpeed in order to use moveSpeed.
  2. The immediate stop is likely because you’ve modified ‘Drag’ in your Rigidbody component. If so, set this back to 0.0 to start.
  3. You can normalize the vector you use for moving to solve this issue.

using UnityEngine;
using System.Collections;

public class Bug2 : MonoBehaviour  {

	// Exposed to Editor for Easy manipulation
	public float moveSpeed = 1.0f;         // player's base movement speed

	void Update () {
		Vector3 v = new Vector3(Input.GetAxis("Horizontal"), 0.0f, Input.GetAxis("Vertical"));
		rigidbody.AddForce(v.normalized * moveSpeed,ForceMode.VelocityChange);
	}
}