How do I make an attack animation and sound play once per click?

Hey,
I a script to fully animate my character, but when I press my attack button in only plays the attack animation while the attack button is pressed instead of following through with the whole animation. Than with the sound it plays it 10 times a second.

How do I fix this? I’m not pro with programming so I don’t know how to limit the animation to play once through. With the sound I could just make a timer that limits it that way correct?

I’d be ideal if I could have an adjustable timer so I could control the amount of time it takes to play the animation so I could copy that command and adjust it for other attacks/spells when I’ve created them.

Here’s my animation script:

var swingSound : AudioClip;

function Start ()
{
   // Set all animations to loop
   animation.wrapMode = WrapMode.Loop;
   // except shooting
   animation["shoot"].wrapMode = WrapMode.Loop;

   //   animations when faded in.
   animation["shoot"].layer = 0;
   // Stop animations that are already playing
   //(In case user forgot to disable play automatically)
   animation.Stop();
}

function Update () {
   // Based on the key that is pressed,
   // play the walk animation or the idle animation
   if (Mathf.Abs(Input.GetAxis("Vertical")) > 0.1)
      animation.CrossFade("walk");
   else
      animation.CrossFade("idle");
	  
	  if (Mathf.Abs(Input.GetAxis("Horizontal")) > 0.1)
	 animation.CrossFade("side");
 
   if (Mathf.Abs(Input.GetAxis("Fire1")) > 0.1)
	  animation.CrossFade("shoot");
	  
   // Shoot
   if (Input.GetButton ("Fire1")) 
            animation.Play("shoot"); 
   else 
            animation.Stop("shoot");

}

?

But anyway…

private var isShooting : boolean = false;

function Update()
{
	if (Input.GetButton ("Fire1")) 
	{	
		if(!isShooting)
		{
			playShooting();
		}
	}
}

private function playShooting()
{
	isShooting = true;
	animation.Play("shoot"); 
	// add sound playng here. NOT looping.
	yield WaitForSeconds(animation["shoot"].length);
	
	animation.CrossFade("idle"); 
	isShooting = false;
}

should give out the general principle.

animation[“shoot”].wrapMode = WrapMode.Once;

and

layer>default is all you need

@amduartev I tried the WrapMode.Once and it didn’t work.

@VonCede I know it was looped, but I ran it anyways because I didn’t want get any errors till I figured this out. As for the code you gave me thanks I appreciate it, but I don’t know where to put it in. If you could show me than I’d learn how to do it.

Thanks

Anyone?

This ain’t going to work.
If you are an artist, look for a programmer.
If you are a Programmer, learn basic programming first (not unity specific).

The Code, that is causing this behaviour is this part:

   if (Mathf.Abs(Input.GetAxis("Fire1")) > 0.1)
	  animation.CrossFade("shoot");
	  
   // Shoot
   if (Input.GetButton ("Fire1")) 
            animation.Play("shoot"); 
   else 
            animation.Stop("shoot");

Now a simple solution was posted up there.
I am going to help you out this once.
But seriously take my advice in the first sentence.

Change your Update Function

function Update()
{
//....

// Do all your Movement and Jumping Stuff here

//....



// Now check if the User want's to shoot
	if (Input.GetButton ("Fire1")) 
	{	

                // If the User isn't already shooting. Start Shooting, else Ignore the below
		if(!isShooting)
		{
			playShooting();
		}
	}
}

//Put this anywhere in the Class (File)

private var isShooting : boolean = false;

private function playShooting()
{
	isShooting = true;
	animation.Play("shoot"); 
	// add sound playng here. NOT looping.
	yield WaitForSeconds(animation["shoot"].length);
	
	animation.CrossFade("idle"); 
	isShooting = false;
}

Okay I appreciate the help but I added the code like you said and I got a few errors.

Some were syntax and the other didn’t recognize private you know this is js right? As I said before I’m not much of a programmer and I’m slowly learning everyone starts somewhere…

function Update () {
   // Based on the key that is pressed,
   // play the walk animation or the idle animation
   if (Mathf.Abs(Input.GetAxis("Vertical")) > 0.1)
      animation.CrossFade("walk");
   else
      animation.CrossFade("idle");
	  
   if (Mathf.Abs(Input.GetAxis("Horizontal")) > 0.1)
	 animation.CrossFade("side");
	
	// Now check if the User want's to shoot
   if (Input.GetButton ("Fire1")) 
	{	
		private var isShooting : boolean = false;

	private function playShooting()
	{
	isShooting = true;
	animation.Play("shoot"); 
	// add sound playng here. NOT looping.
	yield WaitForSeconds(animation["shoot"].length);
	
	animation.CrossFade("idle"); 
	isShooting = false;
	}
//var swingSound : AudioClip;

// Add audio source to your character or you crossbow. Or rifle. or sword. Much easier than isntantiateing ait on the fy and then
// adding the audio clip on it. Make sure that audioSource is not looping and not playing sound on start.
var SwingSoundSource : AudioSource; 

//private makes variable or function invisible oustide from script.
// For example if you remove private from this variable, it makes it public and you can edit it from editor.
// functions are hidden from outside and can only be called from this script.
// more information private/public system can be learned from any Object Oriented programming amnual.
private var isShooting : boolean = false;
 

function Update () 
{
	// Based on the key that is pressed,
	// play the walk animation or the idle animation
	if (Mathf.Abs(Input.GetAxis("Vertical")) > 0.1)
		animation.CrossFade("walk");
	else
		animation.CrossFade("idle");
	  
	if (Mathf.Abs(Input.GetAxis("Horizontal")) > 0.1)
		animation.CrossFade("side");
 
	// Shoot
	if (Input.GetButton ("Fire1")) 
	{	
		if(!isShooting)
		{
			playShooting();
		}
	}
}

// This is private function it can be only called from this script. 
// Also, since it contains yield statement it is a coroutine. They are your friends, When you get your head wrapped around the states and timers.
private function playShooting()
{
	isShooting = true;
	animation.Play("shoot"); 
	SwingSoundSource.Play();
	yield WaitForSeconds(animation["shoot"].length);
	
	animation.CrossFade("idle"); 
	isShooting = false;
}

Thank you very much for your help I now get it. Everything works except when I swing it doesn’t play the full animation I think it’s just playing as long as the sound effect is playing which is under a second. How can I fix this I tried figuring it out but I’m stuck.

It’s somewhere in here:

private function playShooting()
{
	isShooting = true;
	animation.Play("shoot"); 
	SwingSoundSource.Play();
	yield WaitForSeconds(animation["shoot"].length);
	
	animation.CrossFade("idle"); 
	isShooting = false;
}

Or it could be the function start but it’s set to once so it should play through once. The animation clip is probably a little over a second.

function Start ()
{
   // Set all animations to loop
   animation.wrapMode = WrapMode.Loop;
   // except shooting
   animation["shoot"].wrapMode = WrapMode.Once;

   // Put idle and walk into lower layers (The default layer is always 0)
   // This will do two things
   // - Since shoot and idle/walk are in different layers they will not affect
   //   each other's playback when calling CrossFade.
   // - Since shoot is in a higher layer, the animation will replace idle/walk
   //   animations when faded in.
   animation["shoot"].layer = 0;
   // Stop animations that are already playing
   //(In case user forgot to disable play automatically)
   animation.Stop();
}

Anyone? I’m just stuck on this one part. How can I make the animation play through once?

Nm fixed it had to set the animation layer to 1