Forum begins after the advertisement:


[Part 6-7] Ledge Check Y vs Recoil issue

Home Forums Video Game Tutorial Series Creating a Metroidvania in Unity [Part 6-7] Ledge Check Y vs Recoil issue

Viewing 7 posts - 1 through 7 (of 7 total)
  • Author
    Posts
  • #13227
    Courtmaster
    Level 21
    Participant
    Helpful?
    Up
    0
    ::

    The enemies which use the flip movement, the Crawler and Charger, have an issue with recoiling properly. When the Ledge Check Y is set high enough for them to move, then they can’t recoil on the X axis. More specifically, in the first scene I load into, they will recoil in about 1 out of 4 hits on them. When I change scenes, these enemies will stop recoiling entirely. If I set the Ledge Check Y so low that they can’t move, then the recoil works perfectly even after changing scenes. I’ve so far tried fine tuning it down to 0.9395 to see if there is some exact point that they can both move and recoil, but nothing so far. It is either one or the other. Regardless of the Ledge Check Y setting, they CAN be recoiled on the Y axis, launching them into the air.

    Enemies that do not need Ledge Check Y for their movement do not have this issue.

    #13230
    Terence
    Level 30
    Keymaster
    Helpful?
    Up
    0
    ::

    Thanks for highlighting this Courtmaster. I haven’t tested this, but off the top of my head, one thing I would try is to make the enemy unable to change states when recoiling:

        protected override void UpdateEnemyStates()
        {
            if (health <= 0)
            {
                Death(0.05f);
            }
    
            if(isRecoiling) return;
    
            Vector3 _ledgeCheckStart = transform.localScale.x > 0 ? new Vector3(ledgeCheckX, 0) : new Vector3(-ledgeCheckX, 0);
            Vector2 _wallCheckDir = transform.localScale.x > 0 ? transform.right : -transform.right;
    
            switch (GetCurrentEnemyState)
            {
                case EnemyStates.Charger_Idle:
                    if (!Physics2D.Raycast(transform.position + _ledgeCheckStart, Vector2.down, ledgeCheckY, whatIsGround)
                        || Physics2D.Raycast(transform.position, _wallCheckDir, ledgeCheckX, whatIsGround)
                        || Physics2D.Raycast(transform.position + _ledgeCheckStart, _wallCheckDir, ledgeCheckX).collider.CompareTag("Enemy"))
                    {
                        ChangeState(EnemyStates.Crawler_Flip);
    
                        transform.localScale = new Vector2(transform.localScale.x * -1, transform.localScale.y);
                    }
    
                    RaycastHit2D _hit = Physics2D.Raycast(transform.position + _ledgeCheckStart, _wallCheckDir, ledgeCheckX * 10);
                    if (_hit.collider != null && _hit.collider.gameObject.CompareTag("Player"))
                    {
                        ChangeState(EnemyStates.Charger_Suprised);
                    }
    
                    if (transform.localScale.x > 0)
                    {
                        rb.velocity = new Vector2(speed, rb.velocity.y);
                    }
                    else
                    {
                        rb.velocity = new Vector2(-speed, rb.velocity.y);
                    }
                    break;
    
                case EnemyStates.Crawler_Flip:
                    timer += Time.deltaTime;
    
                    if(timer > flipWaitTime)
                    {
                        timer = 0;
                        transform.localScale = new Vector2(transform.localScale.x * -1, transform.localScale.y);
                        ChangeState(EnemyStates.Crawler_Idle);
                    }
                    break;
    
                case EnemyStates.Charger_Suprised:
                    rb.velocity = new Vector2(0, jumpForce);
    
                    ChangeState(EnemyStates.Charger_Charge);
                    break;
    
                case EnemyStates.Charger_Charge:
                    timer += Time.deltaTime;
    
                    if(timer < chargeDuration)
                    {
                        if(Physics2D.Raycast(transform.position, Vector2.down, ledgeCheckY, whatIsGround))
                        {
                            if (transform.localScale.x > 0)
                            {
                                rb.velocity = new Vector2(speed * chargeSpeedMultiplier, rb.velocity.y);
                            }
                            else
                            {
                                rb.velocity = new Vector2(-speed * chargeSpeedMultiplier, rb.velocity.y);
                            }
                        }
                        else
                        {
                            rb.velocity = new Vector2(0, rb.velocity.y);
                        }
                    }
                    else
                    {
                        timer = 0;
                        ChangeState(EnemyStates.Charger_Idle);
                    }
                    break;
            }
        }

    There are probably some kinks in the code you’ll have to work out if you decide to try this path though. Keep me posted here and I’ll help you along (if you need any).

    #13231
    Terence
    Level 30
    Keymaster
    Helpful?
    Up
    0
    ::

    P.S. Thanks for highlighting this. I’ve given you a Bug Reporter badge on your profile — a small token of appreciation because I need help with spotting bugs in our series.

    #13234
    Courtmaster
    Level 21
    Participant
    Helpful?
    Up
    0
    ::

    It doesn’t seem to be working. On further inspection, recoiling any enemy doesn’t seem to set the isRecoiling bool to true, no matter what their recoilLength is set to. Looking through the Enemy script, I can’t seem to find any code that would set it to true

    #13245
    Courtmaster
    Level 21
    Participant
    Helpful?
    Up
    0
    ::

    Adding “isRecoiling = true;” within EnemyHit is what ended up working for me.

    public virtual void EnemyHit(float _damageDone, Vector2 _hitDirection, float _hitForce)
    {
        health -= _damageDone;
        if(!isRecoiling)
        {
            <strong>isRecoiling = true;</strong>
            GameObject _monsterBlood = Instantiate(monsterBlood, transform.position, Quaternion.identity);
            Destroy(_monsterBlood, 5.5f);
            rb.velocity = _hitForce * recoilFactor * _hitDirection;
        }
    }
    #13246
    Terence
    Level 30
    Keymaster
    Helpful?
    Up
    0
    ::

    Thanks for sharing your solution Courtmaster.

    #13256
    Courtmaster
    Level 21
    Participant
    Helpful?
    Up
    0
    ::

    NP, thank you for always being so responsive and helpful! You’ve been a real lifesaver for me

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

Go to Login Page →


Advertisement below: