gamedev

Unity3D – CSharp Audio – Walking Footsteps

Unity3D – CSharp Audio – Walking Footsteps

First you have to consider:

– if character is grounded
– different audio clips depending of movement direction
– random pitch (velocità di riproduzione)
– random audio clips
– trigger zones for different ground surfaces
– trigger zones for different environments

1. In my oipinion the best practice is using an AnimationEvents to synch the Animation and the SFX (http://docs.unity3d.com/Manual/animeditor-AnimationEvents.html)

AnimationEvents -> will calls -> FootstepSfxScript.cs

2. Script some conditions:


using UnityEngine; 
using System.Collections;

public class FootSteps : MonoBehaviour {

	public CharacterController controller; 
	public AudioClip[] concrete ; 
	public AudioClip[] wood ; 
	public AudioClip[] dirt ; 
	public AudioClip[] metal ; 
	public AudioClip[] glass ; 
	public AudioClip[] sand; 
	public AudioClip[] snow; 
	public AudioClip[] floor; 
	public AudioClip[] grass;
	
	private bool step = true; 
	float audioStepLengthWalk = 0.45f; 
	float audioStepLengthRun = 0.25f;
	
	void OnControllerColliderHit ( ControllerColliderHit hit) {
		
		if (controller.isGrounded && controller.velocity.magnitude < 7 && controller.velocity.magnitude > 5 && hit.gameObject.tag == "Untagged" && step == true ) {
			WalkOnConcrete();
		} else if (controller.isGrounded && controller.velocity.magnitude > 8 && hit.gameObject.tag == "Concrete" && step == true || controller.isGrounded && controller.velocity.magnitude > 8 && hit.gameObject.tag == "Untagged" && step == true) {
			RunOnConcrete();
		} else if (controller.isGrounded && controller.velocity.magnitude < 7 && controller.velocity.magnitude > 5 && hit.gameObject.tag == "Wood" && step == true) {
			WalkOnWood();
		} else if (controller.isGrounded && controller.velocity.magnitude > 8 && hit.gameObject.tag == "Wood" && step == true) {
			RunOnWood();
		} else if (controller.isGrounded && controller.velocity.magnitude < 7 && controller.velocity.magnitude > 5 && hit.gameObject.tag == "Dirt" && step == true) {
			WalkOnDirt();
		} else if (controller.isGrounded && controller.velocity.magnitude > 8 && hit.gameObject.tag == "Dirt" && step == true) {
			RunOnDirt();
		} else if (controller.isGrounded && controller.velocity.magnitude < 7 && controller.velocity.magnitude > 5 && hit.gameObject.tag == "Metal" && step == true) {
			WalkOnMetal();
		} else if (controller.isGrounded && controller.velocity.magnitude > 8 && hit.gameObject.tag == "Metal" && step == true) {
			RunOnMetal();       
		} else if (controller.isGrounded && controller.velocity.magnitude < 7 && controller.velocity.magnitude > 5 && hit.gameObject.tag == "Glass" && step == true) {
			WalkOnGlass();
		} else if (controller.isGrounded && controller.velocity.magnitude > 8 && hit.gameObject.tag == "Glass" && step == true) {
			RunOnGlass();
		} else if (controller.isGrounded && controller.velocity.magnitude < 7 && controller.velocity.magnitude > 5 && hit.gameObject.tag == "Sand" && step == true) {
			WalkOnSand();
		} else if (controller.isGrounded && controller.velocity.magnitude > 8 && hit.gameObject.tag == "Sand" && step == true) {
			RunOnSand();            
		} else if (controller.isGrounded && controller.velocity.magnitude < 7 && controller.velocity.magnitude > 5 && hit.gameObject.tag == "Snow" && step == true) {
			WalkOnSnow();
		} else if (controller.isGrounded && controller.velocity.magnitude > 8 && hit.gameObject.tag == "Snow" && step == true) {
			RunOnSnow();
		} else if (controller.isGrounded && controller.velocity.magnitude < 7 && controller.velocity.magnitude > 5 && hit.gameObject.tag == "Floor" && step == true) {
			WalkOnFloor();
		} else if (controller.isGrounded && controller.velocity.magnitude > 8 && hit.gameObject.tag == "Floor" && step == true) {
			RunOnFloor();   
		} else if (controller.isGrounded && controller.velocity.magnitude < 7 && controller.velocity.magnitude > 5 && hit.gameObject.tag == "Grass" && step == true) {
			WalkOnGrass();
		} else if (controller.isGrounded && controller.velocity.magnitude > 8 && hit.gameObject.tag == "Grass" && step == true) {
			RunOnGrass();                   
			
		}       
	}
	
	IEnumerator WaitForFootSteps(float stepsLength) { step = false; yield return new WaitForSeconds(stepsLength); step = true; } 

/////////////////////////////////// CONCRETE //////////////////////////////////////// 
	/// 
void WalkOnConcrete() {
	
	audio.clip = concrete[Random.Range(0, concrete.Length)];
	audio.volume = 0.1f;
	audio.Play();
	StartCoroutine(WaitForFootSteps(audioStepLengthWalk));
}

void RunOnConcrete() {
	
	audio.clip = concrete[Random.Range(0, concrete.Length)];
	audio.volume = 0.3f;
	audio.Play();
	StartCoroutine(WaitForFootSteps(audioStepLengthWalk));
}

////////////////////////////////// WOOD ///////////////////////////////////////////// 

void WalkOnWood() {

audio.clip = wood[Random.Range(0, wood.Length)];
audio.volume = 0.1f;
audio.Play();
StartCoroutine(WaitForFootSteps(audioStepLengthWalk));
}

void RunOnWood() {
	
	audio.clip = wood[Random.Range(0, wood.Length)];
	audio.volume = 0.3f;
	audio.Play();
	StartCoroutine(WaitForFootSteps(audioStepLengthRun));
}

/////////////////////////////////// DIRT ////////////////////////////////////////////// 

void WalkOnDirt() {

audio.clip = dirt[Random.Range(0, dirt.Length)];
audio.volume = 0.1f;
audio.Play();
StartCoroutine(WaitForFootSteps(audioStepLengthWalk));
}

void RunOnDirt() {
	
	audio.clip = dirt[Random.Range(0, dirt.Length)];
	audio.volume = 0.3f;
	audio.Play();
	StartCoroutine(WaitForFootSteps(audioStepLengthRun));
}

////////////////////////////////// METAL /////////////////////////////////////////////// 

void WalkOnMetal() {

audio.clip = metal[Random.Range(0, metal.Length)];
audio.volume = 0.1f;
audio.Play();
StartCoroutine(WaitForFootSteps(audioStepLengthWalk));
}

void RunOnMetal() {
	
	audio.clip = metal[Random.Range(0, metal.Length)];
	audio.volume = 0.3f;
	audio.Play();
	StartCoroutine(WaitForFootSteps(audioStepLengthRun));
}

////////////////////////////////// GLASS /////////////////////////////////////////////// 

void WalkOnGlass() {

audio.clip = glass[Random.Range(0, glass.Length)];
audio.volume = 0.1f;
audio.Play();
StartCoroutine(WaitForFootSteps(audioStepLengthWalk));
}

void RunOnGlass() {
	
	audio.clip = glass[Random.Range(0, glass.Length)];
	audio.volume = 0.3f;
	audio.Play();
	StartCoroutine(WaitForFootSteps(audioStepLengthRun));
}

////////////////////////////////// SAND /////////////////////////////////////////////// 

void WalkOnSand() {

audio.clip = sand[Random.Range(0, sand.Length)];
audio.volume = 0.1f;
audio.Play();
StartCoroutine(WaitForFootSteps(audioStepLengthWalk));
}

void RunOnSand() {
	
	audio.clip = sand[Random.Range(0, sand.Length)];
	audio.volume = 0.3f;
	audio.Play();
	StartCoroutine(WaitForFootSteps(audioStepLengthRun));
}

////////////////////////////////// SNOW /////////////////////////////////////////////// 

void WalkOnSnow() {

audio.clip = snow[Random.Range(0, snow.Length)];
audio.volume = 0.1f;
audio.Play();
StartCoroutine(WaitForFootSteps(audioStepLengthWalk));
}

void RunOnSnow() {
	
	audio.clip = snow[Random.Range(0, snow.Length)];
	audio.volume = 0.3f;
	audio.Play();
	StartCoroutine(WaitForFootSteps(audioStepLengthRun));
}

////////////////////////////////// FLOOR /////////////////////////////////////////////// 

void WalkOnFloor() {

audio.clip = floor[Random.Range(0, floor.Length)];
audio.volume = 0.1f;
audio.Play();
StartCoroutine(WaitForFootSteps(audioStepLengthWalk));
}

void RunOnFloor() {
	
	audio.clip = floor[Random.Range(0, floor.Length)];
	audio.volume = 0.3f;
	audio.Play();
	StartCoroutine(WaitForFootSteps(audioStepLengthRun));
}

////////////////////////////////// GRASS /////////////////////////////////////////////// 

void WalkOnGrass() {

audio.clip = grass[Random.Range(0, grass.Length)];
audio.volume = 0.1f;
audio.Play();
StartCoroutine(WaitForFootSteps(audioStepLengthWalk));
}

void RunOnGrass() {
	
	audio.clip = grass[Random.Range(0, grass.Length)];
	audio.volume = 0.3f;
	audio.Play();
	StartCoroutine(WaitForFootSteps(audioStepLengthRun));
}

}// END class FootSteps

For italian people: come funziona?

1. Ottengo il Character Controller

public CharacterController controller; 

2. Inserisco in un array le clip sonore

public AudioClip[] wood ; 

3. Definisco la lunghezza delle clip

float audioStepLengthWalk = 0.45f; 
float audioStepLengthRun = 0.25f;

4. Verifico delle condizioni:

} else if (controller.isGrounded && controller.velocity.magnitude < 7 && controller.velocity.magnitude > 5 && hit.gameObject.tag == "Wood" && step == true) {
			WalkOnWood();
} else if (controller.isGrounded && controller.velocity.magnitude > 8 && hit.gameObject.tag == "Wood" && step == true) {			RunOnWood();

– controller.isGrounded -> controllo che il controller sia a terra
– controller.velocity.magnitude < 7 -> la velocità del controller sul piano xz, se bassa stà camminando, se più alta sta correndo
– hit.gameObject.tag == “Wood” -> il tipo di terreno che il controller sta toccando
– step == true -> la variabile step è vera

5. Richiama la funziona specifica

void WalkOnWood() {

audio.clip = wood[Random.Range(0, wood.Length)]; // seleziona casualmente l'audio prelevandolo dall'array
audio.volume = 0.1f; // da un volume, basso possibilmente
audio.Play(); // play l'audio
StartCoroutine(WaitForFootSteps(audioStepLengthWalk));// avvia Couroutine per evitare la riproduzione continua
}

6. La Coroutine per riprodurre il suono

IEnumerator WaitForFootSteps(float stepsLength) { step = false; yield return new WaitForSeconds(stepsLength); step = true; } 

– WaitForFootSteps(float stepsLength) -> riceve la lunghezza della clip
– step = false -> interrompe la condizione -> if (controller.isGrounded … && step == true)
– yield return new WaitForSeconds(stepsLength) -> attende fino alla fine della riproduzione del suono
– step = true; -> fa ripartire la condizione if

By |Unity3D, Video Games Development|Commenti disabilitati su Unity3D – CSharp Audio – Walking Footsteps

Unity3D – Play a sound in sync with a countdown

Unity3D – Play a sound in sync with a countdown

Create a scene with:

– Main Camera

– Cube, attach the script:


#pragma strict

// AudioCountDown() variables START ################################################################
var pinPulled : boolean = false;
var fuse : float = 8.5; // the grenade explodes x seconds after the pin is pulled
var fuseTimer : float = 0;
var grenadeBeep : AudioClip;
var slowInterval : float = 1.0; // slow speed SFX
var fastInterval : float = 0.2; // fast speed SFX for last seconds
private var nextTime : float = -1; // declare this variable outside any function so every function can acces 
// AudioCountDown() variables END ##################################################################

function Start () {
} // END Start

function Update () {
		AudioCountDown();// call the audio for the CountDown	
}// END Update

function OnMouseDown ()
{
        // When you click over the object
        pinPulled = true; // the grenade pin will be pulled
        Debug.Log('Pin Pulled!');
}// END OnMouseDown()

function AudioCountDown(){
	// Audio CountDown START ##################################################################
	//If a grenade's pin has been pulled, start the countdown
	if (pinPulled) {
	   fuseTimer -= Time.deltaTime;
	}
	else { // pin in place: reset fuseTimer and nextTime
	   fuseTimer = fuse;
	   nextTime = fuseTimer - slowInterval; // set time for 1st tick
	}
	 
	if (fuseTimer <= nextTime) { // it's time to tick:
	   if (fuseTimer < 3.0){ // if entered fast range (last second), use fast interval
	       nextTime -= fastInterval;
	   } else { // otherwise beep at slow interval
	       nextTime -= slowInterval;
	   }
	   audio.clip = grenadeBeep;
	   audio.Play(); // call Play only once
	}
	// Audio CountDown END  ####################################################################
}// END AudioCountDown()

Inspector> DRAG AND DROP the Bomb-Detonator SFX over var grenadeBeep

Play, click over the cube to start the SFX CountDown

For italian people: come funziona?
1. la variabile pinPulled viene settata true, corrisponde al togliere la sicura alla granata

2. fuseTimer è il conto alla rovescia che si attiva se pinPulled è true infatti:


//If a grenade's pin has been pulled, start the countdown
	if (pinPulled) {
	   fuseTimer -= Time.deltaTime;
	}
	else { // pin in place: reset fuseTimer and nextTime
	   fuseTimer = fuse;
	   nextTime = fuseTimer - slowInterval; // set time for 1st tick

3. fuseTimer una volta attivato viene scalato di 1 secondo alla volta

fuseTimer -= Time.deltaTime;

4. se è passato almeno un secondo…

if (fuseTimer <= nextTime)

5. avvia l’effetto sonoro

           audio.clip = grenadeBeep;
	   audio.Play(); // call Play only once

6. se il countdown è agli ultimi 3 secondi il suono sarà emesso più velocemente

if (fuseTimer <= nextTime) { // it's time to tick:
	   if (fuseTimer < 3.0){ // if entered fast range (last second), use fast interval
	       nextTime -= fastInterval;
By |Unity3D, Video Games Development|Commenti disabilitati su Unity3D – Play a sound in sync with a countdown

Unity3D – Walking Footsteps – SFX – JavaScript

Unity3D – Walking Footsteps – SFX – JavaScript

Create a scene with:

– Main Camera -> Audio Listener component
– Cube -> Audio Source component
-> WalkSfx.js


#pragma strict

// Audio var START -------------------------------
var footsteps : AudioClip[]; // Assign in Inspector
private var step : boolean = true; 
var audioStepLengthWalk = 0.58f;
// Audio var END --------------------------------- 

function Start () {
}// END Start

function Update () {
    Debug.Log(step);// show step status
    
    // move START --------------------------------
    var horiz : float = Input.GetAxis("Horizontal");
	transform.Translate(Vector3(horiz,0,0));
	// move END ----------------------------------

	// AudioPlay START ---------------------------
	if (Input.GetAxis("Horizontal") && step)
	{	
	    Walk();
	}
	// AudioPlay END -----------------------------
}// END Update()

// ###############################################
// Audio functions START #########################
function Walk(){
	audio.clip = footsteps[Random.Range(0, footsteps.Length)];
	audio.volume = 1.0f;
	audio.Play();
	WaitForFootStepsCoroutine(audioStepLengthWalk);// wait time -> audioStepLengthWalk
}// END Walk()

function WaitForFootStepsCoroutine (stepsLength : float){
	step = false; 
	yield WaitForSeconds(stepsLength); 
	step = true;
}// WaitForFootStepsCoroutine()
// Audio functions END ############################
// ################################################

Inspector> Assign 4 different Audio Clip to var footsteps

Play

For italian people: come funziona?

1. if (Input.GetAxis(“Horizontal”) && step) -> se premo i tasti dello spostamento e la variabile step è TRUE
2. viene avviata la funzione Walk();
3. Walk():
– seleziona dall’array una clip random, ce ne servono almeno 4 o il suono risulterà noioso
– setta il volume -> audio.volume = 1.0f;
– avvia l’audio -> audio.Play();
– avvia WaitForFootStepsCoroutine(), inviando audioStepLengthWalk
4. WaitForFootStepsCoroutine():
– audioStepLengthWalk = stepsLength
– step = FALSE per evitare che -> if (Input.GetAxis(“Horizontal”) provochi la riproduzione della clip sonora ad ogni frame
– yield WaitForSeconds(stepsLength); -> mantiene step = FALSE per i secondi di stepsLength -> poi step = TRUE
5. con step = TRUE -> riparte if (Input.GetAxis(“Horizontal”) && step) per avviare una nuova clip audio

By |Unity3D, Video Games Development|Commenti disabilitati su Unity3D – Walking Footsteps – SFX – JavaScript