Search Unity

Loop animation through button presses - MegaMan X shooting

Discussion in 'Animation' started by MacazMania, Jul 26, 2022.

  1. MacazMania

    MacazMania

    Joined:
    Mar 26, 2022
    Posts:
    2
    Hi everyone,

    I'm making MegaMan X in Unity2D as a practice (still fairly new, have only made a few small games). I have movement and jumping sorted with animation, as well as shooting with animation.

    The problem is, I am trying to replicate Mega Man X where if you press shoot again while still in the shoot animation, it doesn't transition back to the idle animation. I can't for the life of me figure out how to achieve this.

    Any thoughts?
    This is what I currently have (achieves the goal of showing a shoot animation when mouse is clicked).


    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class PlayerShoot : MonoBehaviour
    6. {
    7.     private bool _isShooting = false;
    8.     Animator _anim;
    9.  
    10.     public Transform _firePoint;
    11.     public GameObject _bulletBasePrefab;
    12.  
    13.  
    14.     private void Awake()
    15.     {
    16.         _anim = GetComponent<Animator>();
    17.     }
    18.  
    19.     // Start is called before the first frame update
    20.     void Start()
    21.     {
    22.  
    23.     }
    24.  
    25.     // Update is called once per frame
    26.     void Update()
    27.     {
    28.         if (Input.GetButtonDown("Fire1"))
    29.         {
    30.             _anim.SetBool("isShooting", true);
    31.             Shoot();
    32.            
    33.         }
    34.     }
    35.  
    36.     IEnumerator ShootBoolFalse()
    37.     {
    38.         yield return new WaitForSeconds(0.3f);
    39.         _anim.SetBool("isShooting", false);
    40.     }
    41.  
    42.     void Shoot ()
    43.     {
    44.         Instantiate(_bulletBasePrefab, _firePoint.position, _firePoint.rotation);
    45.         StartCoroutine(ShootBoolFalse());
    46.        
    47.     }
    48.  
    49. }
    50.  
    51.  
     
  2. Pixelith

    Pixelith

    Joined:
    Jun 24, 2014
    Posts:
    580
    From what I've seen you don't really need a coroutine for this. I've modified the code a bit. I haven't tried it myself but its how I would first try this.
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. public class PlayerShoot : MonoBehaviour
    5. {
    6.     private bool _isShooting = false;
    7.     private float _buttonPressTimer = 0f;
    8.     Animator _anim;
    9.     public Transform _firePoint;
    10.     public GameObject _bulletBasePrefab;
    11.     private void Awake()
    12.     {
    13.         _anim = GetComponent<Animator>();
    14.     }
    15.     // Start is called before the first frame update
    16.     void Start()
    17.     {
    18.     }
    19.     // Update is called once per frame
    20.     void Update()
    21.     {
    22.         if (Input.GetButtonDown("Fire1"))
    23.         {
    24.             _buttonPressTimer = 1f;
    25.             Shoot();        
    26.         }
    27.          _buttonPressTimer = Mathf.Clamp(_buttonPressTimer-1f*Time.deltaTime,0,1f);
    28.          _isShooting = (_buttonPressTimer > 0) ? true : false;
    29.         _anim.SetBool("isShooting", _isShooting);
    30.     }
    31.     void Shoot ()
    32.     {
    33.         Instantiate(_bulletBasePrefab, _firePoint.position, _firePoint.rotation);
    34.     }
    35. }
    The way it should work is in update every time it detects your fire button, you set the time to 1f. We then subtract by Time.deltaTime * however fast you want this timer to run. _isShooting will be equal to true or false based on the timer, and the animator will have a bool set based on the _isShooting bool since I noticed that wasn't even used in the original script.
     
    MacazMania likes this.
  3. MacazMania

    MacazMania

    Joined:
    Mar 26, 2022
    Posts:
    2
    Worked perfectly, thank you so much. I'm like 50% sure I understand it, I'll study the code and your reply. Legend!
     
    Pixelith likes this.
  4. Pixelith

    Pixelith

    Joined:
    Jun 24, 2014
    Posts:
    580
    Just so I don't leave you hanging on explanation too much

    I basically used a bunch of shorthand to make the code cleaner
    Code (CSharp):
    1. _isShooting = (_buttonPressTimer > 0) ? true : false;
    2.  
    3. //Same as
    4.  
    5. if(_buttonPressTimer > 0){
    6. _isShooting = true;
    7. } else {
    8. _isShooting = false;
    9. }
    and Mathf.Clamp is just a nice way to make sure our timer stays withing the bounds of numbers between 0 and 1f.

    saying
    _buttonPressTimer-1f * Time.deltaTime 
    inside the clamp was a nice way of decreasing the timer without making a whole other line saying
    _buttonPressTimer-=1f * Time.deltaTime;
    .

    Just makes the code look a little cleaner :)