Forum begins after the advertisement:


[Part 3 & Part 5] The Slash Animation and A SpellCast / Heal Problem

Home Forums Video Game Tutorial Series Creating a Metroidvania in Unity [Part 3 & Part 5] The Slash Animation and A SpellCast / Heal Problem

Viewing 8 posts - 1 through 8 (of 8 total)
  • Author
    Posts
  • #13919
    Siyuan Chen
    Participant

    Question 1.
    I would like to clarify my question here a bit as I posted it as a comment to episode 3 but it was not clear enough:
    The slash effect we are using is a white slash going clockwise / anticlockwise.
    When the player faces left and attacks, the slash effect goes anticlockwise.
    When the player faces right and attacks, the slash effect goes clockwise.
    However, when the player is attacking upwards or downwards, the slash effect is always clockwise regardless of the player’s facing direction.
    Was I missing something or it needs some extra work?

    See the “Question 1.” video in the following link for slash behavior I am describing:

    View post on imgur.com

    =========================================
    Question 2.
    For the feature “Interpolate” of the enemy:Zombie, the video says it should be set to “Interpolate”. But my zombie loses its recoil after it is set to “Interpolate”. Instead, setting it to “None” works.

    See the “Question 2.” video in the following link for the recoil problem and the parameters of enemy:Zombie:

    View post on imgur.com

    =========================================
    Question 3.
    I went a bit further into the video episode 5 and had a new question. In the first section “Bug Fixes and Improvements”, the spellcast button and heal button are combined as one, and used a button press timer to tell their difference instead.
    But after this process, I always perform spellcast for one time right after I heal (if I have enough mana).
    I have some clues but I am not very sure how to debug it…

    #13922
    Joseph Tang
    Moderator

    Question 1: Slash effect sprite not properly changing directions.

    By right, the normal code should work as the way it works is that for your side attacks, they are calling Instantiate slash effect under the Side Attack Transform game object on the Player. And since they are underneath a child of the player, whenever your player flips, the slash effect should flip too.
    That brings me to my theory of what the issue is:
    I think your side attack is calling SlashEffectAtAngle() instead of Instantiate.
    Check that your code in PlayerController.cs is as follows:

    void Attack()
        {
            timeSinceAttck += Time.deltaTime;
            if(attack && timeSinceAttck >= timeBetweenAttack)
            {
                timeSinceAttck = 0;
                anim.SetTrigger("Attacking");
    
                if (yAxis == 0 || yAxis < 0 && Grounded())
                {
                    int _recoilLeftOrRight = pState.lookingRight ? 1 : -1;
    
                    Hit(SideAttackTransform, SideAttackArea, ref pState.recoilingX, Vector2.right * _recoilLeftOrRight, recoilXSpeed);
                    Instantiate(slashEffect, SideAttackTransform);
                }
                else if (yAxis > 0)
                {
                    Hit(UpAttackTransform, UpAttackArea, ref pState.recoilingY, Vector2.up, recoilYSpeed);
                    SlashEffectAtAngle(slashEffect, 80, UpAttackTransform);
                }
                else if (yAxis < 0 && !Grounded())
                {
                    Hit(DownAttackTransform, DownAttackArea, ref pState.recoilingY, Vector2.down, recoilYSpeed);
                    SlashEffectAtAngle(slashEffect, -90, DownAttackTransform);
                }
            }
        }

    If this doesn't work, I'll need some screenshots or a video of the inspector of both PlayerController.cs in the scene, or the attack transforms + Slash Effect clones while attacking.

    Question 2: Zombie not recoiling.

    This was an issue that occurred to me as well. After testing now. I can tell you that the recoil should be working. If you crank the enemy speed down to 1 or 0, you can see that they are still being recoiled, just to a lesser extent than they had been before setting interpolate. While this is an additional issue due to interpolate, I'd say we can fix that by changing the code.

    public virtual void EnemyHit(float _damageDone, Vector2 _hitDirection, float _hitForce)
        {
            health -= _damageDone;
            if (!isRecoiling)
            {
                rb.velocity = _hitForce * recoilFactor * _hitDirection;
                isRecoiling = true;
            }
        }

    The isRecoiling bool was never set to true in our code, thus making RecoilLength a useless variable, but doing this will prevent your enemy from moving while being recoiled, which should cancel out the interpolate issue in general.

    Question 3: Spellcast after heal

    This is a common issue that others have experienced and in our bugfixes in Part 6. Check this to see if it helps (Second last comment):

    [Part 5] My SceneFader cannot function

    #13945
    Siyuan Chen
    Participant

    reply check

    #13946
    Siyuan Chen
    Participant

    Hi Joseph! Thank you for answering my questions!

    With your help, I have fixed the problems in Question 2 and Question 3. To be mentioned, in Question 2, after add the “isRecoiling = true” statement, the recoil becomes normal and prevents enemy from moving in its duration. My current solution to that is to adjust the “recoilLength” variable (the time length of enemy recoiling) in enemy class. By shortening the time length of enemy recoiling, enemy now switches between recoiling and moving smoothly.

    In Question 1, I think I was not clear describing the question enough.
    Using the code given, my side attacks animations are working well: flipping according to player’s facing direction.
    But my up/down attacks animations are not flipping when the player’s facing direction changes.

    This is my attack method, instantiate for side attacks and slashEffectAngle for up/down attacks:

    void Attack()
    {
        timeSinceAttack += Time.deltaTime;
        if (attacking && timeSinceAttack >= timeBetweenAttack) // if calling attack & time since last attack is larger than attack cd, we can attack again
        {
            timeSinceAttack = 0; // reset the attack cooldown
            anim.SetTrigger("attacking");
    
            // HERE I GIVE A DIVERSION WITH THE TUTORIAL TO MAKE IT MORE HOLLOW KNIGHT -- YOU CAN ATTACK DOWNWARDS WHILE GROUNDED
            // if player not pressing W or S, the player attacks sidely
            
            if (yAxis == 0)
            {
                // ref variable can affect the variable itself even if it is in another method / script
                Hit(sideAttackTransform, sideAttackArea, ref pState.recoilingX, recoilXSpeed);
                Instantiate(slashEffect, sideAttackTransform);
                //SlashEffectAngle(slashEffect, 0, sideAttackTransform);
            }
            else if (yAxis > 0)
            {
                Hit(upAttackTransform, upAttackArea, ref pState.recoilingY, recoilYSpeed);
                SlashEffectAngle(slashEffect, 90, upAttackTransform);
            } 
            else if (yAxis < 0)
            {
                Hit(downAttackTransform, downAttackArea, ref pState.recoilingY, recoilYSpeed);
                SlashEffectAngle(slashEffect, -90, downAttackTransform);
            }
        }
    }

    It looks identical to your code.
    I have rechecked the video episode for attacking and found the video does not have a flipping up/down attack animation, so I guess this function is not included in the tutorial.

    I come to adjust with the “slashEffectAngle” method and finally have some clues:

    void SlashEffectAngle(GameObject _slashEffect, int _effectAngle, Transform _attackTransform)
    {
        // create a body
        _slashEffect = Instantiate(_slashEffect, _attackTransform);
    
        // fit the effect into the hitbox we designed
        //_slashEffect.transform.localScale = new Vector2(transform.localScale.x, transform.localScale.y);
        
        // deside attacking on which direction(side, up, down)
        if (pState.lookingRight)
        {
            _slashEffect.transform.eulerAngles = new Vector3(0, 0, _effectAngle);
        }
        else
        {
            _slashEffect.transform.eulerAngles = new Vector3(0, 0, -_effectAngle);
        }
    
        // fit the effect into the hitbox we designed
        // _slashEffect.transform.localScale = new Vector2(transform.localScale.x, transform.localScale.y);
    }

    I am adding a if statement to check which direction the player is facing, and decide its up/down attacking animation direction. And I cite out the localScale statement in the very last part.
    Using this adjusted code, I achieved the flipping up/down attacking animation. It looks good but I am worrying about citing out the localScale statement would backstab me somewhere.

    If I add the localScale statement, everything goes back. So I am kind of sure it is the localScale statement that fixed the animation in a certain way. I am currently stucking at this point.

    Sorry! My logic might be in a mess. Thank you for your patience reading this. If you need more information (screenshot, more code etc.), I will upload them.

    P.S. How do you create the green highlight? T_T

    #13948
    Joseph Tang
    Moderator

    Great to hear that 2 & 3 are solved.
    If you want to flip the up and down attacks according to your player’s direction, i recommend changing the localscale code rather than the eulerangles.

    I haven’t tried the code you made but this method should work:

    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);
            if (pState.lookingRight)
            {
                _slashEffect.transform.localScale = new Vector2(transform.localScale.x, transform.localScale.y);
            }
            else
            {
                _slashEffect.transform.localScale = new Vector2(transform.localScale.x, -transform.localScale.y);
            }
        }

    Again, since the localScale used is not the Player, but the Parent of the Instantiated slash effect clones [Side/Up/Down Attack Transform game object], the child object’s scale values aren’t swapping between [1] and [-1] like the Player does when flipping. Thus, the localScale of a slash effect will always remain the same as their non-player parent object [1].
    So if we make it such that the localScale value can become [-1], it should work.

    #13950
    Siyuan Chen
    Participant

    I tried your adjusted code. It works!
    It is this step that creates a clone, am I correct?

    _slashEffect = Instantiate(_slashEffect, _attackTransform);

    #13951
    Joseph Tang
    Moderator

    Yes, whenever you call Instantiate, you can see that whatever your instantiating will appear inside the scene’s hierarchy underneath the parent object, in this case under the Player’s attack objects, with the word “(clone)” next to the name.

    #13952
    Siyuan Chen
    Participant

    Oh! I see the “(clone)”. Thank you so much for helping! I get the mechanics of the code much better than before.

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

Go to Login Page →


Advertisement below: