App state manager

We are going to add an AppStateManager to the project. Let's begin by making the object and then write the component script:

  1. In the root of the Hierarchy, create an empty game object, and name it AppStateManager.
  2. In the Scripts folder create a new C# script named AppStateManager and drag it onto AppStateManager as a component.

Open the AppStateManager script for editing, as follows:

File: AppStateManager.cs

First, we'll declare the appState and a large set of public variables that will be explained as we use them:

using UnityEngine; 
using UnityEngine.Events; 
using UnityEngine.UI; 
using Vuforia; 
 
public class AppStateManager : MonoBehaviour { 
 
    private AppStates appState; 
    //Vuforia scripts that are used to get the state of the app. Can be found using FindObjectOfType<T>(); 
    public ReconstructionBehaviour reconstructionBehaviour; 
    public SurfaceBehaviour surfaceBehaviour; 
    public ImageTrackableEventHandler imageTarget; 
 
    ///UI 
    public GameObject instructionHolder; 
    public Text instructionsText; 
    public Button doneButton; 
    public Button resetButton; 
 
    //For the game 
    public UnityEvent OnStartGame; 
 
    //UI resources for instructions 
    public string pointDeviceText; 
    public string pullBackText; 
 
} 

The Start() function will register a listener for when tracking is first detected and set our state to INIT_ANIMATION:

    void Start() { 
        imageTarget.OnImageTrackableFoundFirstTime.AddListener( OnImageTrackableFoundFirstTime); 
    } 
 
    private void OnImageTrackableFoundFirstTime() { 
        appState = AppStates.INIT_ANIMATION; 
    } 

The bulk of our state management is performed in Update(). The update action depends on the current state, where we use a big switch statement. This code directly follows the state definitions specified earlier in this section's User experience and app states topic. Begin writing the Update as follows:

    void Update() { 
        //We declare the bool values here because we want them to be set to false, unless the state is correct 
        //This saves us from setting the values to false in each state. 
        bool showDoneButton = false; 
        bool showResetButton = false; 

Now, we begin the big switch statement:

        switch (appState) { 
            //Detection phase 
            case AppStates.OVERLAY_OUTLINE: 
                instructionsText.text = pointDeviceText; 
                surfaceBehaviour.GetComponent<Renderer>().enabled = false; 
                break; 
 
            // The animation that is played when the trackable is found for the first time 
            case AppStates.INIT_ANIMATION: 
                appState = AppStates.SCANNING; 
                break; 
 
            // Scanning phase 
            case AppStates.SCANNING: 
                ShowWireFrame(true); 
                instructionsText.text = pullBackText; 
                showDoneButton = true; 
                break; 
 
            // When the user taps done. This happens before the game can be played 
            case AppStates.GAME_RENDERING: 
                if ((reconstructionBehaviour != null) && (reconstructionBehaviour.Reconstruction != null)) { 
                    ShowWireFrame(false); 
                    surfaceBehaviour.GetComponent<Renderer>().enabled = false; 
                    imageTarget.ToggleOnStateChange = true; 
                    reconstructionBehaviour.Reconstruction.Stop(); 
                    OnStartGame.Invoke(); 
                    appState = AppStates.GAME_PLAY; 
                } 
                break; 
 
            //This is where the user can shoot the ball 
            case AppStates.GAME_PLAY: 
                instructionHolder.gameObject.SetActive(false); 
                showResetButton = true; 
                break; 
 
            //User taps on [RESET] button - Re-loads the level 
            case AppStates.RESET_ALL: 
                //Reloads this scene 
                UnityEngine.SceneManagement.SceneManager.LoadScene(0); 
                appState = AppStates.NONE; 
                break; 
 
            // Just a placeholder state, to make sure that the previous state runs for just one frame. 
            case AppStates.NONE: break; 
        } 

After the switch statement, we include logic to decide when to display the done or cancel buttons, as follows:

        if (doneButton != null && 
            showDoneButton != doneButton.enabled) { 
            doneButton.enabled = showDoneButton; 
            doneButton.image.enabled = showDoneButton; 
            doneButton.gameObject.SetActive(showDoneButton); 
        } 
 
        if (resetButton != null && 
            showResetButton != resetButton.enabled) { 
            resetButton.enabled = showResetButton; 
            resetButton.image.enabled = showResetButton; 
            resetButton.gameObject.SetActive(showResetButton); 
        } 
    } 

That's the end if the Update function. It calls some helper functions as defined next, as follows:

    void ShowWireFrame(bool show) { 
        WireframeBehaviour[] wireframeBehaviours = FindObjectsOfType<WireframeBehaviour>(); 
        foreach (WireframeBehaviour wireframeBehaviour in wireframeBehaviours) { 
            wireframeBehaviour.ShowLines = show; 
        } 
    } 
 
    //Called by the buttons 
    public void TerrainDone() { 
        appState = AppStates.GAME_RENDERING; 
    } 
 
    public void ResetAll() { 
        appState = AppStates.RESET_ALL; 
    } 

I know this is a lot of code and I hope you don't mind following it, let alone typing it into your own app, but when you break it down, each section is just a few lines of code.

The completed code files are included with the downloadable files for the projects in this book from the publisher.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset