Home > OS >  Movement Code Affected by Fps in Unity 2D
Movement Code Affected by Fps in Unity 2D

Time:02-16

My current player movement code provides 0.32 translation on each key click.

If it is clicked 2 times very quickly, it should be 0.64.

I provide this with coroutine, but it is affected by fps.

How do I ensure that it is not affected by fps?

I know Time.deltaTime, but how do I get exactly 0.32 if I multiply by Time.deltaTime?

My current move code:

public float move = 0.32f; //movement limitation
public float repeat = 4;  // I perform 0.32 in 4 parts to be more smooth.
 
void Update()
{
    if (Input.GetKeyDown(KeyCode.LeftArrow) //Exapmle key. I have 4 ways to move
    {
        StartCoroutine("Left");
    }
}
 
IEnumerator Left()
{
    for (int i = 1; i <= repeat; i  )// as I said, I perform 0.32 in 4 parts to be more smooth.
    {
        transform.position = transform.position   new Vector3(-move / repeat, 0, 0);
        yield return null;
    }
}

CodePudding user response:

If you wanted to be smooth rather use a fixed speed and do e.g.

// distance to move
public float move = 0.32f;
// speed in Unity units per second
public float speed = 1f;
 
void Update()
{
    if (Input.GetKeyDown(KeyCode.LeftArrow) 
    {
        StartCoroutine(Left);
    }
}
 
IEnumerator Left()
{
    // Pre-calculate the target position
    // This is the huge advantage of IEnumerators -> you can store local variables over multiple frames
    var targetPosition = transform.position   Vector3.left * move;

    // track how far you have already moved
    var moved = 0f;
    // Loop until you moved enough
    while(moved < move)
    {
        // the step is now frame-rate independent and moves the object with a fixed value per second
        var step = speed * Time.deltaTime;
        // every frame move one such step towards the target without overshooting
        transform.position = Vector3.MoveTowards(transform.position, targetPosition, step);
        // keep track of the movement
        moved  = step;

        yield return null;
    }

    // and to end up with a clean value in the end
    transform.position = targetPosition;
}

However

If it is clicked 2 times very quickly, it should be 0.64

this wouldn't be covered. In order to do this I would actually use a completely different approach without Coroutines at all and rather simply use e.g.

// distance to move
public float move = 0.32f;
// speed in Unity units per second
public float speed = 1f;
 
Vector3 targetPosition;

void Start()
{
    targetPosition = transform.position;
}

void Update()
{
    if (Input.GetKeyDown(KeyCode.LeftArrow) 
    {
        targetPosition  = Vector3.left;
    }

    ...

    transform.position = Vector3.MoveTowards(transform.position, targetPosition, speed * Time.deltaTime);
}

so now you can smash your move keys in any direction as much as you like and it will simply sum them all up into the one targetPosition and always keep moving towards it smoothly but with a fixed velocity.

or another alternative would be to interpolate and rather make the object move faster if it is further away from the target but slower the closer it comes

// 5 here is an arbitrary number based on experience -> tweak it according to your needs
public float interpolation = 5f;

...

transform.position = Vector3.Lerp(transform.position, targetPosition, interpolation * Time.deltaTime);
  • Related