void Init()
    {
        // incase we need to change the timescale, it gets set here
        Time.timeScale = gameSpeed;

        // tell race manager to prepare for the race
        GlobalRaceManager.Instance.InitNewRace(totalLaps);

        // initialize some temporary arrays we can use to set up the players
        Vector3 []    playerStarts    = new Vector3 [numberOfRacers];
        Quaternion [] playerRotations = new Quaternion [numberOfRacers];

        // we are going to use the array full of start positions that must be set in the editor, which means we always need to
        // make sure that there are enough start positions for the number of players

        for (int i = 0; i < numberOfRacers; i++)
        {
            // grab position and rotation values from start position transforms set in the inspector
            playerStarts [i]    = (Vector3)startPoints [i].position;
            playerRotations [i] = ( Quaternion )startPoints [i].rotation;
        }

        SpawnController.Instance.SetUpPlayers(playerPrefabList, playerStarts, playerRotations, playerParent, numberOfRacers);

        playerTransforms = new ArrayList();

        // now let's grab references to each player's controller script
        playerTransforms = SpawnController.Instance.GetAllSpawnedPlayers();

        playerList = new ArrayList();

        for (int i = 0; i < numberOfRacers; i++)
        {
            Transform         tempT          = (Transform)playerTransforms[i];
            CarController_MVD tempController = tempT.GetComponent <CarController_MVD>();

            playerList.Add(tempController);

            BaseAIController tempAI = tempController.GetComponent <BaseAIController>();

            // tell each player where to find the waypoints
            tempAI.SetWayController(WaypointControllerForAI);

            tempController.Init();

            // tell the car controller script about the waypoint controller so it can pass it on to the racecontroller (!)
            tempController.SetWayController(WaypointControllerForAI);
        }

        // grab a ref to the player's gameobject for later
        playerGO1 = SpawnController.Instance.GetPlayerGO(0);

        // add an audio listener to the first car so that the audio is based from the car rather than the main camera
        playerGO1.AddComponent <AudioListener>();

        // look at the main camera and see if it has an audio listener attached
        AudioListener tempListener = Camera.main.GetComponent <AudioListener>();

        // if we found a listener, let's destroy it
        if (tempListener != null)
        {
            Destroy(tempListener);
        }

        // grab a reference to the focussed player's car controller script, so that we can
        // do things like access its speed variable
        focusPlayerScript = ( CarController_MVD )playerGO1.GetComponent <CarController_MVD>();

        // assign this player the id of 0
        focusPlayerScript.SetID(0);

        // set player control
        focusPlayerScript.SetUserInput(true);

        // tell the camera script to target this new player
        cameraScript.SetTarget(playerGO1.transform);

        // do initial lap counter display
        UpdateLapCounter(1);

        // lock all the players on the spot until we're ready to go
        SetPlayerLocks(true);

        // start the game in 3 seconds from now
        Invoke("StartRace", 4);

        // update positions throughout the race, but we don't need
        // to do this every frame, so just do it every half a second instead
        InvokeRepeating("UpdatePositions", 0.5f, 0.5f);

        // hide our count in numbers
        HideCount();

        // schedule count in messages
        Invoke("ShowCount3", 1);
        Invoke("ShowCount2", 2);
        Invoke("ShowCount1", 3);
        Invoke("HideCount", 4);

        // hide final position text
        finalPositionText.gameObject.SetActive(false);
        doneFinalMessage = false;

        // start by hiding our wrong way message
        wrongWaySign.SetActive(false);

        didInit = true;
    }