Please be advised that the Audiokinetic offices will close at 3:00 p.m. EST on December 23rd, 2019 for the holiday period, and will reopen on January 3rd, 2020 at 9:00 a.m. EST. Learn more.

Lesson 8

Table of Contents

Setting a Music Region State

When integrating interactive music into a game, you would most often associate your music compositions to different in-game events or actions, thereby creating an association in the player's mind between a segment of music and that event or action. There are many different ways of creating a music system. You could switch music based on the player's in-game progress or position, let the player choose what to listen to, or use a mix of these; but, you would most often only have a single music piece active at one time (or a collection of many that share rhythm or key), to avoid cluttering the soundscape. For any of these scenarios, States are ideal for controlling the current music State, as they work on a global scope (read more about game objects and global scope in Lesson 5).

In the following steps, you will be asked to change the State of the music when the player enters the Village. You will need to add a Trigger volume around the Village, and then from a script you'll set the State depending on the Player's location.

  1. In the Unity menu, go to Audiokinetic > Certification > 301 > Lesson 8 and select Setting a Music Region State.

    First you need to choose a Trigger shape that fits well with the Village area.

    An overhead view of the Village reveals that it is somewhat circular, so a Sphere Trigger would fit well.

    [Tip]

    The Sphere Trigger is one of the most performant Trigger type, requiring less CPU than some other shapes.

  2. Adjust the Scene View, so it's looking down at the Village area.

    [Note]

    Make sure you have not marked any game objects in the Hierarchy. If in doubt, click an empty space below the game objects.

  3. In the Hierarchy, right-click in an empty space, then go to 3D Object and select Sphere.

  4. Use the Move tool, Rotate tool, and Scale tool to make the Sphere encapsulate the Village area.

    Let's now set a different mesh for the Trigger shape, so you can look inside it, and set the Sphere Collider to being a Trigger, so you can enter the Trigger.

  5. In the Inspector's Sphere Collider, enable Is Trigger.

    If you wanted to make the Sphere shape invisible, you could disable the Mesh Renderer altogether. For testing purposes, let's instead make the Sphere shape into a transparent material so you can see when you are entering the trigger. To draw the Sphere, you will be using the included Trigger_Red Material which we used in Lesson 3.

  6. In the Project view, search for Trigger_Red and drag the Trigger_Red Material onto the Sphere game object.

    Next, you need to add a script that will set a state to the Sphere Trigger.

  7. Add a new script named SetMusicState to the sphere, and open it .

  8. You will now have a script with the basic Start() and Update() functions already defined, as explained in Lesson 4.

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class SetMusicState : MonoBehaviour {
    
        // Use this for initialization.
        void Start () {
            
        }
        
        // Update is called once per frame.
        void Update () {
            
        }
    }

    You are not going to use those functions, so let's clean it up by removing everything inside the SetMusicState class.

  9. Select all lines within the SetMusicState curly braces and press Backspace.

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class SetMusicState : MonoBehaviour {
    
    }

    To detect when the player enters the Trigger, you can use the OnTriggerEnter function that will be called by the Trigger if available in the script. This function is named and works similarly to 'AkTriggerEnter', one of the Trigger On options of the AkEvent, previously described in Lesson 1.

  10. In the blank space, write void OnTriggerEnter.

    Notice that a dropdown is being shown by Visual Studio. Here it suggests the function OnTriggerEnter, which is exactly what you are looking for. By clicking on the OnTriggerEnter element, Visual Studio will automatically complete the function. When Visual Studio auto-completes the function, it will also declare it with the access modifier private, which means the function can only be used from within the SetMusicState class.

    [Note]

    If the dropdown is not appearing in your code editor, you can simply type it in manually as in the following step.

  11. Click on the OnTriggerEnter element in the dropdown, or complete the line so that it reads private void OnTriggerEnter(Collider other){}.

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class SetMusicState : MonoBehaviour {
        private void OnTriggerEnter(Collider other){
        
        }
    }
    

    In the OnTriggerEnter parentheses, you will see a Collider variable called 'other'. When the Sphere game object Collider detects another Collider (including Triggers), it will call the OnTriggerEnter function along with what it detected. In other words, the 'other' variable will be a reference to the Collider that just entered this Trigger. For example, when the Player game object enters the Sphere Trigger we just created, OnTriggerEnter will be called, with the 'other' variable containing a reference to the Collider component found on the Player.

    You only want the State to change when the Player's game object enters the Trigger, so you will have to identify if the Collider entering has the tag "Player". For this, you can use an 'if statement' along with the CompareTag() function on the Collider object entering. Let's take a closer look at an 'if statement'.

    An If Statement will receive an input, then evaluate it against a given condition, so that the programmer can execute a piece of code when the condition evaluates to 'true'. Otherwise, when the If statement returns 'false', it will skip that segment of code. To write an if statement, you simply write 'if ' followed by a set of parentheses '()' which will include the boolean expression to evaluate, and curly braces '{}' including the code to run. Let's take a very basic example.

        if (Number == 42){
            print("Number is 42.");
        }else {
            print("Number is not 42.");
        }
    

    Let's return to the exercise. Inside if statement parentheses you need to use the CompareTag() function on the Collider object entering, to investage whether the 'other' game object is the Player. To do so, you write the name of the Player's tag (which is also 'Player') as a string inside CompareTag function's parentheses, and the CompareTag function will then reply with whether the 'true' comparison is 'true' or 'false'.

    [Note]
    A string is a way to store text, and to declare a string you encapsulate the text with two quotation markers ("").

  12. Inside the OnTriggerEnter function curly braces, type if(other.CompareTag("Player")){ }.

    public class SetMusicState : MonoBehaviour {
        private void OnTriggerEnter(Collider other){
            if(other.CompareTag("Player")){ 
                
            }
        }
    }

    [Note]

    Be aware that your code editor might automatically add the ending curly brace for you, so make sure you don't have too many ending curly braces.

    When you set the State inside this "if statement", you can be sure that it is because the player entered the Trigger. Next, you need to make the Wwise-Type State property.

  13. At the top of the class, declare the Wwise-Type State property by writing public AK.Wwise.State OnTriggerEnterState;.

    public class SetMusicState : MonoBehaviour {    
        public AK.Wwise.State OnTriggerEnterState;
        private void OnTriggerEnter(Collider other){
            if(other.CompareTag("Player")){

    You can now set the MusicState in the OnTriggerEnter() function.

  14. Inside the If Statement, write OnTriggerEnterState.SetValue();, and save the script.

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class SetMusicState : MonoBehaviour {
        public AK.Wwise.State OnTriggerEnterState;
        private void OnTriggerEnter(Collider other){
            if(other.CompareTag("Player")){
                OnTriggerEnterState.SetValue();
            }
        }
    }

  15. In the Unity Inspector's SetMusicState script, open the OnTriggerEnterState property, expand MusicStates > Music_Regions and select Village.

    That's it! Let's try it out.

  16. Enter Play mode and run into the Sphere Trigger.

    When spawning in the Training Area you will be listening to the Ambient Music Playlist Container. As you enter the Sphere Trigger, however, the music will change to the Village Music Playlist Container.

    This process will take care of setting the State whenever entering. When exiting, however, the State will not change back to the Ambient Music Playlist Container. Let's add an additional Wwise-Type State class property and set the State when exiting the Trigger. You may now exit Play mode.

  17. Switch back to your code editor, add an empty line below the declaration of the OnTriggerEnterState property, and write public AK.Wwise.State OnTriggerExitState; in it.

    public class SetMusicState : MonoBehaviour {
        public AK.Wwise.State OnTriggerEnterState;
        public AK.Wwise.State OnTriggerExitState;    
        private void OnTriggerEnter(Collider other){
            if(other.CompareTag("Player")){
                OnTriggerEnterState.SetValue();
            }
        }
    }

    To detect whenever the player exits the Trigger, you can use the OnTriggerExit() function. To save some time coding, let's copy-paste the OnTriggerEnter() function and make it into an OnTriggerExit() function.

  18. Select the entire OnTriggerEnter() function, including curly braces, then right-click and select Copy.

  19. Add an empty line below the closing brace of the OnTriggerEnter() function, right-click on that line and select Paste.

    public class SetMusicState : MonoBehaviour {
        public AK.Wwise.State OnTriggerEnterState;
         public AK.Wwise.State OnTriggerExitState;
        private void OnTriggerEnter(Collider other){
            if(other.CompareTag("Player")){
                OnTriggerEnterState.SetValue();
            }
        }
        
        private void OnTriggerEnter(Collider other){
            if(other.CompareTag("Player")){
                OnTriggerEnterState.SetValue();
            }    
        }
    }

  20. You can now simply rename OnTrigger Enter to OnTrigger Exit and OnTrigger EnterState to OnTrigger ExitState, and save the script.

        private void OnTriggerExit(Collider other){
            if(other.CompareTag("Player")){
                OnTriggerExitState.SetValue();
            }
        }

    Lastly, you need to assign the OnTriggerExitState property as well, and try it out.

  21. In the Unity Inspector, open the On Trigger Exit State property, then go to MusicStates > Music_Regions and select Nowhere.

  22. Enter Play mode and run into the Sphere Trigger.

    As before, the Village music should start playing.

  23. Run out of the Sphere Trigger.

    With the changes you've made to the script, now the Ambient music should start playing. You may now exit Play mode.

This approach is very quick to set up and simple to use, but it is important to make sure that the Triggers used for setting States do not overlap, as this might cause a State conflict. More about this in the next section: Creating a System for Intersecting State Areas.