Vector2.MoveTowards giving me a hard time

First of all, it’s a 2d “sidescroller” game, where the player is moving towards the right at a constant speed.

I’ve created an ability for the player to move 5 seconds back in time with the player object.

It seemed to work pretty fine a while ago as far as I can remember. But after I’ve implemented a bunch of other stuff and came back to test this ability, it’s causing problems (sometimes).

Let me explain the timetravelling feature
For each 0.5sec I am adding the current position to a list. And through that list I can move to an earlier position, later on in the game. I am moving the object with the Vector2.MoveTowards() feature

The problem is
Sometimes it moves REALLY slowly, and sometimes too fast. But sometimes it also feels correct, hard to tell anymore.

The code is as follows: I know it’s a lot to take in, but I’ve cut away most of what seems unnecessary tor this question. I would advise your to start reading from the IENumerator Move() since that is most likely where the problem is.

    private PlayerController player;
    private bool cooldown;
    private List<Vector2> positionList = new List<Vector2>();
	

    void Awake()
    {
        player = GameObject.Find("Stickman").GetComponent<PlayerController>();
    }

    void Start()
    {
        StartCoroutine(Cooldown());
        StartCoroutine(Track());
    }

    public void Ability() // This begins the moving
    {        
        if (!cooldown)
        { 
            StartCoroutine(Move(positionList[positionList.Count - 10]));
            positionList.Clear();
        }
    }

    IEnumerator Track() // Adding the position to a list every 0.5sec
    {
        float timer = 0f;
        positionList.Add(player.transform.position);
        while (timer < 0.5f) 
        {
            timer += Time.deltaTime;
            yield return null;
        }     
        StartCoroutine(Track());
    }

    IEnumerator Move(Vector2 target)//Here the actual moving happens
    {
		StartCoroutine(Cooldown());
		bool reached = false;
        float step = 10f * Time.deltaTime;
        player.collider2D.enabled = false;
		
        while (!reached && !player.isDead)
        {
			player.rigidbody2D.isKinematic = true; // This is needed
            player.transform.position = Vector2.MoveTowards(player.transform.position, 
                                                            target, step); //Here it moves

            if (player.transform.position.x < target.x + 0.0001f) // That's good enough for me
            {
                reached = true;
		        player.collider2D.enabled = true;
		        player.rigidbody2D.isKinematic = false;
            }
            yield return null;
        }     
    }

What is causing this problem here? Also feel free to point at any other stuff that seems “weird”.

Thanks for reading!

I’m not aware about the difference in speed, so I’ll suggest to check two things for now:

Either you happen to get a “huge” difference in Time.deltaTime in line 42:

float step = 10f * Time.deltaTime;

which is rather unlikely. Note, that this won’t make your player move framerate-independantly as you calculate the step value once and use it for many frames. More to that later.

Or, what I suspect to be the reason and this is more likely, is that you probably do not disable the player’s movement during the move-back-in-time-phase.


Off Topic due to request by OP

As you also asked for other things to be pointed out:

In order to move the player back in a framerate-independant manner, you should consider to calculate the value in each iteration again, just like for normal movements. As for that, remove the line above and change this line (48)

player.transform.position = Vector2.MoveTowards(player.transform.position, target, step);

to:

player.transform.position = Vector2.MoveTowards(player.transform.position, target, step*Time.deltaTime);

Next, your caching of the positions seems suboptimal if you only need the position that the player had 5 seconds ago (assuming you stick to the constant speed). You can calculate that on the fly (note, that this does not apply to the first 5 seconds):

cachedPosition.x = (player.transform.position.x - playersMoveSpeedPerSecond * seconds)

If you still want to cache the last 10 positions (e.g. speed changes so that the formula above does not apply), think about an array that you iterate over and once you reach the last element, start at the beginning again and overwrite the obsolete entries. You won’t have a continuously growing cache then.

And one more thing: is your cooldown supposed to start right over or do you wait in the cooldown coroutine until the player moved back and continues to play?