Home > Software design >  Unity2D Melee Combat
Unity2D Melee Combat

Time:07-27

I'm new to programming and C#. I'm trying to build a melee system for my platform game following tutorials on yt.

This is my PlayerAttack script:

using System.Collections; using System.Collections.Generic; using UnityEngine;

public class PlayerAttack : MonoBehaviour {
    //[SerializeField] private float attackCooldown;
    [SerializeField] private float range;
    [SerializeField] private int damage;

    [SerializeField] private LayerMask enemyLayer;


    public Transform AttackPoint;

    //private float cooldownTimer = Mathf.Infinity;

    private Animator anim;
    private Enemy enemyHealth;




    private void Awake()
    {
        anim = GetComponent<Animator>();
        enemyHealth = GetComponent<Enemy>();
    }

    private void Update()
    {
        if (Input.GetButtonDown("Fire1"))
        {
            anim.SetTrigger("Attack");
            Attack();
            Debug.Log("attacking");
        }
    }

    private void OnDrawGizmos()
    {
        if (AttackPoint == null)
            return;

        Gizmos.color = Color.red;
        Gizmos.DrawWireSphere(AttackPoint.position, range);

    }



    void Attack()
    {


        Collider2D[] hitEnemies = Physics2D.OverlapCircleAll(AttackPoint.position, range, enemyLayer);

        foreach (Collider2D Enemy in hitEnemies)
        {

            Enemy.transform.GetComponent<Enemy>().TakeDamage(damage);   

        }



    }

}

and this one is the EnemyHealth script

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Enemy : MonoBehaviour
{
    [SerializeField] private int startingHealth;

    public int currentHealth;
    public Animator anim;

    void Start()
    {
        currentHealth = startingHealth;
    }

    public void TakeDamage(int _damage)
    {
        currentHealth = Mathf.Clamp(currentHealth - _damage, 0, startingHealth);

        if (currentHealth > 0)
        {
            //hurt animation
            //invulnerability
        }

        else
        {
            //die animation
            GetComponentInParent<EnemyPatrol>().enabled = false;
            GetComponent<EnemyMelee>().enabled = false;
        }


    }

    void Die()
    {
        if (currentHealth <= 0)
        {

            Debug.Log("Enemy Dead!");
            Destroy(gameObject);
            //die animation
        }


    }
}

I'm getting an error from the Unity editor "object reference not set to an instance of an object" on line 61 of the PlayerAttack: enter code here

Enemy.transform.GetComponent().TakeDamage(damage);

I checked the scripts names and they are fine, and I checked also if I missed something in the editor , I don't know what's wrong.

When I hit the enemy the game crashes and i get this error. Thanks

CodePudding user response:

You are trying to call Enemy.transform.GetComponent<Enemy>().TakeDamage(damage); on everything that has collider but some of those objects don't have the Enemy component so you can't call TakeDamage on them. That is where the error comes from. To fix it you have to find only the enemy game objects. To do this you can assign tags to your enemy and check the ones with Enemy tag through the script like this:

  foreach (Collider2D Enemy in hitEnemies)
        {
          if (Enemy.tag == "Enemy")
            Enemy.transform.GetComponent<Enemy>().TakeDamage(damage);               
        }

There is another way to do it without tags which I don't recommend:

  foreach (Collider2D Enemy in hitEnemies)
        {
          if (Enemy.transform.GetComponent<Enemy>() != null)
            Enemy.transform.GetComponent<Enemy>().TakeDamage(damage);             
        }

CodePudding user response:

Check if the player has hit the enemy or not:

foreach (Collider2D hitEnemy in hitEnemies) {
    if(hitEnemy.TryGetComponent(out Enemy enemy)) {
        enemy.TakeDamage(damage);
    }
}

Other than the answer:
In your PlayerAttack.cs script, you have a field enemyHealth which you are trying to get a reference to it using enemyHealth = GetComponent<Enemy>(); in your Awake() method. This doesn't get a reference to it because of Enemy.cs and PlayerAttack.cs scripts are attached to different gameobjects.

  • Related