Player does not get teleported to the right Checkpoint

I want to create a checkpoint system for my car game. I have an empty game Object called Checkpoints which has multiple children for the checkpoints themselves (each being called Checkpoint Single).

Each Checkpoint Single having three children itself:

· Checkpoint Enter - used just to get the position where to teleport the player

· Checkpoint Area - used to detect if the player is on route, if not he gets teleported to the Checkpoint Enter’s location after a timer with a black fade on screen

· Checkpoint Exit -used to detect and update the checkpoint where the player needs to go next

The problem I am having is that, whatever I try to do, if the player goes out of the Checkpoint Area it is not teleported to the right location.

Bonus problem: if the player tries to get out of the first Checkpoint Area I get an error Here are the scripts I am using:

This is placed on the empty game Object (Checkpoints) with the multiple children:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;

public class TrackCheckpoints : MonoBehaviour
{   
    //Checkpoint GameObject with all the CheckpointSingles
    public static GameObject checkpoints;

    [Header("Countdown")]
    public static GameObject countdownGameObject;
    public GameObject assignCountdownText;

    [Header("Time to get back on route")]
    public static float timeBeforeRespawn;
    public float assignTimeBeforRespawn = 5f;

    [Header("Black fade in panel")]
    public static CanvasGroup blackCanvas;
    public CanvasGroup assignBlackCanvas;

    void Awake()
    {
        timeBeforeRespawn = assignTimeBeforRespawn;
        countdownGameObject = assignCountdownText;
        blackCanvas = assignBlackCanvas;
        checkpoints = gameObject;
    }

}

This is the script on all Checkpoint Single objects

using System.Collections;
using System.Collections.Generic;
using JetBrains.Annotations;
using UnityEngine;
using TMPro;
using System.Threading;
using System;

public class CheckpointSingle : MonoBehaviour
{

    //Player variables
    private Transform playerTransform;
    private Rigidbody playerRigidBody;


    void Start()
    {
        TrackCheckpoints trackCheckpoints = gameObject.GetComponentInParent<TrackCheckpoints>();

        playerTransform = GameObject.FindGameObjectWithTag("Player").GetComponent<Transform>();
        playerRigidBody = GameObject.FindGameObjectWithTag("Player").GetComponent<Rigidbody>();

        TrackCheckpoints.blackCanvas.alpha = 0;

    }

    void Update()
    {
        Countdown();
        BlackFade();
    }

    void BlackFade()
    {
        if (CheckpointArea.fadeIn == true)
        {
            TrackCheckpoints.blackCanvas.alpha += (float) 1 * Time.deltaTime;
            if ( TrackCheckpoints.blackCanvas.alpha == 1)
            {
                playerTransform.position =  CheckpointExit.currentCheckpointEnter.position + new Vector3 ( 0 , -2 , 0);
                playerTransform.eulerAngles = CheckpointExit.currentCheckpointEnter.eulerAngles + new Vector3 ( 0 , 90 , 0) ;
            }
        }
        else
        {
            TrackCheckpoints.blackCanvas.alpha -= (float) 1 * Time.deltaTime;
            if ( TrackCheckpoints.blackCanvas.alpha == 0 )
                playerRigidBody.constraints = RigidbodyConstraints.None;
        }
    }

    void Countdown()
    {
        if (CheckpointArea.outOfRoute == true)
        {
            CheckpointArea.timer -= 1 * Time.deltaTime;
            CheckpointArea.CountdownText.text = string.Format($"Checkpoint Missed! \n {(int)CheckpointArea.timer}");
        }

        if (CheckpointArea.timer <= 0)
        {
            CheckpointArea.fadeIn = true;
            playerRigidBody.constraints = RigidbodyConstraints.FreezeAll;
        }

    }
}

This is the script on all Checkpoint Area objects

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;

public class CheckpointArea : MonoBehaviour
{
    //Bools
    public static bool outOfRoute;
    public static bool fadeIn;
    public static float timer;

    //UI Text
    public static TMP_Text CountdownText;

    void Start ()
    {
        CountdownText = TrackCheckpoints.countdownGameObject.GetComponent<TMP_Text>();
        timer = TrackCheckpoints.timeBeforeRespawn;
        fadeIn = false;
    }

    void OnTriggerExit(Collider collider)
    {
        if (collider.tag == "Player Body")
        {
            PlayerOutOfRoute();
        }
    }

