Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Stopping a part of another script

Discussion in 'Scripting' started by rennster200, Mar 20, 2021.

  1. rennster200

    rennster200

    Joined:
    Jun 21, 2019
    Posts:
    65
    Hello everyone, so... I have a problem with stopping the walk animation when the attack button is pressed(android game). I was thinking about doing it with GetComponent<> method but I don't really know how. Basically, all I want to do is that when my character is moving and I press attack button, I want him to stop moving until attack animation is done(currently when I move and click button on screen for attack, he does attack animation and moves). I have 3 scripts: 1st for combat-melee attack, 2nd for movement using joystick and 3rd for character controller. I also have animator component attached which works perfectly.
    Do I have to write some code or change something in animator?
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class PlayerMovement : MonoBehaviour {
    6.  
    7.     public CharacterController2D controller;
    8.  
    9.     public float runSpeed = 40f;
    10.     public Animator animator;
    11.     float horizontalMove = 0f;
    12.     public Joystick joystick;
    13.     bool jump = false;
    14.     bool crouch = false;
    15.  
    16.     // Update is called once per frame
    17.     void Update () {
    18.      
    19. if (joystick.Horizontal >= .2f)
    20.         {
    21.             horizontalMove = runSpeed;
    22.         }else if(joystick.Horizontal <= -.2f)
    23.         {
    24.             horizontalMove = -runSpeed;
    25.         }else
    26.         {
    27.             horizontalMove = 0f;
    28.         }
    29.  
    30.         animator.SetFloat("Speed", Mathf.Abs(horizontalMove));
    31.         if (Input.GetButtonDown("Jump"))
    32.         {
    33.             jump = true;
    34.         }
    35.  
    36.         if (Input.GetButtonDown("Crouch"))
    37.         {
    38.             crouch = true;
    39.         } else if (Input.GetButtonUp("Crouch"))
    40.         {
    41.             crouch = false;
    42.         }
    43.  
    44.     }
    45.  
    46.     void FixedUpdate ()
    47.     {
    48.         // Move our character
    49.         controller.Move(horizontalMove * Time.fixedDeltaTime, crouch, jump);
    50.         jump = false;
    51.    
    52.     }
    53. }
    54.  
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using System;
    5. using UnityEngine.UI;
    6.  
    7. public class PlayerCombat : MonoBehaviour
    8. {
    9.     public Animator animator;
    10.  
    11.     public Transform attackPoint;
    12.     public LayerMask enemyLayers;
    13.  
    14.     public Button attackButton; //gumb za attack
    15.     public float attackRange = 0.5f;
    16.     public int attackDamage = 40;
    17.  
    18.     public float attackRate = 1f;  //broj udaraca u sekundi koje možemo zadati
    19.     float nextAttackTime = 0f;
    20.  
    21.     void Start()
    22.     {
    23.         Button btn = attackButton.GetComponent<Button>();
    24.         btn.onClick.AddListener(Attack); //ako je button pritisnut pokreni sekvencu attack dolje
    25.  
    26.     }
    27.  
    28.     void Attack()
    29.     {
    30.         if (Time.time >= nextAttackTime)
    31.         {
    32.             nextAttackTime = Time.time + 1f / attackRate;
    33.             //punch animacija
    34.             animator.SetTrigger("Attack");
    35.  
    36.             //je li u range-u napada
    37.             Collider2D[] hitEnemies = Physics2D.OverlapCircleAll(attackPoint.position, attackRange, enemyLayers);
    38.  
    39.             //oduzeti im health
    40.             foreach (Collider2D enemy in hitEnemies)
    41.             {
    42.                 enemy.GetComponent<Enemy>().TakeDamage(attackDamage);
    43.             }
    44.         }
    45.          
    46.     }
    47.     void OnDrawGizmosSelected()
    48.         {
    49.             if (attackPoint == null)
    50.                 return;
    51.  
    52.             Gizmos.DrawWireSphere(attackPoint.position, attackRange);
    53.         }
    54.  
    55. }
    56.  
    Code (csharp):
    1.  
    2. using UnityEngine;
    3.  
    4. public class CharacterController2D : MonoBehaviour
    5. {
    6.     [SerializeField] private float m_JumpForce = 400f;                            // Amount of force added when the player jumps.
    7.     [Range(0, 1)] [SerializeField] private float m_CrouchSpeed = .36f;            // Amount of maxSpeed applied to crouching movement. 1 = 100%
    8.     [Range(0, .3f)] [SerializeField] private float m_MovementSmoothing = .05f;    // How much to smooth out the movement
    9.     [SerializeField] private bool m_AirControl = false;                            // Whether or not a player can steer while jumping;
    10.     [SerializeField] private LayerMask m_WhatIsGround;                            // A mask determining what is ground to the character
    11.     [SerializeField] private Transform m_GroundCheck;                            // A position marking where to check if the player is grounded.
    12.     [SerializeField] private Transform m_CeilingCheck;                            // A position marking where to check for ceilings
    13.     [SerializeField] private Collider2D m_CrouchDisableCollider;                // A collider that will be disabled when crouching
    14.  
    15.     const float k_GroundedRadius = .2f; // Radius of the overlap circle to determine if grounded
    16.     private bool m_Grounded;            // Whether or not the player is grounded.
    17.     const float k_CeilingRadius = .2f; // Radius of the overlap circle to determine if the player can stand up
    18.     private Rigidbody2D m_Rigidbody2D;
    19.     private bool m_FacingRight = true;  // For determining which way the player is currently facing.
    20.     private Vector3 velocity = Vector3.zero;
    21.  
    22.     private void Awake()
    23.     {
    24.         m_Rigidbody2D = GetComponent<Rigidbody2D>();
    25.     }
    26.  
    27.  
    28.     private void FixedUpdate()
    29.     {
    30.         m_Grounded = false;
    31.  
    32.         // The player is grounded if a circlecast to the groundcheck position hits anything designated as ground
    33.         // This can be done using layers instead but Sample Assets will not overwrite your project settings.
    34.         Collider2D[] colliders = Physics2D.OverlapCircleAll(m_GroundCheck.position, k_GroundedRadius, m_WhatIsGround);
    35.         for (int i = 0; i < colliders.Length; i++)
    36.         {
    37.             if (colliders.gameObject != gameObject)
    38.                 m_Grounded = true;
    39.         }
    40.     }
    41.  
    42.  
    43.     public void Move(float move, bool crouch, bool jump)
    44.     {
    45.         // If crouching, check to see if the character can stand up
    46.         if (!crouch)
    47.         {
    48.             // If the character has a ceiling preventing them from standing up, keep them crouching
    49.             if (Physics2D.OverlapCircle(m_CeilingCheck.position, k_CeilingRadius, m_WhatIsGround))
    50.             {
    51.                 crouch = true;
    52.             }
    53.         }
    54.  
    55.         //only control the player if grounded or airControl is turned on
    56.         if (m_Grounded || m_AirControl)
    57.         {
    58.  
    59.             // If crouching
    60.             if (crouch)
    61.             {
    62.                 // Reduce the speed by the crouchSpeed multiplier
    63.                 move *= m_CrouchSpeed;
    64.  
    65.                 // Disable one of the colliders when crouching
    66.                 if (m_CrouchDisableCollider != null)
    67.                     m_CrouchDisableCollider.enabled = false;
    68.             } else
    69.             {
    70.                 // Enable the collider when not crouching
    71.                 if (m_CrouchDisableCollider != null)
    72.                     m_CrouchDisableCollider.enabled = true;
    73.             }
    74.  
    75.             // Move the character by finding the target velocity
    76.             Vector3 targetVelocity = new Vector2(move * 10f, m_Rigidbody2D.velocity.y);
    77.             // And then smoothing it out and applying it to the character
    78.             m_Rigidbody2D.velocity = Vector3.SmoothDamp(m_Rigidbody2D.velocity, targetVelocity, ref velocity, m_MovementSmoothing);
    79.  
    80.             // If the input is moving the player right and the player is facing left...
    81.             if (move > 0 && !m_FacingRight)
    82.             {
    83.                 // ... flip the player.
    84.                 Flip();
    85.             }
    86.             // Otherwise if the input is moving the player left and the player is facing right...
    87.             else if (move < 0 && m_FacingRight)
    88.             {
    89.                 // ... flip the player.
    90.                 Flip();
    91.             }
    92.         }
    93.         // If the player should jump...
    94.         if (m_Grounded && jump)
    95.         {
    96.             // Add a vertical force to the player.
    97.             m_Grounded = false;
    98.             m_Rigidbody2D.AddForce(new Vector2(0f, m_JumpForce));
    99.         }
    100.     }
    101.  
    102.  
    103.     private void Flip()
    104.     {
    105.         // Switch the way the player is labelled as facing.
    106.         m_FacingRight = !m_FacingRight;
    107.  
    108.         // Multiply the player's x local scale by -1.
    109.         Vector3 theScale = transform.localScale;
    110.         theScale.x *= -1;
    111.         transform.localScale = theScale;
    112.     }
    113. }
    114.  
     
  2. seejayjames

    seejayjames

    Joined:
    Jan 28, 2013
    Posts:
    685
    You just have to check whether that condition is true when you either 1) determine the move speed or 2) when you actually do the movement. So the move speed could be set to 0 during that condition, or you can calculate it as usual but simply don't actually move the player. Either should work.
     
  3. rennster200

    rennster200

    Joined:
    Jun 21, 2019
    Posts:
    65
    Thanks for reply... But how am I able to do this if tgey are 2 seperate scripts?
     
  4. Mashimaro7

    Mashimaro7

    Joined:
    Apr 10, 2020
    Posts:
    723
    It's better to use parameters, add parameters in your animator. Here's what my animator looks like,
    upload_2021-3-21_16-14-58.png
    Probably not the neatest one haha, but I have a float parameter, if the speed is higher than a certain amount it will transition to the swim animation, if it runs into an enemy it can eat, it switches the bool "biting" to true, which transitions to the Bite animation.

    You can set these parameters using animator.SetBool() or animator.SetFloat(), in the brackets, pass in the name of the bool or float, and the value. And then you can add conditions such as,
    upload_2021-3-21_16-17-59.png
    if biting is true, and stunned is false, then it will transition to the biting animation.

    Edit: not a big fan of Brackeys, but he has a good tutorial on animations,

    head to the 5:30 mark or so
     
  5. rennster200

    rennster200

    Joined:
    Jun 21, 2019
    Posts:
    65
    Thanks :)
     
    Mashimaro7 likes this.
  6. Mashimaro7

    Mashimaro7

    Joined:
    Apr 10, 2020
    Posts:
    723
    No problem :)
     
  7. rennster200

    rennster200

    Joined:
    Jun 21, 2019
    Posts:
    65
    Ok so here is a little update: I decided to add Speed lesser/greater value to my combat. In animator, when speed is less than 0.01 it plays attack animation but... When I run, and click button for attack, my Attack trigger is on and its not attacking until the speed hits 0. I want attack trigger not to go on after going to idle. Myb its confusing but...
    1.He runs
    2.I click attack button, he is not attacking, attack trigger is on
    3.when I stop running the attack animation plays-->trigger waits until I stop running
    I want him to reset if at the moment of pressing attack button he is running..
    Any thoughts?
    Thanks
     
  8. Mashimaro7

    Mashimaro7

    Joined:
    Apr 10, 2020
    Posts:
    723
    It's better to have a bool, so just set it to attacking animation if "attacking" and set the movement animation if !attacking, and speed is greater than a certain amount. So don't check for speed when attacking
     
  9. rennster200

    rennster200

    Joined:
    Jun 21, 2019
    Posts:
    65
    Ok...I must be really stupid or something bc I am not able to do this...
    tbh I don't really know much about C#
     
  10. Mashimaro7

    Mashimaro7

    Joined:
    Apr 10, 2020
    Posts:
    723
    It's okay, what are you having trouble with? You can just set the animator to only transition to walking animation while attacking is false. In your attack method, I assume you're using a coroutine, set the animator's attacking bool to true when the attack starts, then set it to false when the attack ends.
     
  11. rennster200

    rennster200

    Joined:
    Jun 21, 2019
    Posts:
    65
    I am struggling with where should I put what to make this work... I tried setting bool attacking true from any state when button is pressed if speed is lesser than 0.01(0)... I dont know what to put where... Can you help me with the code itself and animator?
     
  12. rennster200

    rennster200

    Joined:
    Jun 21, 2019
    Posts:
    65
    I was thinking if you could edit my code a little bit in order to work. I would be grateful
     
  13. rennster200

    rennster200

    Joined:
    Jun 21, 2019
    Posts:
    65
    A
    Actually I dont know how to check if bool is true or false...
    if(animator.GetBool("AbleToAttack") =true) and then attack

    I dont know if I wrote this well...
    And in movement part, i set animator.SetBool("AbleToAttack")=true or false depending if there is movement or not.
    Now I dont know if I should put bool AbleToAttack = false; in void start or in the beginning or nowhere at all...
     
  14. Mashimaro7

    Mashimaro7

    Joined:
    Apr 10, 2020
    Posts:
    723
    Oh, you shouldn't be checking if the animator's bool is true or false, make a bool variable in your script that's completely separate from your animator's parameter.

    Sorry, when I have some free time I'll take a look at your code and see what I can write up for you :)
     
  15. rennster200

    rennster200

    Joined:
    Jun 21, 2019
    Posts:
    65
    Thank you very much
     
  16. Mashimaro7

    Mashimaro7

    Joined:
    Apr 10, 2020
    Posts:
    723
    Sorry for the lateness, I was distracted with work and totally forgot haha.

    If you want to debug your animator, you can open it up in the Unity Editor while the game is running, you can even put it beside the game window.

    You should set it to a bool and set it to false like this, if I'm understanding your code correctly,
    Code (CSharp):
    1.     void Attack()
    2.     {
    3.         if (Time.time >= nextAttackTime)
    4.         {
    5.             nextAttackTime = Time.time + 1f / attackRate;
    6.             //punch animacija
    7.             animator.SetBool("Attack", true);
    8.  
    9.             //je li u range-u napada
    10.             Collider2D[] hitEnemies = Physics2D.OverlapCircleAll(attackPoint.position, attackRange, enemyLayers);
    11.  
    12.             //oduzeti im health
    13.             foreach (Collider2D enemy in hitEnemies)
    14.             {
    15.                 enemy.GetComponent<Enemy>().TakeDamage(attackDamage);
    16.             }
    17.         }
    18.         else if(animator.GetBool("Attack") == true)
    19.         {
    20.             animator.SetBool("Attack", false);
    21.         }
    22.  
    23.     }
    Sorry, I'm not 100% sure how triggers work, you could swap it out for a bool.

    Now that I look at your code more closely, when are you counting up this timer? There's no references to the timer in any of your update methods, unless I'm just blind haha.
     
  17. rennster200

    rennster200

    Joined:
    Jun 21, 2019
    Posts:
    65
    Time.time is time passed in real life i think... Sorry, I was following up Brackeys tutorial on combat so thats it..
    So I basically need to replace attack trigger to bool in animator and at the beginning of my script put bool Attack;
    Am I right? Or I dont have to put a reference to a bool
    Thanks tho for your help, means a lot me
     
  18. rennster200

    rennster200

    Joined:
    Jun 21, 2019
    Posts:
    65
    Okay, I did what you wrote but when button is pressed, it just stops at that state waiting for me manually to untick bool in animator and then it plays animation
     
  19. Mashimaro7

    Mashimaro7

    Joined:
    Apr 10, 2020
    Posts:
    723
    Ah, I see, this is keeping track of when the next attack can occur only, sorry I wasn't thinking lol. However, this code has no way of making an attack that stays for a set period of time or stops the animator. I think it would be best to use a coroutine. Something like this,

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using System;
    5. using UnityEngine.UI;
    6. public class PlayerCombat : MonoBehaviour
    7. {
    8.     public Animator animator;
    9.  
    10.     public Transform attackPoint;
    11.     public LayerMask enemyLayers;
    12.  
    13.     public Button attackButton; //gumb za attack
    14.     public float attackRange = 0.5f;
    15.     public int attackDamage = 40;
    16.  
    17.     public float attackRate = 1f;  //broj udaraca u sekundi koje možemo zadati
    18.     bool canAttack;
    19.  
    20.  
    21.     void Start()
    22.     {
    23.         Button btn = attackButton.GetComponent<Button>();
    24.         btn.onClick.AddListener(Attack); //ako je button pritisnut pokreni sekvencu attack dolje
    25.  
    26.     }
    27.  
    28.     void Attack()
    29.     {
    30.         if (canAttack)
    31.         {
    32.             StartCoroutine(AttackRoutine());
    33.         }
    34.  
    35.     }
    36.     IEnumerator AttackRoutine()
    37.     {
    38.         canAttack = false;
    39.         animator.SetBool("Attacking", true);
    40.  
    41.         Collider2D[] hitEnemies = Physics2D.OverlapCircleAll(attackPoint.position, attackRange, enemyLayers);
    42.  
    43.  
    44.         foreach (Collider2D enemy in hitEnemies)
    45.         {
    46.             enemy.GetComponent<Enemy>().TakeDamage(attackDamage);
    47.         }
    48.  
    49.         yield return new WaitForSeconds(attackRate);
    50.         canAttack = true;
    51.         animator.SetBool("Attacking", false);
    52.     }
    53.  
    54.     void OnDrawGizmosSelected()
    55.     {
    56.         if (attackPoint == null)
    57.             return;
    58.  
    59.         Gizmos.DrawWireSphere(attackPoint.position, attackRange);
    60.     }
    61.  
    62. }
    63.  
    Then in your animator, make a transition to your walking animation, and make it "if attacking == false" and make a transition from any state to attacking, if attacking is true.

    I'll be honest, I don't really think Brackeys is very good lol, some of his tutorials are good for learning from, but a lot of his tutorials are not very flexible. I remember learning cameras from him, and he ended the tutorial saying he didn't know why the camera jittered, and if someone could teach him why he'd appreciate it :/ lol
     
  20. rennster200

    rennster200

    Joined:
    Jun 21, 2019
    Posts:
    65
    Thank you for ur help put its still not working :/
    I will try to slow down his speed at least when he is attacking
     
  21. Mashimaro7

    Mashimaro7

    Joined:
    Apr 10, 2020
    Posts:
    723
    What's not working? Did you set the bools and transitions in the animator? Speed should be easy, create a second speed variable in the player, make it public, and change the players speed to that when you're attacking through your attack script. Make a third speed variable, so you can have runSpeed, speedWhileAttacking, speed. Set the speed to run speed when not atttacking, and speedWhileAttacking while attacking.
     
  22. rennster200

    rennster200

    Joined:
    Jun 21, 2019
    Posts:
    65
    I DID IT!!!
    Code (CSharp):
    1. void Update()
    2.     {
    3.  
    4.         if (joystick.Horizontal >= .2f)
    5.         {
    6.             if(animator.GetCurrentAnimatorStateInfo(0).IsName("Attack"))
    7.             {
    8.                 horizontalMove = speedwhileattacking;
    9.             }
    10.             else
    11.             {
    12.             horizontalMove = runSpeed;
    13.             }
    14.         }
    15.         else if (joystick.Horizontal <= -.2f)
    16.         {
    17.             if (animator.GetCurrentAnimatorStateInfo(0).IsName("Attack"))
    18.             {
    19.                 horizontalMove = -speedwhileattacking;
    20.             }
    21.             else
    22.             {
    23.             horizontalMove = -runSpeed;
    24.             }
    25.         }
    26.         else
    27.         {
    28.  
    29.  
    30.             horizontalMove = 0f;
    31.  
    32.         }
    at the beginning of the script, I just set the speed while attacking to 0f and it worked :):):) And I also had to connect these 2 scripts into one...
    I was trying so hard the other day and was so close to letting this part of the controller slide away and continue to work on other stuff...Man, I didn't know that it would be an easy way...
    Thanks for everything!!!:D
     
    Mashimaro7 likes this.
  23. Mashimaro7

    Mashimaro7

    Joined:
    Apr 10, 2020
    Posts:
    723
    No problem! I'm glad you got it to work!

    I just thought, if you wanted a good tutorial for learning game design with Unity, check out this series!



    Happy coding :)
     
  24. rennster200

    rennster200

    Joined:
    Jun 21, 2019
    Posts:
    65
    I will, thanks!
    Take care
     
    Mashimaro7 likes this.