Stopping a part of another script

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?

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerMovement : MonoBehaviour {

    public CharacterController2D controller;

    public float runSpeed = 40f;
    public Animator animator;
    float horizontalMove = 0f;
    public Joystick joystick;
    bool jump = false;
    bool crouch = false;
  
    // Update is called once per frame
    void Update () {
      
if (joystick.Horizontal >= .2f)
        {
            horizontalMove = runSpeed;
        }else if(joystick.Horizontal <= -.2f)
        {
            horizontalMove = -runSpeed;
        }else
        {
            horizontalMove = 0f;
        }

        animator.SetFloat("Speed", Mathf.Abs(horizontalMove));
        if (Input.GetButtonDown("Jump"))
        {
            jump = true;
        }

        if (Input.GetButtonDown("Crouch"))
        {
            crouch = true;
        } else if (Input.GetButtonUp("Crouch"))
        {
            crouch = false;
        }

    }

    void FixedUpdate ()
    {
        // Move our character
        controller.Move(horizontalMove * Time.fixedDeltaTime, crouch, jump);
        jump = false;
    
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using UnityEngine.UI;

public class PlayerCombat : MonoBehaviour
{
    public Animator animator;
  
    public Transform attackPoint;
    public LayerMask enemyLayers;

    public Button attackButton; //gumb za attack
    public float attackRange = 0.5f;
    public int attackDamage = 40;
 
    public float attackRate = 1f;  //broj udaraca u sekundi koje možemo zadati
    float nextAttackTime = 0f;

    void Start()
    {
        Button btn = attackButton.GetComponent<Button>();
        btn.onClick.AddListener(Attack); //ako je button pritisnut pokreni sekvencu attack dolje

    }
 
    void Attack()
    {
        if (Time.time >= nextAttackTime)
        {
            nextAttackTime = Time.time + 1f / attackRate;
            //punch animacija
            animator.SetTrigger("Attack");

            //je li u range-u napada
            Collider2D[] hitEnemies = Physics2D.OverlapCircleAll(attackPoint.position, attackRange, enemyLayers);

            //oduzeti im health
            foreach (Collider2D enemy in hitEnemies)
            {
                enemy.GetComponent<Enemy>().TakeDamage(attackDamage);
            }
        }
          
    }
    void OnDrawGizmosSelected()
        {
            if (attackPoint == null)
                return;

            Gizmos.DrawWireSphere(attackPoint.position, attackRange);
        }
  
}
using UnityEngine;

public class CharacterController2D : MonoBehaviour
{
    [SerializeField] private float m_JumpForce = 400f;                            // Amount of force added when the player jumps.
    [Range(0, 1)] [SerializeField] private float m_CrouchSpeed = .36f;            // Amount of maxSpeed applied to crouching movement. 1 = 100%
    [Range(0, .3f)] [SerializeField] private float m_MovementSmoothing = .05f;    // How much to smooth out the movement
    [SerializeField] private bool m_AirControl = false;                            // Whether or not a player can steer while jumping;
    [SerializeField] private LayerMask m_WhatIsGround;                            // A mask determining what is ground to the character
    [SerializeField] private Transform m_GroundCheck;                            // A position marking where to check if the player is grounded.
    [SerializeField] private Transform m_CeilingCheck;                            // A position marking where to check for ceilings
    [SerializeField] private Collider2D m_CrouchDisableCollider;                // A collider that will be disabled when crouching

    const float k_GroundedRadius = .2f; // Radius of the overlap circle to determine if grounded
    private bool m_Grounded;            // Whether or not the player is grounded.
    const float k_CeilingRadius = .2f; // Radius of the overlap circle to determine if the player can stand up
    private Rigidbody2D m_Rigidbody2D;
    private bool m_FacingRight = true;  // For determining which way the player is currently facing.
    private Vector3 velocity = Vector3.zero;

    private void Awake()
    {
        m_Rigidbody2D = GetComponent<Rigidbody2D>();
    }


    private void FixedUpdate()
    {
        m_Grounded = false;

        // The player is grounded if a circlecast to the groundcheck position hits anything designated as ground
        // This can be done using layers instead but Sample Assets will not overwrite your project settings.
        Collider2D[] colliders = Physics2D.OverlapCircleAll(m_GroundCheck.position, k_GroundedRadius, m_WhatIsGround);
        for (int i = 0; i < colliders.Length; i++)
        {
            if (colliders.gameObject != gameObject)
                m_Grounded = true;
        }
    }


    public void Move(float move, bool crouch, bool jump)
    {
        // If crouching, check to see if the character can stand up
        if (!crouch)
        {
            // If the character has a ceiling preventing them from standing up, keep them crouching
            if (Physics2D.OverlapCircle(m_CeilingCheck.position, k_CeilingRadius, m_WhatIsGround))
            {
                crouch = true;
            }
        }

        //only control the player if grounded or airControl is turned on
        if (m_Grounded || m_AirControl)
        {

            // If crouching
            if (crouch)
            {
                // Reduce the speed by the crouchSpeed multiplier
                move *= m_CrouchSpeed;

                // Disable one of the colliders when crouching
                if (m_CrouchDisableCollider != null)
                    m_CrouchDisableCollider.enabled = false;
            } else
            {
                // Enable the collider when not crouching
                if (m_CrouchDisableCollider != null)
                    m_CrouchDisableCollider.enabled = true;
            }

            // Move the character by finding the target velocity
            Vector3 targetVelocity = new Vector2(move * 10f, m_Rigidbody2D.velocity.y);
            // And then smoothing it out and applying it to the character
            m_Rigidbody2D.velocity = Vector3.SmoothDamp(m_Rigidbody2D.velocity, targetVelocity, ref velocity, m_MovementSmoothing);

            // If the input is moving the player right and the player is facing left...
            if (move > 0 && !m_FacingRight)
            {
                // ... flip the player.
                Flip();
            }
            // Otherwise if the input is moving the player left and the player is facing right...
            else if (move < 0 && m_FacingRight)
            {
                // ... flip the player.
                Flip();
            }
        }
        // If the player should jump...
        if (m_Grounded && jump)
        {
            // Add a vertical force to the player.
            m_Grounded = false;
            m_Rigidbody2D.AddForce(new Vector2(0f, m_JumpForce));
        }
    }


    private void Flip()
    {
        // Switch the way the player is labelled as facing.
        m_FacingRight = !m_FacingRight;

        // Multiply the player's x local scale by -1.
        Vector3 theScale = transform.localScale;
        theScale.x *= -1;
        transform.localScale = theScale;
    }
}

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.

Thanks for reply… But how am I able to do this if tgey are 2 seperate scripts?

It’s better to use parameters, add parameters in your animator. Here’s what my animator looks like,


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,


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

Thanks :slight_smile:

1 Like

No problem :slight_smile:

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

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

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#

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.

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?

I was thinking if you could edit my code a little bit in order to work. I would be grateful

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…

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 :slight_smile:

Thank you very much

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,

    void Attack()
    {
        if (Time.time >= nextAttackTime)
        {
            nextAttackTime = Time.time + 1f / attackRate;
            //punch animacija
            animator.SetBool("Attack", true);

            //je li u range-u napada
            Collider2D[] hitEnemies = Physics2D.OverlapCircleAll(attackPoint.position, attackRange, enemyLayers);

            //oduzeti im health
            foreach (Collider2D enemy in hitEnemies)
            {
                enemy.GetComponent<Enemy>().TakeDamage(attackDamage);
            }
        }
        else if(animator.GetBool("Attack") == true)
        {
            animator.SetBool("Attack", false);
        }

    }

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.

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

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

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,

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using UnityEngine.UI;
public class PlayerCombat : MonoBehaviour
{
    public Animator animator;

    public Transform attackPoint;
    public LayerMask enemyLayers;

    public Button attackButton; //gumb za attack
    public float attackRange = 0.5f;
    public int attackDamage = 40;

    public float attackRate = 1f;  //broj udaraca u sekundi koje možemo zadati
    bool canAttack;


    void Start()
    {
        Button btn = attackButton.GetComponent<Button>();
        btn.onClick.AddListener(Attack); //ako je button pritisnut pokreni sekvencu attack dolje

    }

    void Attack()
    {
        if (canAttack)
        {
            StartCoroutine(AttackRoutine());
        }

    }
    IEnumerator AttackRoutine()
    {
        canAttack = false;
        animator.SetBool("Attacking", true);

        Collider2D[] hitEnemies = Physics2D.OverlapCircleAll(attackPoint.position, attackRange, enemyLayers);


        foreach (Collider2D enemy in hitEnemies)
        {
            enemy.GetComponent<Enemy>().TakeDamage(attackDamage);
        }

        yield return new WaitForSeconds(attackRate);
        canAttack = true;
        animator.SetBool("Attacking", false);
    }

    void OnDrawGizmosSelected()
    {
        if (attackPoint == null)
            return;

        Gizmos.DrawWireSphere(attackPoint.position, attackRange);
    }

}

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 :confused: lol

Thank you for ur help put its still not working :confused:
I will try to slow down his speed at least when he is attacking