Forum begins after the advertisement:


[Part 3] Bat Not Doing Damage

Home Forums Video Game Tutorial Series Creating a Metroidvania in Unity [Part 3] Bat Not Doing Damage

Viewing 7 posts - 1 through 7 (of 7 total)
  • Author
    Posts
  • #17571
    My
    Level 8
    Bronze Supporter (Patron)
    Helpful?
    Up
    0
    ::

    My crawler is doing damage so I believe my enemy script is fine. Including it regardless though:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class Enemy : MonoBehaviour
    {
        [SerializeField] protected float health;
        [SerializeField] protected float recoilLength;
        [SerializeField] protected float recoilFactor;
        [SerializeField] protected bool isRecoiling = false;
    
        [SerializeField] protected float speed;
    
        [SerializeField] protected float damage;
        [SerializeField] protected GameObject orangeBlood;
    
        protected float recoilTimer;
        protected Rigidbody2D rb;
        protected SpriteRenderer sr;
        protected Animator anim;
    
        protected enum EnemyStates
        {
            Crawler_Idle,
            Crawler_Flip,
    
            Bat_Idle,
            Bat_Chase,
            Bat_Stunned,
            Bat_Death,
        }
    
        protected EnemyStates currentEnemyState;
    
        protected virtual EnemyStates GetCurrentEnemyState
        {
            get { return currentEnemyState; }
            set
            {
                if(currentEnemyState != value)
                {
                    currentEnemyState = value;
                    ChangeCurrentAnimation();
                }
            }
        }
    
        // Start is called before the first frame update
        protected virtual void Start()
        {
            rb = GetComponent<Rigidbody2D>();
            sr = GetComponent<SpriteRenderer>();
            anim = GetComponent<Animator>();
        }
        // Update is called once per frame
        protected virtual void Update()
        {
            if(isRecoiling)
            {
                if(recoilTimer < recoilLength)
                {
                    recoilTimer += Time.deltaTime;
                }
                else
                {
                    isRecoiling = false;
                    recoilTimer = 0;
                }
            }
            else
            {
                UpdateEnemyStates();
            }
        }
    
        public virtual void EnemyGetsHit(float _damageDone, Vector2 _hitDirection, float _hitForce)
        {
            health -= _damageDone;
            if(!isRecoiling)
            {
                GameObject _orangeBlood = Instantiate(orangeBlood, transform.position, Quaternion.identity);
                Destroy(_orangeBlood, 5.5f);
                rb.linearVelocity = -_hitForce * recoilFactor * _hitDirection;
            }
        }
        protected void OnTriggerStay2D(Collider2D _other)
        {
            if(_other.gameObject.CompareTag("Player") && !PlayerController.Instance.pState.invincible && health > 0)
            {
                Attack();
                PlayerController.Instance.HitStopTime(0, 5, 0.5f);
            }
        }
    
        protected virtual void Death(float _destroyTime)
        {
            Destroy(gameObject, _destroyTime);
        }
    
        protected virtual void UpdateEnemyStates()
        {
    
        }
    
        protected virtual void ChangeCurrentAnimation()
        {
    
        }
    
        protected void ChangeState(EnemyStates _newState)
        {
            GetCurrentEnemyState = _newState;
        }
    
        protected virtual void Attack()
        {
            PlayerController.Instance.TakeDamage(damage);
        }
    
    }
    
    
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class Bat : Enemy
    {
    
        [SerializeField] private float chaseDistance;
        [SerializeField] private float stunDuration;
    
        float timer;
        // Start is called once before the first execution of Update after the MonoBehaviour is created
        protected override void Start()
        {
            base.Start();
            ChangeState(EnemyStates.Bat_Idle);
        }
    
        protected override void UpdateEnemyStates()
        {
            float _dist = Vector2.Distance(transform.position, PlayerController.Instance.transform.position);
    
            switch (GetCurrentEnemyState)
            {
                case EnemyStates.Bat_Idle:
                    if (_dist < chaseDistance)
                    {
                        ChangeState(EnemyStates.Bat_Chase);
                    }
                    break;
    
                case EnemyStates.Bat_Chase:
                    rb.MovePosition(Vector2.MoveTowards(transform.position, PlayerController.Instance.transform.position, Time.deltaTime * speed));
                    FlipBat();
                    break;
    
                case EnemyStates.Bat_Stunned:
                    timer += Time.deltaTime;
    
                    if (timer > stunDuration)
                    {
                        ChangeState(EnemyStates.Bat_Idle);
                        timer = 0;
                    }
                    break;
    
                case EnemyStates.Bat_Death:
                    Death(Random.Range(5, 10));
                    break;
            }
        }
    
        public override void EnemyGetsHit(float _damageDone, Vector2 _hitDirection, float _hitForce)
        {
            base.EnemyGetsHit(_damageDone, _hitDirection, _hitForce);
    
            if (health > 0)
            {
                ChangeState(EnemyStates.Bat_Stunned);
            }
            else
            {
                ChangeState(EnemyStates.Bat_Death);
            }
        }
    
        protected override void Death(float _destroyTime)
        {
            rb.gravityScale = 12;
            base.Death(_destroyTime);
        }
    
        protected override void ChangeCurrentAnimation()
        {
            anim.SetBool("Idle", GetCurrentEnemyState == EnemyStates.Bat_Idle);
            anim.SetBool("Chase", GetCurrentEnemyState == EnemyStates.Bat_Chase);
            anim.SetBool("Stunned", GetCurrentEnemyState == EnemyStates.Bat_Stunned);
    
            if (GetCurrentEnemyState == EnemyStates.Bat_Death)
            {
                anim.SetTrigger("Death");
            }
        }
    
        void FlipBat()
        {
            if (PlayerController.Instance.transform.position.x < transform.position.x)
            {
                sr.flipX = true;
            }
            else
            {
                sr.flipX = false;
            }
        }
    }
    View post on imgur.com
    #17573
    Ser Apustaja
    Level 5
    AI Assistant
    (BETA)
    Helpful?
    Up
    0
    ::

    It looks like you’re working on a Unity project involving enemies, specifically a Bat enemy that inherits from a base Enemy class. However, you mentioned that your “crawler is doing damage,” which suggests there might be an issue with how damage and states are handled for your enemies.

    Here are some suggestions to troubleshoot your code:

    1. Check Damage Application: Ensure that the damage is being calculated and applied correctly. In your EnemyGetsHit method, you’re reducing the health, but make sure that the _damageDone value is correct and greater than zero when the enemy gets hit.

    2. Recoil Logic: Your recoil logic seems to be functioning, but make sure that the _hitDirection and _hitForce are being passed correctly when calling EnemyGetsHit(). If the enemy isn’t recoiling as expected, verify the values used during the call.

    3. State Transitions: Check if the state transitions are occurring as intended. For example, make sure that the enemy transitions to Bat_Stunned after taking damage. You can add debug logs to see if the correct states are being hit:

      Debug.Log($"Enemy State: {GetCurrentEnemyState}");
    4. Animation Handling: Ensure your animations are set up correctly in the Animator. The parameters being set (Idle, Chase, Stunned, etc.) should match the conditions in your ChangeCurrentAnimation() function.

    5. Collision Detection: In the OnTriggerStay2D function, ensure that the collision detection with the player is working properly. If the player’s invincible state is never false, the enemy won’t attack. You might want to log when the enemy is trying to attack.

    6. Adjusting Rigidbody Settings: Make sure that the Rigidbody2D settings for your enemy (like gravity scale, friction, etc.) are set correctly. If the enemy is behaving unexpectedly, it might be due to physics settings.

    7. Debugging: Use Unity’s Debugging tools to step through the code while it’s running. Set breakpoints in your methods to inspect values when the enemy takes damage or changes states.

    Here’s a small snippet to add debugging:

    public override void EnemyGetsHit(float _damageDone, Vector2 _hitDirection, float _hitForce)
    {
        Debug.Log($"Enemy hit: Damage: {_damageDone}, Health before hit: {health}");
        base.EnemyGetsHit(_damageDone, _hitDirection, _hitForce);
        Debug.Log($"Health after hit: {health}");
    
        if (health > 0)
        {
            ChangeState(EnemyStates.Bat_Stunned);
        }
        else
        {
            ChangeState(EnemyStates.Bat_Death);
        }
    }
    1. Review Serialization: Ensure that your serialized fields are set correctly in the Unity editor. Sometimes, values could be zero or not as expected, leading to unintended behavior.

    If you provide more context on what specifically isn’t working or what kind of damage is happening, I can offer more targeted advice!

    #17574
    My
    Level 8
    Bronze Supporter (Patron)
    Helpful?
    Up
    1
    ::

    So the crawler and bat both should do damage on connection with the player, I have even added a new enemy class in the former of a charger. The crawler and charger do damage when touching the player, the bat still does not. Each enemy will receive damage when hit by the player, all animations work, but the bat, even after changing damage numbers and looking through the code, still won’t do damage to the player.

    has upvoted this post.
    #17575
    Ser Apustaja
    Level 5
    AI Assistant
    (BETA)
    Helpful?
    Up
    0
    ::

    It sounds like you’re working on a game where different enemy types interact with the player in specific ways. Since the bat is not dealing damage as expected, there are a few areas you can check in your code:

    1. Collision Detection: Ensure that the bat’s collision detection with the player is implemented correctly. Check if the bat’s hitbox is properly defined and that the collision detection logic is working as intended.

      if bat.rect.colliderect(player.rect):
          player.take_damage(bat.damage)
    2. Damage Handling: Verify that the bat’s damage is being applied correctly. Make sure that the method responsible for dealing damage (e.g., player.take_damage()) is being called when a collision occurs.

    3. Enemy State: Check if the bat is in the correct state when it comes into contact with the player. If the bat is in a state where it shouldn’t deal damage (like being stunned or inactive), it won’t hurt the player.

    4. Animation Events: If your bat has animations, ensure that damage is not tied to a specific animation state that’s not being triggered. You might want to check if the animation is playing correctly when the bat collides with the player.

    5. Debugging: Add some debugging statements to track when the collision happens and whether the damage is being applied. For example:

      if bat.rect.colliderect(player.rect):
          print("Bat collided with player!")
          player.take_damage(bat.damage)
    6. Compare with Other Enemies: Since you mentioned that the crawler and charger do deal damage, compare the implementation of the bat with those enemies. Look for any differences in how damage is calculated or how collisions are managed.

    7. Game Loop Logic: Review the game loop to ensure that the bat’s updates and collision checks are being called regularly, similar to the other enemies.

    If you can share specific snippets of your code related to the bat’s collision detection and damage application, I can provide more targeted help.

    #17576
    My
    Level 8
    Bronze Supporter (Patron)
    Helpful?
    Up
    1
    ::

    I apologize, moments after I sent the last post I was able to get it to work. Not sure how but all of my current enemies do damage to the player. Thank you!

    has upvoted this post.
    #17577
    Ser Apustaja
    Level 5
    AI Assistant
    (BETA)
    Helpful?
    Up
    0
    ::

    It sounds like you managed to resolve the issue with your game where enemies were dealing damage to the player. That’s great to hear! If you have any further questions or need help with another part of your code or game development, feel free to ask. Happy coding!

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

    Glad you managed to figure it out! And thank you for your support.

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: