Forum begins after the advertisement:


[Part 3] Enemy cant take damage

Home Forums Video Game Tutorial Series Creating a Metroidvania in Unity [Part 3] Enemy cant take damage

Viewing 2 posts - 1 through 2 (of 2 total)
  • Author
    Posts
  • #18859
    Danya 16
    Level 1
    Participant
    Helpful?
    Up
    0
    ::

    The enemy cannot take damage. In the third part of the Metroid game, I copied the author’s code, and the console displayed the text “Null Reference Exception.” The enemy’s health is not being depleted

    PlayerMovement Code:

    using System.Collections;
    using System.Runtime.CompilerServices;
    using UnityEngine;
    
    public class PlayerMovement : MonoBehaviour
    {
    
        [Header("Horizontal Input Settings:")]
        [SerializeField] private float walkSpeed = 1;
    
        [Header("Vertical Movment Settings:")]
        [SerializeField] private float jumpForce = 45f;
        private float jumpBufferCounter;
        [SerializeField] private float jumpBufferFrames;
        private float coyotTimeCounter = 0;
        [SerializeField] private float coyotTime;
        private int airJumpCounter = 0;
        [SerializeField] private int maxAirJumps;
    
        [Header("Grounde Check Settings:")]
        [SerializeField] private Transform groundCheckPoint;
        [SerializeField] private float groundCheckY = 0.2f;
        [SerializeField] private float groundCheckX = 0.5f;
        [SerializeField] private LayerMask whatIsGround;
    
        [Header("Dash Settings:")]
        [SerializeField] private float dashSpeed;
        [SerializeField] private float dashTime;
        [SerializeField] private float dashCooldown;
    
        [Header("Attack Settings:")]
        private bool attack = false;
        float timeBetweenAttack, timeSinceAttack;
        [SerializeField] Transform SideAttackTransform, UpAttackTransform, DownAttackTransform;
        [SerializeField] Vector2 SideAttackArea, UpAttackArea, DownAttackArea;
        [SerializeField] LayerMask attackableLayer;
        [SerializeField] float damage;
        [SerializeField] GameObject slashEffect;
    
        PlayerStateList pState;
        private Rigidbody2D rb;
        private float xAxis, yAxis;
        private float gravity;
        Animator anim;
        private bool canDash = true;
        private bool dashed;
    
    
        public static PlayerMovement Instance;
    
        private void Start()
        {
            rb = GetComponent<Rigidbody2D>();
            anim = GetComponent<Animator>();
            pState = GetComponent<PlayerStateList>();
            gravity = rb.gravityScale;
    
            if (Instance != null && Instance != this)
            {
                Destroy(gameObject);
            }
            else
            {
                Instance = this;
            }
        }
        private void Awake()
        {
        }
    
        private void OnDrawGizmos()
        {
            Gizmos.color = Color.red;
            Gizmos.DrawWireCube(SideAttackTransform.position, SideAttackArea);
            Gizmos.DrawWireCube(UpAttackTransform.position, UpAttackArea);
            Gizmos.DrawWireCube(DownAttackTransform.position, DownAttackArea);
        }
    
        private void Update()
        {
            GetInputs();
            UpdateJumpVariables();
    
            if (pState.dashing) return;
            Flip();
            Move();
            Jump();
            StartDash();
            Attack();
        }
    
        private void GetInputs()
        {
            xAxis = Input.GetAxisRaw("Horizontal");
            yAxis = Input.GetAxisRaw("Vertical");
            attack = Input.GetMouseButtonDown(0);
        }
    
        private void Flip()
        {
            if (xAxis > 0)
            {
                transform.localScale = new Vector3(1, 1, 1);
            }
    
            if (xAxis < 0)
            {
                transform.localScale = new Vector3(-1, 1, 1);
            }
        }
    
        void StartDash()
        {
            if (Input.GetButtonDown("Dash") && canDash && !dashed)
            {
                StartCoroutine(Dash());
                dashed = true;
            }
    
            if (Grounded())
            {
                dashed = false;
            }
        }
    
        IEnumerator Dash()
        {
            canDash = false;
            pState.dashing = true;
            anim.SetTrigger("Dashing");
            rb.gravityScale = 0;
            rb.linearVelocity = new Vector2(transform.localScale.x * dashSpeed, 0);
            yield return new WaitForSeconds(dashTime);
            rb.gravityScale = gravity;
            pState.dashing = false;
            yield return new WaitForSeconds(dashCooldown);
            canDash = true;
        }
    
        void Attack()
        {
            timeSinceAttack += Time.time;
            if (attack && timeSinceAttack >= timeBetweenAttack)
            {
                timeSinceAttack = 0;
                anim.SetTrigger("Attacking");
    
                if (yAxis == 0 && yAxis < 0 && Grounded())
                {
                    Hit(SideAttackTransform, SideAttackArea);
                    Instantiate(slashEffect, SideAttackTransform);
                }
                else if (yAxis > 0)
                {
                    Hit(UpAttackTransform, UpAttackArea);
                    SlashEffectAtAngle(slashEffect, 90, UpAttackTransform);
                }
                else if (yAxis < 0 && !Grounded())
                {
                    Hit(DownAttackTransform, DownAttackArea);
                    SlashEffectAtAngle(slashEffect, -90, DownAttackTransform);
                }
            }
        }
    
        private void Hit(Transform _attackTransform, Vector2 _attackArea)
        {
            Collider2D[] objectsToHit = Physics2D.OverlapBoxAll(_attackTransform.position, _attackArea, 0, attackableLayer);
    
            if(objectsToHit.Length > 0)
            {
                Debug.Log("Hit");
            }
    
            for (int i = 0; i < objectsToHit.Length; i++)
            {
                print("Found " + objectsToHit[i].name);
                if (objectsToHit[i].GetComponent<Enemy>() != null)
                {
                    print("Hitting " + objectsToHit[i].name);
                    objectsToHit[i].GetComponent<Enemy>().EnemyHit(damage);
                }
            }
        }
    
        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);
        }
    
        private void Move()
        {
            rb.linearVelocity = new Vector2(xAxis * walkSpeed, rb.linearVelocity.y);
            anim.SetBool("Walking", rb.linearVelocity.x != 0 && Grounded());
        }
    
        public bool Grounded()
        {
            if(Physics2D.Raycast(groundCheckPoint.position, Vector2.down, groundCheckY, whatIsGround) 
                || Physics2D.Raycast(groundCheckPoint.position + new Vector3(groundCheckX, 0, 0), Vector2.down, groundCheckY, whatIsGround) 
                || Physics2D.Raycast(groundCheckPoint.position + new Vector3(-groundCheckX, 0, 0), Vector2.down, groundCheckY, whatIsGround))
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    
        private void Jump()
        {
            if (Input.GetButtonUp("Jump"))
            {
                rb.linearVelocity = new Vector2(rb.linearVelocity.x, 0);
                pState.jumping = false;
            }
    
            if (!pState.jumping)
            {
                if (jumpBufferCounter > 0 && coyotTimeCounter > 0)
                {
                    rb.linearVelocity = new Vector2(rb.linearVelocity.x, jumpForce);
                    pState.jumping = true;
                }
                else if (!Grounded() && airJumpCounter < maxAirJumps && Input.GetButtonDown("Jump"))
                {
                    pState.jumping = true;
                    airJumpCounter++;
                    rb.linearVelocity = new Vector2(rb.linearVelocity.x, jumpForce);
                }
            }
    
    
            anim.SetBool("Jumping", !Grounded());
        }
    
        private void UpdateJumpVariables()
        {
            if (Grounded())
            {
                pState.jumping = false;
                coyotTimeCounter = coyotTime;
                airJumpCounter = 0;
            }
            else
            {
                coyotTimeCounter -= Time.deltaTime;
            }
    
            if (Input.GetButtonDown("Jump"))
            {
                jumpBufferCounter = jumpBufferFrames;
            }
            else
            {
                jumpBufferCounter = jumpBufferCounter - Time.deltaTime * 10;
            }
        }
    }

    Enemy Code:

    using UnityEngine;
    
    public class Enemy : MonoBehaviour
    {
        [SerializeField] float health = 10;
    
        private void Update()
        {
            if (health <= 0)
            {
                Destroy(gameObject);
            }
        }
    
        public void EnemyHit(float _damageDone)
        {
            health -= _damageDone;
        }
    }

    Console text:

    NullReferenceException: Object reference not set to an instance of an object UnityEditor.Graphs.Edge.WakeUp () (atf37757a1c985477b9f83ca7c1f4fb00c>:0)
    #18862
    Ser Apustaja
    Level 6
    AI Assistant
    (BETA)
    Helpful?
    Up
    0
    ::

    It looks like you’re encountering a Null Reference Exception which usually indicates that you’re trying to access a member of an object that hasn’t been initialized (i.e., the object is null). In your case, since you mentioned that the enemy’s health is not being depleted, let’s focus on the Hit method in your PlayerMovement code.

    Here are a few potential issues to check:

    1. Ensure Attackable Layer is Set: Make sure that the enemy GameObject has the correct Layer set, which matches the attackableLayer mask in your PlayerMovement script. If the enemy is on a layer that is not included in attackableLayer, it won’t be detected by the Physics2D.OverlapBoxAll function.

    2. Check Collider Setup: Ensure that the enemy GameObject has a Collider2D component and that the attack transform (like SideAttackTransform, UpAttackTransform, etc.) is positioned correctly to overlap with the enemy’s collider when you attack.

    3. Instantiate Slash Effect: In your Attack method, you’re calling Instantiate(slashEffect, SideAttackTransform). Ensure that slashEffect is assigned in the Inspector, as this could also lead to a NullReferenceException if it’s not set.

    4. Debugging the Hit Method: Add some debug logs to help pinpoint where the problem lies. Modify the Hit method like this:

    private void Hit(Transform _attackTransform, Vector2 _attackArea)
    {
        Collider2D[] objectsToHit = Physics2D.OverlapBoxAll(_attackTransform.position, _attackArea, 0, attackableLayer);
    
        if (objectsToHit.Length > 0)
        {
            Debug.Log("Hit");
            for (int i = 0; i < objectsToHit.Length; i++)
            {
                Debug.Log("Found " + objectsToHit[i].name);
                Enemy enemy = objectsToHit[i].GetComponent();
                if (enemy != null)
                {
                    Debug.Log("Hitting " + objectsToHit[i].name);
                    enemy.EnemyHit(damage);
                }
                else
                {
                    Debug.LogWarning("Found object does not have an Enemy component: " + objectsToHit[i].name);
                }
            }
        }
    }
    1. Check Player State List: Make sure that the PlayerStateList component is correctly attached to the player GameObject. If pState is null, it will cause issues when you check pState.dashing.

    2. Handling the Null Reference Exception: The error message regarding NullReferenceException from UnityEditor.Graphs.Edge.WakeUp seems unrelated to your game logic and might be a part of Unity’s editor scripts or your project setup. If the game runs fine despite this error, it might not be critical. Ensure all your scripts are properly linked and referenced in the Unity Editor.

    After checking these points, try running your game again and see if the enemy’s health starts depleting or if the console gives you more information about the source of the error.

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

Go to Login Page →


Advertisement below: