Forum begins after the advertisement:


[Part 3] Player attacks twice

Home Forums Video Game Tutorial Series Creating a Metroidvania in Unity [Part 3] Player attacks twice

Viewing 4 posts - 1 through 4 (of 4 total)
  • Author
    Posts
  • #11925
    Samuel Morgan
    Participant
    Helpful?
    Up
    0
    ::

    Hey, I am currently stuck in Part 3. I recreated the code 1:1, but as soon as I want to attack with the mouse button in Unity, it plays the attack animation twice.

    #11926
    Terence
    Keymaster
    Helpful?
    Up
    0
    ::

    Hi Samuel,

    Have a look at the frames for the attack animation on the Animation window. Look at whether it is correct.

    Alternatively, the error might be in the Animator itself. Put the Animator window somewhere on a different place from your Game window, and play the game. Look at how the Animator states are transitioning to each other when you attack. This should give you some insight as to where the issue might be.

    #11927
    Samuel Morgan
    Participant
    Helpful?
    Up
    0
    ::

    The animation is set correctly. When I’m in the game and start an attack, the attack animation is played twice in a row in the animator before it switches back to the idle animation

    My guess would be that there is something wrong with the Time.deltaTime command.`
    Is there a way to write the script without the time.deltatime function?

    My second problem is the recoil.

    On the Enemy, the recoil works perfectly, but the player receives 0 recoil.

    I just can’t find the error.

    void Attack()
        {
            timeSinceAttck += Time.DeltaTime;
            if(attack && timeSinceAttck >= timeBetweenAttack)
            {
                
                timeSinceAttck = 0;
                anim.SetTrigger("Attacking");
                
    
                if (yAxis == 0 || yAxis < 0 && Grounded())
                {
                    Hit(SideAttackTransform, SideAttackArea, ref pState.recoilingX, recoilXSpeed);              
                   Instantiate(slashEffect, SideAttackTransform);
                }
                else if (yAxis > 0)
                {
                    Hit(UpAttackTransform, UpAttackArea, ref pState.recoilingY, recoilYSpeed);
                    SlashEffectAtAngle(slashEffect, 80, UpAttackTransform);
                }
                else if (yAxis < 0 && !Grounded())
                {
                    Hit(DownAttackTransform, DownAttackArea, ref pState.recoilingY, recoilYSpeed);
                    SlashEffectAtAngle(slashEffect, -90, DownAttackTransform);
                }
            }
    
        }
        void Hit(Transform _attackTransform, Vector2 _attackArea, ref bool _recoilDir, float _recoilStrength)
        {
            Collider2D[] objectsToHit = Physics2D.OverlapBoxAll(_attackTransform.position, _attackArea, 0, attackableLayer);
    
            if (objectsToHit.Length > 0)
            {
                _recoilDir = true;
            }
            for (int i = 0; i < objectsToHit.Length; i++)
            {
                if (objectsToHit[i].GetComponent<Enemy>() != null)
                {
                    objectsToHit[i].GetComponent<Enemy>().EnemyHit(damage, (transform.position - objectsToHit[i].transform.position).normalized, _recoilStrength);
                }
            }
        }
    
        void SlashEffectAtAngle(GameObject _slashEffect, int _effectAngle, Transform _attackTransform)
    {
        _slashEffect = Instantiate(_slashEffect, _attackTransform);
        _slashEffect.transform.eulerAngles = new Vector3(0, 0, _effectAngle);
            _slashEffect.transform.localScale = new Vector2(transform.localScale.x, transform.localScale.y);
    }
    
        public void Recoil()
        {
            if (pState.recoilingX)
            {
                if (pState.lookingRight)
                {
                    rb.velocity = new Vector2(-recoilXSpeed, 0);
                }
                else
                {
                    rb.velocity = new Vector2(recoilXSpeed, 0);
                }
            }
    
            if (pState.recoilingY)
            {
                rb.gravityScale = 0;
                if (yAxis < 0)
                {
                    
                    rb.velocity = new Vector2(rb.velocity.x, recoilYSpeed);
                }
                else
                {
                    
                    rb.velocity = new Vector2(rb.velocity.x, -recoilYSpeed);
                }
                airJumpCounter = 0;
            }
            else
            {
                rb.gravityScale = gravity;
            }
    
            //stop recoil
            if (pState.recoilingX && stepsXRecoiled < recoilXSteps)
            {
                stepsXRecoiled++;
            }
            else
            {
                StopRecoilX();
            }
            if (pState.recoilingY && stepsYRecoiled < recoilYSteps)
            {
                stepsYRecoiled++;
            }
            else
            {
                StopRecoilY();
            }
    
            if (Grounded())
            {
                StopRecoilY();
            }
    
        }
          
        public void StopRecoilX()
        {
            stepsXRecoiled = 0;
            pState.recoilingX = false;
        }
    
        public void StopRecoilY()
        {
            stepsYRecoiled = 0;
            pState.recoilingY = false;
        }
    #11928
    Terence
    Keymaster
    Helpful?
    Up
    0
    ::

    For the transition from Attack to Idle, try setting the Exit Time back to 1. It’s likely that it is a value more than 1.

    For the recoil on the player character not working, try going into Debug Mode on the Inspector and select your player. The Debug Mode will expose all private variables. Look at the recoilingX and recoilingY properties (I assume they are responsible for player recoil. Pardon me, I’m not the series creator). Do they activate for a single frame when you hit an enemy? If they do, that means that they are being unset immediately after the recoil is activated, which means that StopRecoilX() and StopRecoilY() are likely being called prematurely in Update().

    Hope this helps you zoom in on the issue!

Viewing 4 posts - 1 through 4 (of 4 total)
  • You must be logged in to reply to this topic.

Go to Login Page →


Advertisement below: