Mecanim bool parameter is staying true for too long

I made a simple gun with a simple shoot animation. I’m using the mecanim animation system to handle the animation. I have dragged an idle animation to the window, which is the default state, and I dragged the shooting animation. The transition from idle to shoot happens when a bool parameter called “Shot” is set to true.

My problem is that Shot stays true for too long and my shooting animation is 4 frames long. As a result, my shooting animation loops 3 times. I tried handling the parameter like in the mecanim tutorial, but it didn’t help. I tried making the bool parameter false immediately after making it true, but then it doesn’t play at all.

EDIT: I uploaded the project file here(it’s really small): Dropbox - File Deleted - Simplify your life

This is what my code looks like currently:

private Animator anim;
	static int shootState = Animator.StringToHash("Base Layer.Shoot");	

	private AnimatorStateInfo currentBaseState;
	
	void Start () {
		anim = gameObject.GetComponent<Animator>();
	}

	private bool canShoot = true;
	
	void Update () {
		
	    currentBaseState = anim.GetCurrentAnimatorStateInfo(0);
		
		if(Input.GetButtonDown("Fire1"))
		{
			if(canShoot)
			{
				canShoot = false;
				anim.SetBool("Shot",true);
			}
		}
		else if(currentBaseState.nameHash == shootState)
		{
			anim.SetBool("Shot",false);	
		}
		else
		{
			canShoot = true;
		}
	}

You should be doing the comparison of the base state of the animator prior to checking for input. That way all your bools can be reset at the beginning of the frame and input can be checked afterwards. Currently, you are checking input first, which could potentially be causing the looping effect you are experience. Here is an example to try:

private Animator anim;
private bool canShoot;

// Animator states to track
static int shootState = Animator.StringToHash("Base Layer.Shoot");
static int idleState = Animator.StringToHash("Base Layer.Idle");
private AnimatorStateInfo currentBaseState;

 

void Start ()
{
	anim = gameObject.GetComponent<Animator>();
	canShoot = true;
}
 

void Update () 
{
	// Get the current base state of the animator 
	currentBaseState = anim.GetCurrentAnimatorStateInfo(0);

	// Check to see if we are in the shootState.
	// If so, the transition was obviously triggered
	// and the bool should be reset immediately
	if(currentBaseState.nameHash == shootState)
	{
		anim.SetBool("Shoot", false);
		canShoot = true;
		Debug.Log("All booleans reset");
	}

	// Now we check that the animator is in
	// the idle state
	if(currentBaseState.nameHash == idleState)
	{
		Debug.Log("Animator in Idle.  Player can shoot");

		// Now we can check for inputs and do our
		// check against canShoot that will alter
		// the animator state.  If the player hits
		// "Fire1" and canShoot is true, set canShoot
		if(Input.GetButtonDown("Fire1") && canShoot)
		{
			canShoot = false;
			anim.SetBool("Shot",true);
                        Debug.Log("You fired a shot.");
		}
		
		// Just for good measure we can set our
		// bools back to default values, though
		// this "else" statement, shouldn't be
		// necessary.  You can try it with or
		// without the following code.
		else
		{
			canShoot = true;
			anim.SetBool("Shot", false);
			Debug.Log("Redundant Check: Booleans reset");
		}
	}
}

Hope that helps you out. Let me know if the comments don’t make sense. Also, you could consider doing the input check on FixedUpdate() rather than Update() as well. If you want an example of that, let me know and I will edit accordingly.

EDIT:

“Exit Time” in the animators transition back to idle will not cause the animation to loop. When importing the animation make sure that the “Loop Pose” setting in “Animation Tab” of the corresponding model is not checked. Having this checked will cause the animation to loop until the transition is completed rather than running only once. Here is a link to the project with the correction in it: Shooting Animation Loop - fixed

You have to make it false after the transition has triggered, which is why setting it to false immediately didn’t work.

Try adding some Debug.Log lines. Are you sure that the state name is correct? Is it ever getting to the animSetBool(“Shot”,false); line?