Hello amazing reader!
Today I want to discuss something that I had to address while working on AngryBots. If you haven’t played the game yet you can download my version here.
If you have played the game you may have noticed that when you’re hacking a terminal, if you step away from the computer the progress bar animation pauses. If we simply set a sound to play when the hacking starts, then we will missing out the fantastic opportunity to make pictures and sounds work together. In fact the sound will just playback until the end while the bar will pause. To avoid this and to take full advantage of the auditory experience that we can offer to the player I decided to modify the original script called TerminalHack.js. Here’s how it goes:
#pragma strict
@script RequireComponent (Health)
Ok, so this part just above is the header. If you remember, from my previous post, the header is where we tell the cook where to look for the ingredients. So it’s either the fridge, the cupboard, or in this case in another script called Health.js
Actually, in Javascript, we have this nice feature which is called “pragma”. I don’t want to get too technical, but what #pragma strict basically does is to tell the compiler to warn us if we write “bad code”. Mind, not “wrong” code, just “bad”. It’s like your significant other saying: “You’re not going out dressed like that, are you?!”.
Then we can start to declare our variables. What we need is 5 simple things: a name for the Wwise event that pauses the sounds, a name for the Wwise event that resumes the sounds, a guy raising a flag if the hacking as started, a girl raising a flag if the hacking is in progress and finally their parents that tells them to go back home cause it’s late and the hacking is completed anyway. The first two are gonna be strings, the last three are gonna be boolean.
public var hackStartEventName : String;
public var hackCompleteEventName : String;
/************************** ADDITIONAL AUDIO CODE *****************************/
public var hackPauseEventName : String; // when OnTriggerExit is called the hacking pauses
public var hackResumeEventName : String; // when the hacking is paused it resumes
private var hackingStarted : boolean; // tells if the hacking has started so we can pause the sounds and resume them
private var hackingInProgress : boolean; // lets us determine wether the hacking is in progress or not
private var hackingCompleted : boolean; // tells if the hacking has been completed
/************************** END OF ADDITIONAL AUDIO CODE *****************************/
/************************** ORIGINAL CODE *****************************/
private var health : Health;
private var animationComp : Animation;
// initialising the two variables just defined
health = GetComponent. ();
animationComp = GetComponentInChildren. ();
Ok, so now that all the variables we need are there we will go on and initialize them as soon as the game starts. Obviously when the game starts the hacking won’t be already started, and it won’t even be in progress or completed, so we’ll set everything to false. On a side note, the two string variables we defined (the ones holding the name of Wwise events) will be available to set and/or modify in the Unity editor, as we declared them as public variables. We’ll therefore set their initialisation value there.
function Start () {
UpdateHackingProgress ();
enabled = false;
/************************** AUDIO CODE *****************************/
hackingStarted = false; // hacking has not started
hackingInProgress = false; // is not in progress
hackingCompleted = false; // and has not been terminated
/************************** END OF AUDIO CODE *****************************/
}
Ok, so the way this terminal hacking thing works is through the use of a collider and a health systems. It’s like if the player deals damage to the computer while standing inside of the collider. When the health reaches zero a signal is sent that announces that the hacking operation was successful. Here’s how it works when the player is inside:
function OnTriggerStay (other : Collider) {
if (other.gameObject.tag == "Player")
health.OnDamage (Time.deltaTime, Vector3.zero);
}
Now, we’re not really interested in what happens when the player stands in front of the terminal. We are more interested in what happens when the player gets in and out of the collider area, i.e. the area in which the player deals damage to the terminal. Here’s what happens when we enter the area:
/************************** AUDIO CODE *****************************/
function OnTriggerEnter (other : Collider) {
// if the game object entering is the player AND the hacking has not started yet
if (other.gameObject.tag == "Player" && !hackingStarted) {
// then start the hacking process and call the starting event in Wwise
AkSoundEngine.PostEvent(hackStartEventName, gameObject);
// set hackingStarted to true because the hacking process has started
hackingStarted = true;
}
// if the game object entering is the player AND the hacking percentage is non-zero BUT the hacking has previously started
else if (other.gameObject.tag == "Player" && health.health && hackingStarted){
// then resume the event that was stopped by calling the resume event in Wwise
AkSoundEngine.PostEvent(hackResumeEventName, gameObject);
}
}
/************************** END OF AUDIO CODE *****************************/
So, even if the code is commented quite thoroughly a little explanation won’t hurt here. Basically we can find ourselves in two different situations when entering the collider. First case is that the hacking has not started yet, and what will happen here is that we will call the event to start the hacking sound. The second case though is when the player already started to hack the terminal, but then, for some reason, she left the area in which she can deal damage to the terminal. In this other scenario we will have to resume an event that surely must have been previously paused. There is actually a third scenario (I know I said it was only two). And it’s when the player hacks the terminal successfully. Now, if she were to leave the area and then come back to it, the resume event would get called in Wwise, because the hacking has started. If we include a check on the health in the if statement we will avoid calling a useless event and save some resources.
Now let’s have a look at what happens when we leave the collider. Again, there will be two scenarios: the hacking is complete, the hacking is not complete. The first case is not of our concern now, as we’ll deal with it later. The second case though will have to be addressed now:
/************************** AUDIO CODE *****************************/
function OnTriggerExit(other : Collider){
// if the player is leaving the collider AND the hacking progress is not completed
if (other.gameObject.tag == "Player" && !hackingCompleted){
// pause the hacking sound by calling the relative pause event in Wwise
AkSoundEngine.PostEvent (hackPauseEventName, gameObject);
}
}
/************************** END OF AUDIO CODE *****************************/
As you can see, it works pretty similarly from the entering code we wrote before. If the player gets inside the area and the hacking is not completed, then we will pause the event.
At the end of the following bit of code we tell Wwise that the hacking is complete and we set the variable we defined earlier to be true, and this will tell all of our code that: "Yes! The player is awesome! She hacked the terminal!! Hooray!"
function OnHacking () {
enabled = true;
UpdateHackingProgress ();
}
function OnHackingCompleted () {
AkSoundEngine.PostEvent(hackCompleteEventName, gameObject);
animationComp.Stop ();
enabled = false;
/************************** AUDIO CODE *****************************/
hackingCompleted = true; // the hacking process is completed, so we set the relative variable to true
/************************** END OF AUDIO CODE *****************************/
}
And we're done! Now if the player wanders around the audio will match the picture. Here you can see the final part of the code as well as the Update function. They're not part of the audio but they are essential for the animation to work properly.
function UpdateHackingProgress () {
animationComp.gameObject.SampleAnimation (animationComp.clip, (1 - health.health / health.maxHealth) * animationComp.clip.length);
}
function Update () {;
UpdateHackingProgress ();
if (health.health == 0 || health.health == health.maxHealth) {
UpdateHackingProgress ();
enabled = false;
}
}
I hope this is helpful for you, and that you will use something like this in your games, as audio scripting/programming is what can make your already amazing audio blend seamlessly into the game and enhance the player experience.
Take care!