- Home /
Footsteps on different surfaces
Hey guy's,
I was wondering how I can make footsteps when the player walks on different surfaces im guessing I should use a Tag like Woodfloor and when the player is in contact it would trigger the footsteps looping like a player is walking... But I was wondering I dont quite understand it well can someone maybe show me a example of it and I can add to it? or explain it?
I was wondering about this myself, and I asked a question relating to this a few days ago that never really got answered.
There should be an example project that comes with Unity called AngryBots.
If you look at the scripts called FootStepHandler and $$anonymous$$aterialImpact$$anonymous$$anager (You can search for the scripts by clicking in the search bar under the Project window), I think these scripts are supposed to allow different footstep sounds on different surfaces.
The problem is, it doesn't seem to actually work during gameplay, and I've been trying to figure out why.
Everything in the project seems to be set up correctly; there are arrays of sound files for each material, and there are objects in the game you can walk on, like the catwalk, with a physic material assigned to them.
I'm sure the answer is somewhere in the scripts...
If you or someone else figures this out, I'd love to know!
Answer by Develogamer · Jun 15, 2012 at 10:02 AM
You can do a Raycast from the player to the floor, it would return the info of what it hit and like you said, you can determine the type of floor it is by its tag.
for example:
void Update ()
{
RaycastHit hit;
if (Physics.Raycast(transform.position, Vector3.down, out hit))
{
//This is the colliders tag
floorTag = hit.collider.tag;
}
//Then you use the floorTag to choose the type of footstep
if (floorTag == "woodenFloor")
{
//do wood
}
if (floorTag == "stoneFloor")
{
//do stone
}
}
Heres the unity reference for Raycasts http://unity3d.com/support/documentation/ScriptReference/Physics.Raycast.html
hope that helped
Answer by Fuzzfas · Dec 10, 2012 at 03:18 AM
Sorry for the late reply, but I was able to get my script working by replacing:
function OnCollisionEnter(collision : Collision){
var controller : CharacterController = GetComponent(CharacterController);
with:
function OnControllerColliderHit (hit : ControllerColliderHit){
Here is the example of the full script to put it into context:
var stepWood:AudioClip[];
var stepMetal:AudioClip[]; // fill this array with the sounds at the Inspector
var stepConcrete:AudioClip[];
var footSource1 : AudioSource;
var footSource2 : AudioSource;
var delayBeforeSteps : float = 0.20;
var delayBetweenSteps: float = 0.45;
var audioStepLength : float = 0.60;
var groundType : int;
var isPlayerWalking : float = 0.0;
var footAudioRandomness = 0.1;
var soundEffectPitchRandomness = 0.05;
function Update(){
//Check to see if the player is walking by checking for input from the walking keys
if(Input.GetButton("Horizontal") || Input.GetButton("Vertical")){
//if those keys are pressed, the player must be walking...
isPlayerWalking += Time.deltaTime;
}
else{
//if those keys aren't pressed, the player can't be walking.....
isPlayerWalking = 0;
}
}
function Start(){
var aSources = GetComponents(AudioSource);
footSource1 = aSources[0];
footSource2 = aSources[1];
while(true){
if (isPlayerWalking >= 0.20 && groundType == 1){
yield WaitForSeconds(delayBeforeSteps);
footSource1.clip = stepMetal[Random.Range(0, stepMetal.length)];
footSource1.volume = Random.Range(0.4 - footAudioRandomness, 0.4 + footAudioRandomness);
footSource1.pitch = Random.Range(1.0 - soundEffectPitchRandomness, 1.0 + soundEffectPitchRandomness);
footSource1.Play();
if(isPlayerWalking == 0){
yield;}
else{
yield WaitForSeconds(delayBetweenSteps);
footSource2.clip = stepMetal[Random.Range(0, stepMetal.length)];
footSource2.volume = Random.Range(0.4 - footAudioRandomness, 0.4 + footAudioRandomness);
footSource2.pitch = Random.Range(1.0 - soundEffectPitchRandomness, 1.0 + soundEffectPitchRandomness);
footSource2.Play();
yield WaitForSeconds(audioStepLength);
if(isPlayerWalking == 0){
yield;}
}
}
else if ( isPlayerWalking >= 0.20 && groundType == 2){
yield WaitForSeconds(delayBeforeSteps);
footSource1.clip = stepWood[Random.Range(0, stepWood.length)];
footSource1.volume = Random.Range(0.4 - footAudioRandomness, 0.4 + footAudioRandomness);
footSource1.pitch = Random.Range(1.0 - soundEffectPitchRandomness, 1.0 + soundEffectPitchRandomness);
footSource1.Play();
if(isPlayerWalking == 0){
yield;}
else{
yield WaitForSeconds(delayBetweenSteps);
footSource2.clip = stepWood[Random.Range(0, stepWood.length)];
footSource2.volume = Random.Range(0.4 - footAudioRandomness, 0.4 + footAudioRandomness);
footSource2.pitch = Random.Range(1.0 - soundEffectPitchRandomness, 1.0 + soundEffectPitchRandomness);
footSource2.Play();
yield WaitForSeconds(audioStepLength);
if(isPlayerWalking == 0){
yield;}
}
}
else if ( isPlayerWalking >= 0.20 && groundType == 3){
yield WaitForSeconds(delayBeforeSteps);
footSource1.clip = stepConcrete[Random.Range(0, stepConcrete.length)];
footSource1.volume = Random.Range(0.4 - footAudioRandomness, 0.4 + footAudioRandomness);
footSource1.pitch = Random.Range(1.0 - soundEffectPitchRandomness, 1.0 + soundEffectPitchRandomness);
footSource1.Play();
if(isPlayerWalking == 0){
yield;}
else{
yield WaitForSeconds(delayBetweenSteps);
footSource2.clip = stepConcrete[Random.Range(0, stepConcrete.length)];
footSource2.volume = Random.Range(0.4 - footAudioRandomness, 0.4 + footAudioRandomness);
footSource2.pitch = Random.Range(1.0 - soundEffectPitchRandomness, 1.0 + soundEffectPitchRandomness);
footSource2.Play();
yield WaitForSeconds(audioStepLength);
if(isPlayerWalking == 0){
yield;}
}
}
else{
yield;
}
}
}
function OnControllerColliderHit (hit : ControllerColliderHit){
if (hit.gameObject.tag == "metalFloor"){
groundType = 1;
print("Metal");
}
else if (hit.gameObject.tag == "woodFloor"){
groundType = 2;
print("Wood");
}
else if (hit.gameObject.tag == "concreteFloor"){
groundType = 3;
print("Concrete");
}
}
Now this is a valid way to do it, but I ended up syncing the audio to the animation of the character by adding events in the animation editor, so the script I ended up using is actually a little bit more simplified, but still derived from this.
Hope this is helpful!
You are awesome Fuzzfas. Downloading free 4.0 right now onto my crumby laptop because I am eager to try this. Will be back once I try it out. Thanks so much for the reply!
Fuzzfas, it works, just need to fine tune some of these settings but I threw it in a really basic project to do a dirty test and it works. So great! Thanks man! I will be putting a special thanks to you in my free community project and my personal project if thats ok with you. Thanks again!
No problem! Glad this was helpful to someone out there! Looking forward to seeing/hearing about your projects.
Yeah absolutely, question if you have the time. What exactly does delayBeforeSteps, delayBetweenSteps, audioStepLength do or affect.
And also I finally got the chance to drop this in my project ive been working on and am getting this error. Any idea why I might be getting this error?
IndexOutOfRangeException: Array index is out of range.
WalkingSounds+$Start$104+$.$$anonymous$$oveNext () (at Assets/_Scripts/WalkingSounds.js:35)
In fact I went back to my really basic test, I had not saved it once i had it working last time and im getting the same exact error message. :( I im so confused now ahah
Answer by Grady · Jun 15, 2012 at 09:15 AM
Ok guys,
This is something that I thought of recently as well...
So, because you guys were asking about this, I thought I would try and write a little script from scratch... Now I haven't tested this, so there may be some errors, but this is basically how I would do it...:
//Written by Grady Featherstone
//Create a variable to tell whether the player is walking or not
var isPlayerWalking = false;
var metalFloorSound : AudioClip;
var grassDirtGroundSound : AudioClip;
var riverStreamPuddlesSound : AudioClip;
function Update(){
//Check to see if the player is walking by checking for input from the walking keys
if(Input.GetKeyDown("a") || Input.GetKeyDown("w") || Input.GetKeyDown("s") || Input.GetKeyDown("d")){
//if those keys are pressed, the player must be walking...
isPlayerWalking = true;
}
else{
//if those keys aren't presesd, the player can't be walking.....
isPlayerWalking = false;
}
}
function OnCollisionEnter(collision : Collision){
//Check if the player is walking...
if(isPlayerWalking == true){
//If the player is walking, check what sort of ground they're walking on, and then play that sound...
if(collision.gameObject.tag == "metalFloor"){
audio.Play(metalFloorSound);
}
else if(collision.gameObject.tag == "grassDirtGround"){
audio.Play(grassDirtGroundSound);
}
else if(collision.gameObject.tag == "riverStreamPuddles"){
audio.Play(riverStreamPuddlesSound);
}
}
}
You would have to tag each different type of ground something different, as you can see in the script, and then add this script to your player, and it would basically check to see if the player is moving, and if so, what surface they are moving on, and would then play the footsteps sound for that particular ground!
I hope this works, but as I say, I just quickly wrote it then, so no guarantees, but if anyone is interested, then I can try and seriously see if I could get this working nicely!
-Grady
Hi Grady,
This is what I tried to do, but it doesn't seem to be working. I don't get any audio at all. I think something is wrong with my code. $$anonymous$$aybe you can spot it?
var stepWood:AudioClip[];
var step$$anonymous$$etal:AudioClip[];
var $$anonymous$$Interval = 0.1; // $$anonymous$$ interval between steps
var maxVelocity = 8; // max character speed
var bias = 1.1; // the greater the bias, the lesser the step delay variation
var footAudioRandomness = 0.1;
var soundEffect$$anonymous$$chRandomness = 0.05;
function OnCollisionEnter(collision : Collision){
var controller : CharacterController = GetComponent(CharacterController);
while (true){
var vel = controller.velocity.magnitude;
if (controller.isGrounded && vel > 0.2){
if(collision.gameObject.tag == "metalFloor"){
audio.clip = step$$anonymous$$etal[Random.Range(0, step$$anonymous$$etal.length)];
audio.volume = Random.Range(0.4 - footAudioRandomness, 0.4 + footAudioRandomness);
audio.pitch = Random.Range(1.0 - soundEffect$$anonymous$$chRandomness, 1.0 + soundEffect$$anonymous$$chRandomness);
audio.Play();
}
else if(collision.gameObject.tag == "woodFloor"){
audio.clip = stepWood[Random.Range(0, stepWood.length)];
audio.volume = Random.Range(0.4 - footAudioRandomness, 0.4 + footAudioRandomness);
audio.pitch = Random.Range(1.0 - soundEffect$$anonymous$$chRandomness, 1.0 + soundEffect$$anonymous$$chRandomness);
audio.Play();
}
var interval = $$anonymous$$Interval*(maxVelocity+bias)/(vel+bias);
yield WaitForSeconds(interval);
}
else
{
yield;
}
}
}
have tried both these sets of answers/suggestions but am not getting any audio, but also no errors. Any ideas? Were either of you able to confirm these scripts function?
Answer by DaveA · Feb 06, 2014 at 03:34 AM
Or get this asset: http://u3d.as/content/qlc/advanced-footstep-system/6o2