- Home /
Getting audio.PlayOneShot to work
Hey there! I just ran into an issue working with audio.PlayOneShot. I want to say first I'm new to scripting, I'm an audio guy wanting to gain more knowledge about properly implementing audio into video games. So I have a script set up with triggers for different walking sounds depending on what kind of surface the character is walking on (utilizing tags). I have audio playing but it's really fast and when my character isn't moving it'll loop the last step sound. I was looking to use the audio.PlayOneShot to help fix my issue but what I thought looked right in code doesn't seem to work (either get errors or it doesn't fix the issue, I've tried moving the line of code with no result). Is there another way to fix the problem or did I just place the line of code in the wrong spot? Here it is:
var stepWood:AudioClip[];
var stepTemple:AudioClip[]; // fill this array with the sounds at the Inspector
var stepStone:AudioClip[];
var stepGround:AudioClip[];
var footSource1 : 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];
while(true)
{
if (isPlayerWalking >= 0.20 && groundType == 1)
{
yield WaitForSeconds(delayBeforeSteps);
footSource1.clip = stepTemple[Random.Range(0, stepTemple.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 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 if ( isPlayerWalking >= 0.20 && groundType == 3)
{
yield WaitForSeconds(delayBeforeSteps);
footSource1.clip = stepStone[Random.Range(0, stepStone.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 if (isPlayerWalking >= 0.20 && groundType == 4)
{
yield WaitForSeconds(delayBeforeSteps);
footSource1.clip = stepGround[Random.Range(0, stepGround.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;
}
}
}
function OnControllerColliderHit (hit : ControllerColliderHit)
{
if (hit.gameObject.tag == "templeFloor")
{
groundType = 1;
print("Temple");
audio.PlayOneShot(stepTemple);
}
else if (hit.gameObject.tag == "woodFloor")
{
groundType = 2;
print("Wood");
audio.PlayOneShot(stepWood);
}
else if (hit.gameObject.tag == "stoneFloor")
{
groundType = 3;
print("Stone");
audio.PlayOneShot(stepStone);
}
else if (hit.gameObject.tag == "groundFloor")
{
groundType = 4;
print("Ground");
audio.PlayOneShot(stepGround);
}
}
Thank you very much in advance for any help!
Answer by MarkD · Oct 13, 2013 at 02:31 PM
Ok I can see you put much effort into your audio script and for the general there is nothing wrong with it, only if I where you I wouldn't use playOneShot for a walking loop.
In my own walking script wich is kinda similar to this one I simply play when moving and pause when stopping, this way the audio will continue as soon as you are walking again. Then on the bottom lines I check the floors and switch the Audio clips. I'l give you a rough example:
var WalkAudio:AudioClip;
var stepTemple:AudioClip;
function Update (){
//Here we will detect if the walk buttons are pressed and //play the audio.
var Audio= gameObject.GetComponent(AudioSource);
if(Input.GetButton("Horizontal") || Input.GetButton("Vertical"))
{
//if those keys are pressed, the player must be walking...
Audio.Play();
}
else
{
//if those keys aren't pressed, the player can't be walking.....
Audio.Pause();
}
}
function OnControllerColliderHit (hit : ControllerColliderHit)
{
var Audio= gameObject.GetComponent(AudioSource);
if (hit.gameObject.tag == "templeFloor")
{
groundType = 1;
print("Temple");
Audio.clip=stepTemple;
}
else{
Audio.clip=WalkAudio;
}
}
Also if you are using the character controller you can check its velocity and play audio accordingly, I myself use the velocity to check how fast my character is going and switch between running walking and crouching clips. But those are extra, for what you want to achive this is a good base to start of. Good luck
Thank you very much for the suggestion! I'm still having some issue, I have audio playing but the footstep sounds are triggering super fast. I tried pulling in some of the code I posted before, like the delayBetweenSteps variable but I'm still having the issue.
well you could use a smooth out/in function (the Audio system supports it search it up in the docs :p) for each time the audio switches clip. That could fix your problem without needing to delay with a yield
I'm not familiar with that function and having a hard time finding (I've been looking into the Smooth function) a format that would relate to scripting audio in such a way. That and where to place it in relation to the rest of the code.
Again I'm quite new to all of this, still digging though scripting tutorials
Well it seems that i can't find the function anymore in the ref here, just checked my old code and noticed that I did it completely different. Here is a few examples of code for smoothly lowering the sound's volume and raising.
//adjust this to raise the speed the closer the digits are to 1 the fster it will rise
var FadeSpeed:float=0.005;
function update (){
// based on the rigids body movement speed (usefull for starting and stopping)
Audio.volume=transform.rigidbody.velocity.magnitude;
//and if it is for switching sounds.
if(!CurrentGround){
Audio.volume-=FadeSpeed;
}
//then when a new audioclip is assigned
if(NextGround){
Audio.volume+=FadeSpeed;
}
}
note that this is again made on the fly and you need to impliment itin your own system. (with the hit tags as in your original script.
Hey $$anonymous$$arkD,
I gave this script a shot, and I have the Unity trip over the rigidbody portion in the code due to not having a rigidbody on my character. So I put one on and it flips my character completely upside down and limits the mobility of the character quite a bit (I can rotate around but can't move forward). Also still having issue with the sound firing rapidly, this is what I've done with the script:
function Update ()
{
// based on the rigidbody movement speed (usefull for starting and stopping)
audio.volume=transform.rigidbody.velocity.magnitude;
//and if it is for switching sounds.
if(stepGround)
{
audio.volume-=FadeSpeed;
}
//then when a new audioclip is assigned
if(stepTemple)
{
audio.volume+=FadeSpeed;
}
if(stepWood)
{
audio.volume+=FadeSpeed;
}
if(stepStone)
{
audio.volume+=FadeSpeed;
}
}
I may have done this wrong plugging in my own info and to work around some of the errors I was getting but this is where I'm at with it.
Answer by meat5000 · Oct 14, 2013 at 12:15 AM
Place things in your Start() that require to be executed before the general running of the script.
Place continuous function in your Update() which gets called every frame. This way you wont need a while loop, which can be dangerous anyway.
I don't know but I think yield from a while in start sounds like disaster to me.
I think its firing super fast as its zipping round a while loop stacking up coroutines.
Thanks for the help! Right now my code is looking like this now:
var stepGround:AudioClip;
var stepTemple:AudioClip;
var stepWood:AudioClip;
var stepStone:AudioClip;
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 soundEffect$$anonymous$$chRandomness = 0.05;
function Update ()
{
}
function OnControllerColliderHit (hit : ControllerColliderHit)
{
//Here we will detect if the walk buttons are pressed and //play the audio.
var Audio= gameObject.GetComponent(AudioSource);
if(Input.GetButton("Horizontal") || Input.GetButton("Vertical"))
{
//if those keys are pressed, the player must be walking...
Audio.Play();
}
else
{
//if those keys aren't pressed, the player can't be walking.....
Audio.Pause();
}
if (hit.gameObject.tag == "groundFloor")
{
groundType = 0;
print("Ground");
Audio.clip=stepGround;
}
if (hit.gameObject.tag == "templeFloor")
{
groundType = 1;
print("Temple");
Audio.clip=stepTemple;
}
if (hit.gameObject.tag == "woodFloor")
{
groundType = 2;
print("Wood");
Audio.clip=stepWood;
}
if (hit.gameObject.tag == "stoneFloor")
{
groundType = 3;
print("Stone");
Audio.clip=stepStone;
}
}
But I'm still having problems with the sound going off like a machine gun, I've tried messing with my delayBetweenSteps variable but I'm not having any luck. Is there another way to get the sounds to slow down?
Isn't the character collider always in contact with the floor? It might be worth adding two box colliders to the feet and using those to trigger sound ins$$anonymous$$d.
$$anonymous$$achine gun firing could be a result of the CC 'gravity' routine pulling the CC to the floor constantly.
Character doesn't have feet, it's designed like a worm so the character slides along the terrain
Your answer
Follow this Question
Related Questions
The name 'Joystick' does not denote a valid type ('not found') 2 Answers
A simple problem with scripts 1 Answer
Problems making an audio JumpScare 2 Answers
Making a sound play only once with a Boolean variable in javascript 1 Answer
Triggering different sounds for "footsteps" on different surfaces for a worm-like character. 2 Answers