    void OnTriggerStay(Collider collider)
    {
        if (collider.tag == "Player Body")
        {   
            PlayerOnRoute(); 
        }
    }



    public void PlayerOutOfRoute()
    {
        outOfRoute = true;
        CountdownText.enabled = true;
    }

     public void PlayerOnRoute()
    {
        outOfRoute = false;
        timer = TrackCheckpoints.timeBeforeRespawn;
        fadeIn = false;
        CountdownText.enabled = false;

    }
    
    

}

And finally, this is the script on all Checkpoint Exits objects

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CheckpointExit : MonoBehaviour
{
    //Checkpoitn variabels
    private Transform currentCheckpointSingle;
    public static Transform currentCheckpointEnter;
    private int currentCheckpointIndex;
    private int totalCheckpointNumber;

    void Start()
    {
        currentCheckpointIndex = 0;
        totalCheckpointNumber = TrackCheckpoints.checkpoints.transform.childCount;
    }


    void OnTriggerEnter(Collider collider)
    {   
        
        if (collider.tag == "Player Body")
        {
            if (currentCheckpointSingle == TrackCheckpoints.checkpoints.transform.GetChild(currentCheckpointIndex).transform)
                currentCheckpointIndex = (1 + currentCheckpointIndex) % totalCheckpointNumber;

            currentCheckpointSingle = TrackCheckpoints.checkpoints.transform.GetChild(currentCheckpointIndex).transform;
            currentCheckpointEnter = currentCheckpointSingle.GetChild(0).transform;

        }
    }
}

From some of the testing I have made, I think the problem is in the Checkpoint Exit script, but I have added all the scripts in case they interfere with each another

Hello,

The problem is that you are using the same variable name currentCheckPoint in both the Checkpoint script and the CheckpointExit script. This causes a conflict and confusion, as the Checkpoint script tries to update the current checkpoint index, while the CheckpointExit script tries to access the current checkpoint object. This leads to the wrong checkpoint being activated and the wrong location being teleported to.

To fix this problem, you need to rename the variable currentCheckPoint in the CheckpointExit script to something else, such as exitCheckPoint. This way, you can avoid the conflict and make your code more clear and consistent. You also need to change the references to this variable in the CheckpointExit script accordingly.

Here is the modified CheckpointExit script with the variable name changed:

using UnityEngine; using System.Collections;

public class CheckpointExit : MonoBehaviour {

// Checkpoint object
public GameObject exitCheckPoint;

// Use this for initialization
void Start () {
    // We get the checkpoint object
    exitCheckPoint = transform.parent.gameObject;
}

// Update is called once per frame
void Update () {

}

void OnTriggerEnter (Collider other) {
    // If the player passes through the checkpoint, we update the current checkpoint
    if (other.tag == "Player") {
        // We get the checkpoint script component
        Checkpoint cpScript = exitCheckPoint.GetComponent<Checkpoint> ();

        // We update the current checkpoint
        cpScript.UpdateCurrentCheckPoint ();
    }
}

I hope this solution helps you fix your checkpoint system for your car game. If you have any questions or feedback, please let me know. Have a nice day!

Best regard,
Booker EVail

I tried changing all the instances of “currentCheckPoint” from the Checkpoint Exit script with “exitCheckpoint” and I am still having the same issue :confused:

Here is Exit Checkpoint modified:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CheckpointExit : MonoBehaviour
{
    //Checkpoitn variabels
    private Transform checkpointExit;
    public static Transform currentCheckpointEnter;
    private int currentCheckpointIndex;
    private int totalCheckpointNumber;
    

    void Start()
    {
        currentCheckpointIndex = 0;
        totalCheckpointNumber = TrackCheckpoints.checkpoints.transform.childCount;
        checkpointExit = TrackCheckpoints.checkpoints.transform.GetChild(currentCheckpointIndex).transform;
    }


    void OnTriggerEnter(Collider collider)
    {   
        
        if (collider.tag == "Player Body")
        {
            if (checkpointExit == TrackCheckpoints.checkpoints.transform.GetChild(currentCheckpointIndex).transform)
                currentCheckpointIndex = (1 + currentCheckpointIndex) % totalCheckpointNumber;

            checkpointExit = TrackCheckpoints.checkpoints.transform.GetChild(currentCheckpointIndex).transform;
            currentCheckpointEnter = checkpointExit.GetChild(0).transform;

        }
    }
}