Character Controller Move returning player to the start

Hello everyone,

I’m working on a 2D runner, and I have been running into this problem for months.
Basically I have this checkpoint system not destroyed on load, and when a level is restarted the Checkpoint Manager teleports the player to the latest checkpoint. Most of the time this works, but sometimes at random the player respawns back at the beginning. I have determined through repeated testing that the Checkpoint Manager is properly, but something else is moving the player back to the beginning.

The culprit is the PlayerController script I have, specifically this block:

            currState.OnStateUpdate(this);

            if (IsDead)
            {
                movement.x = 0;
            }

            characterController.Move(movement * Time.deltaTime);

            if (gameInput.PathDownButtonUp && followPath.node.leftParellelNode != null)
            {
                followPath.node = followPath.node.leftParellelNode;
            }

            if (gameInput.PathUpButtonDown && followPath.node.rightParellelNode != null)
            {
                followPath.node = followPath.node.rightParellelNode;
            }

            lastYAxis = gameInput.Axis.y;

I have placed some debug statements and narrowed down the issue to the line

characterController.Move(movement * Time.deltaTime);

Before it, the position of the player is (196.0, 0.4, -1.0), which is the one they are teleported to by the CheckpointManager. However, after that line the player is somehow teleported back to the start at (-50.4, 0.4, -1.0)

I have confirmed that the vector is not a negative number that would move the player back to that position. The variable Movement is working as intended as well. So there must be something wrong with the CharacterController that keeps causing this.
Can anyone help me solve this?

Hi. I had the same problem and fixed it by doing this:

    bool hasloaded = false;

    void Start()
    {
        StartCoroutine(WaitForLoad());
    }

    void Update()
    {
        if (hasloaded)
        {
            // Your movement code here
        }
    }

    IEnumerator WaitForLoad()
    {
        yield return new WaitForSeconds(0.5f);
        hasloaded = true;
    }

I’m not sure if it’s the best solution (I’m kinda new to programming), but it fixed it for me at least! :slight_smile: