I am playing with a simple movement script, and I have a tricky problem.
My acceleration is set to 0.2, max speed to 5. These are scaled based on Delta.Time, however when running with different framerates the apparent acceleration can vary wildly.
The problem arises because regardless of Delta.Time, it will take 25 update steps to go from 0 to 5 in terms of speed.
If the framerate is at 60 fps, this is nice and smooth. If I turn off Vsync, and go up to 2000 fps, the apparent acceleration is virtually instantaneous. I want to make the apparent acceleration consistent across any framerate.
The solution probably lies in thinking of acceleration in terms of distance per second per second, rather than distance per step per step. I am bit tired though and can’t think straight.
Any help is appreciated.
I have pasted the code below:
using UnityEngine;
using System.Collections;
public class Movement : MonoBehaviour {
public float maxSpeed = 5f;
public float maxAcceleration = 0.02f;
public float deceleration = 0.02f;
public bool normalizeMovement = true;
private Vector2 speed = Vector2.zero;
// Use this for initialization
void Start ()
{
}
// Update is called once per frame
void Update ()
{
float maxSpd = maxSpeed * Time.deltaTime;
float maxAcc = maxAcceleration * Time.deltaTime;
float dec = deceleration * Time.deltaTime;
// Add raw axis inputs to temp acceleration vector
Vector2 acceleration = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
// Normalize the acceleration vector if set
if(normalizeMovement) acceleration.Normalize();
// Modify acceleration based on maxAcceleration
acceleration = acceleration * maxAcc;
// If x of acceleration is zero, apply deceleration if speed is also zero
if (acceleration.x == 0f speed.x != 0f)
{
if (Mathf.Abs(speed.x) < dec) speed.x = 0f; // If speed is less than deceleration, set to zero
else if (speed.x > 0f) speed.x -= dec; // Else if speed is greater than zero, reduce speed by deceleration
else if (speed.x < 0f) speed.x += dec; // Else is speed is less than zero, increase speed by deceleration
}
if (acceleration.y == 0f speed.y != 0f)
{
if (Mathf.Abs(speed.y) < dec) speed.y = 0; // If speed is less than deceleration, set to zero
else if (speed.y > 0) speed.y -= dec; // Else if speed is greater than zero, reduce speed by deceleration
else if (speed.y < 0) speed.y += dec; // Else is speed is less than zero, increase speed by deceleration
}
speed += acceleration; // apply acceleration to speed
if (speed.magnitude > maxSpd) // If speed is greater than max speed
{
speed.Normalize(); // Normalize speed
speed = speed * maxSpd; // Modify speed based on max speed
}
// Apply speed to object transform.position
Vector3 speedV3 = new Vector3(speed.x, speed.y, 0); // Create vector 3 of speed vector 2, for simpler addition
transform.position += speedV3; // Apply speed to position modified by delta time
Debug.Log ("Speed: " + speedV3.magnitude * (1/ Time.deltaTime) + " Acceleration: " + acceleration.magnitude * (1/Time.deltaTime)) ;
}
}