Input KeyDown that turns off when you take your finger off the key?

I’m new to javascript and working on a piece that will have walking sounds in the world when you press W. But how can I create it so when you press W the sound will play and if you take it off it will stop playing.

Because right now it just creates a sound and plays the whole walking sound. So I can tap W and it will create a bunch of walking sound bits in the game. Here’s my code

function Update () {
   
    if (Input.GetKeyDown(KeyCode.W))
    {
        AudioSource.PlayClipAtPoint(walkingoutside, transform.position);
    }
}

Input.GetKeyUp(KeyCode.W)

Input.GetKey returns true when the button is held down, and false when it is not. So that’s half the problem; it can give you the current state of the key.

The other half is: once you tell an AudioSource to play, it will play the whole sound, unless you tell it to stop. Fortunately there’s a Stop method for exactly that purpose. So something like the following ought to work:

  if (Input.KeyDown(KeyCode.W)) {
    audioSource.PlayClipAtPoint(walkingoutside, transform.position);
  } else {
    audioSource.Stop();
  }

Incidentally, if you’re new to JavaScript, then let me recommend you be new to C# instead. The JavaScript support in Unity is great for people who are already fluent in JS and don’t have the time or inclination to switch. But serious Unity coding is almost always done in C# (the PlayStation team here at the Unity conference said it was well over 95%, maybe 99% of the code they see on that platform). If you’re new to both, I don’t think one is particularly harder than the other, and in the long run I think you’ll be happier with C#. That’s my $0.02, anyway.

Cheers,

  • Joe

Joe, your code will play the sound for 1 frame then immediately stop it.

if (Input.GetKeyDown(KeyCode.W)) {
    AudioSource.PlayClipAtPoint(walkingoutside, transform.position);
}
if (Input.GetKeyUp(KeyCode.W)) {
    AudioSource.Stop();
}

I think he meant GetKey()

This would still be the wrong behavior, as it would generate a new object playing sound every frame the key is held.

Ah good point, was looking at the input rather than the audio.

Oops, that was a typo, I did mean GetKey. And StarManta, you’re right, it would restart the sound every frame. Sheesh, that’s what I get for posting before breakfast. Apologies for the confusion! StarManta’s version looks correct to me.

Unknown identifier: ‘audioSource’.

Should be capitalized I guess.

Ok. Capitalized. Now I have 2 errors from that.

"Unknown identifier ‘audioSource’ (From the “AudioSource.Stop())”

&

“An instance of type ‘UnityEngine.AudioSource’ is required to access non static member ‘Stop’.” from “AudioSource.Stop” also…

Ok I messed around with it a little and I can’t get past the “AudioSource.Stop()” error. It says " An instance of type ‘UnityEngine.AudioSource’ is required to access non static member ‘Stop’."

…oh, right. OK, you’re going to have to implement a bit of your own version of PlayClipAtPoint, one that returns the generated AudioSource. Basically PlayClipAtPoint creates a temporary GameObject with an AudioSource, then throws it to the wind to do its thing.

Something like this:

public static AudioSource PlayClipAtPointImproved(AudioClip clip, Vector3 position) {
GameObject newGO = new GameObject("AudioSource for "+clip.name);
AudioSource rtn = newGO.AddComponent<AudioSource>();
rtn.clip = clip;
rtn.Play();
return rtn;
}

private AudioSource storedSource;
void Update() {
if (Input.GetKeyDown(KeyCode.W)) {
    storedSource = PlayClipAtPointImproved(walkingoutside, transform.position);
}
if (Input.GetKeyUp(KeyCode.W) && storedSource) {
    storedSource.Stop();
Destroy(storedSource.gameObject);
}
}