This week I focused on the new player experience and decided that I was going to make a tutorial level that simply explains to the player how to approach different areas of a circuit they will encounter while playing, giving them a training ground in which they can freely learn without having to feel the need to race.
This started with the creation of a very easy tutorial track. I decided to make it completely flat and mainly comprised of straights and the different types of turns. Each segment of it acts as a way to teach the player. I quickly laid it out in unity with planes before taking it into Maya and tracing over the shape and extruding from the curve. I then just used all the other assets and textures I had to create a simple stadium environment:
I took a coloured identified approach where each colour represented a different action for the player to undertake:
Yellow was simply to ease off the gas as a gentle corner was ahead.
Orange meant to drift. A combination of Gas + Brake while turning
Red meant to brake. Like drifting but without the gas.
After creation of the environment it was time for creating the scripts to teach the player. The way the tutorials pop up is through the use of two scripts and triggers placed within the level. On each trigger is the TutorialTrigger Script. This simply says that when the player is identified to have hit the bounds of the trigger, activate the pop up:
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Player") && !hasTriggeredFinalPopup)
{
// Show pop-up
tutorialPopup.ShowTutorial(tutorialImage);
if (isFinalPopup)
{
hasTriggeredFinalPopup = true;
}
}
}
I also created a bool to know when the final the trigger is collided with. This then stops them from all turning on again on the next lap when the player keeps playing after the tutorial is over.
The second script is the TutorialPopUp script and this actually defines what the pop up is and what to do when it is activated. The first method is for handling activating the pop up:
public void ShowTutorial(Sprite image)
{
tutorialImage.sprite = image;
popupPanel.SetActive(true);
if (eventSystem != null && closeButton != null)
{
eventSystem.SetSelectedGameObject(closeButton.gameObject);
}
gameAudioMixer.SetFloat("Engine", -80f); //mute vol
Time.timeScale = 0f; // Pause the game
}
It first tells the Event System to select the close button as the first selected button. I had to do this otherwise the player wouldn't be able to click it and continue playing. It then sets the the image to active, making it turn on. It then mutes the engine volume and sets time to 0. This pauses the game.
The second method then handles deactivating the pop up:
public void HideTutorial()
{
popupPanel.SetActive(false);
gameAudioMixer.SetFloat("Engine", -8f); //do i need to update this for player prefs later.
Time.timeScale = 1f; // resume the game
}
As you can I see it's pretty much just the opposite of above. I also left myself a note as if I want to have audio settings in the game I will need to use the player prefs audio setting to unmute the audio back to their selected level and not the default I have set it too.
I then altered the level order, reworking them to have the easier levels at the top of the list and moving level 2 to the bottom as that has been the most difficult for players so far. I then encountered a bug where I had forgot to resume time when calling a load scene method in my PauseMenu script. This was a simple fix of setting time to 1 and let me move from tutorial level to level select without freezing the game.
I then updated the Main menu with sub menus for the controls page, settings page, and created a tutorial warning pop up when pressing start, letting first time players choose between playing it or not. This was simple additions to code that was just turning on and off objects:
public void OpenSubMenu()
{
if (mainMenu != null && subMenu != null)
{
mainMenu.SetActive(false); // hide main menu
subMenu.SetActive(true); // show submenu
EventSystem.current.SetSelectedGameObject(closeButton);
}
}
Once again I had to hardcode the button to first select as otherwise swapping between menus would leave the player softlocked not being bale to navigate the menus.
public void ReturnToMainMenu()
{
if (mainMenu != null && subMenu != null && controls != null)
{
subMenu.SetActive(false);
controls.SetActive(false);
startMenu.SetActive(false);
mainMenu.SetActive(true);
EventSystem.current.SetSelectedGameObject(startButton);
}
}
Here is a playthrough of the changes:
Comments