It cannot be done......or so it seems.

Hi All.

It would appear that getting a gradual increase in speed of an object, by a set amount, over a set period of time, in progressive stages based on key input, is nigh on impossible.

Scenario is I have a ship and It was planned to be a recreation of old school engine controls on an actual ship…stop, ahead 1/4, ahead full, etc.

Now I can achieve the changes in speed just fine…different key inputs will increase or decrease the speed by a set amount. Can go from zero to 3, and then to 6,9 and 12 with subsequent key inputs.

The problem is the speed change is instantaneous, and looks a bit ridiculous.

I am trying to get the speed to increase gradually over time with each key press, but it will just not work.

I am currently enrolled in a game dev course, so I asked for assistance.

A fellow student gave me a script that involved Lerp, and one of my tutors gave me one that used coroutines.

Problem is the result was pretty much the same regardless, the speed change is instant, though the ratios did change.

I know this is possible, as the same system is used in another game I play, but how is it achieved?

Have spent so many hours/days trying to figure this out it is not even remotely funny. I am almost at the point of sacrificing my firstborn to the coding gods to get a solution to this.

Codes are as below:

Mine.
public class movement2 : MonoBehaviour {

``````public float turnSpeed;

public float velocity = 0f;
public float maxVelocity;
public float minVelocity;
public float AccelSpeed;

public float maxAccel;
public float minAccel;

void Update()
{

if (Input.GetKeyDown (KeyCode.W))
velocity += maxAccel;

if (Input.GetKeyDown (KeyCode.S))
velocity -= maxAccel;

if (Input.GetKey (KeyCode.A))
transform.Rotate (Vector3.up, -turnSpeed * velocity * Time.deltaTime);

if (Input.GetKey (KeyCode.D))
transform.Rotate (Vector3.up, turnSpeed * velocity * Time.deltaTime);

if (velocity >= maxVelocity)
velocity = maxVelocity;

if (velocity <= minVelocity)
velocity = minVelocity;

transform.Translate (Vector3.forward * velocity * Time.deltaTime);
}
``````

}

Tutors:
public class movement : MonoBehaviour
{
public float velocity = 0f;
public float maxVelocity = 100f;
public float minVelocity = 0f;
public float AccelSpeed;

``````public float minAccel;

void Update()
{
if (Input.GetKeyDown(KeyCode.W))
{
StartCoroutine("UpdateVelocity", 3);
}

if (Input.GetKeyDown(KeyCode.S))
{
StartCoroutine("UpdateVelocity", -1);
}

transform.Translate (Vector3.forward * velocity * Time.deltaTime);
}

IEnumerator UpdateVelocity(float value)
{
float temp = velocity + value;

while (velocity < temp) {
velocity += 0.1f;
}
if (velocity >= temp)
{
velocity -= 0.1f;
}
{
yield return new WaitForSeconds(0.25f);
}
}
``````

}

And fellow Students:
public class movment3 : MonoBehaviour {

``````public float speed = 0f;
public float maxspeed;
public float minspeed;
public float AccelSpeed;

void Update ()
{
float maxAccel = Mathf.Lerp (minspeed, maxspeed, Time.deltaTime * 10f);

if (Input.GetKeyDown (KeyCode.W))
speed += maxAccel;

transform.Translate (Vector3.forward * speed * Time.deltaTime);
}
``````

}

It shouldn’t be this hard…should it?

Any solutions GRATEFULLY recieved.

Cheers Coldbeer

They are both kind of right. My version of the coroutine would look like this:

``````WaitForEndOfFrame waitFrame = new WaitForEndOfFrame(); //Create your YieldInstruction here so you dont allocate new memory every iteration
IEnumerator UpdateVelocity(float value)
{
float temp = velocity + value;
while (Mathf.Abs(velocity-temp) > float.Epsilon) {
velocity = Mathf.Lerp(velocity, temp, Time.deltaTime);
yield return waitFrame;
}
}
``````

This will however cause problems when calling the coroutine several times (some kind of “race” where each coroutine try to set velocity to its own goal, one trying to increase the value while the other decreases it). So I would but “float temp” outside of the coroutine depending on the behaviour you want.