0

I'm a beginner developper and I just started making my own game but in my advancement I got stuck with the creation of an enemy.

The goal of this script is to move the enemy, catch the player and most of all making damages to the player, but in this case, I cannot make link between my player health and my enemy controller script because of the NullReferenceException error that haunts me. It's the only error I have and I've searched everywhere to fix my error but don't find anything.

This is my EnemyController script which I know is not really optimized but whatever. The real problem is right here at the line 49 in the Update function (if(playerHealth == null){})
All of my scripts are connected, here are all scripts I used for this.

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

public class EnemyContoller : MonoBehaviour
{
    public float lookRadius = 10f;
    public float maxHealth = 100f;
    public float currentHealth;
    Transform target;
    NavMeshAgent agent;
    public HealthBarScript healthBar;
    public Animator anim;
    EnemyAttack attack;
    PlayerHealth playerHealth;

    // Update is called once per frame
    void Start()
    {
        attack = GetComponent<EnemyAttack>();
        anim = GetComponent<Animator>();
        gameObject.layer = 6;
        currentHealth = maxHealth;
        healthBar.SetMaxHealth(maxHealth);
        target = PlayerManager.instance.player.transform;
        agent = GetComponent<NavMeshAgent>();
        playerHealth = GetComponent<PlayerHealth>();
    }
    
    void Update()
    {
        float distance = Vector3.Distance(target.position, transform.position);

        if(distance <= lookRadius)
        {
            anim.speed = agent.speed;
            anim.SetBool("isRunning",true);
            agent.SetDestination(target.position);
        }else{
            anim.speed = 0;
            anim.SetBool("isRunning",false);
        }

        if(distance <= agent.stoppingDistance)
        {
            if(playerHealth != null)
            {
                attack.MakeDamage(attack.damages, playerHealth);
                Debug.Log(playerHealth.currentHealth);
            }
            else if(playerHealth == null)
            {
                Debug.Log("Player Health = null");
            }
            FaceTarget();
        }
    }

    public void TakeDamage(float amount){
        currentHealth -= amount;
        healthBar.SetHealth(currentHealth);
        if(currentHealth <= 0)
        {
            Die();
        }
    }
    void Die()
    {
        Destroy(gameObject);
    }

    void OnDrawGizmosSelected()
    {
        Gizmos.color = Color.red;
        Gizmos.DrawWireSphere(transform.position, lookRadius);
    }

    void FaceTarget()
    {
        Vector3 direction = (target.position - transform.position).normalized;
        Quaternion lookRotation = Quaternion.LookRotation(new Vector3(direction.x, 0, direction.z));
        transform.rotation = Quaternion.Slerp(transform.rotation, lookRotation, Time.deltaTime * 3f);
    }
}

This is my Enemy Attack script

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

public class EnemyAttack : MonoBehaviour
{
    public float damages = 10f;
    public float damageRate = 1f;
    private float damageCooldown = 0f;
    PlayerHealth pH;

    void Update()
    {
        damageCooldown -= Time.deltaTime;
    }
    public void MakeDamage(float amount, PlayerHealth health)
    {
        if(damageCooldown <= 0f)
        {
            pH.TakeDamage(damages);
            Debug.Log(health);
            damageCooldown = 1f / damageRate;
        }
    }
}

This my PlayerHealth script

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

public class PlayerHealth : MonoBehaviour
{
    public float currentHealth;
    public float maxHealth = 50f;
    public HealthBarScript healthBar;
    // Start is called before the first frame update
    void Start()
    {
        currentHealth = maxHealth;
        healthBar.SetMaxHealth(maxHealth);
    }

    public void TakeDamage(float amount)
    {
        currentHealth -= amount;
        healthBar.SetHealth(currentHealth);
        Debug.Log(currentHealth);
        if(currentHealth <= 0)
        {
            Debug.Log("You're Dead.");
            Time.timeScale = 0;
        }
    }
}

If someone could help me that would be great I don't know what to do to fix this bug that lasts for 2 days.

Alokin
  • 1
  • Quick question. is your PlayerHealth script a generic script for any entity in your game to have health? Or is it strictly for the player? I think the issue is you are attempting to get the component on the enemy but it is not on the enemy, it is on the player. This line `playerHealth = GetComponent();` is attempting to get the component PlayerHealth on the Enemy object. I believe you want to use something along the lines of `GameObject.Find("PlayerObjectName").GetComponent();` instead – TEEBQNE Apr 07 '21 at 20:35
  • @derHugo I prefer [this duplicate](https://stackoverflow.com/questions/62413907/in-unity-c-why-am-i-getting-a-nullreferenceexception-and-how-do-i-fix-it) – Ruzihm Apr 07 '21 at 20:44
  • Also, in `MakeDamage` what is meant to be the difference between the parameter `health` and the field `pH`? If `MakeDamage` is meant to be called when the owning enemy damages the player whose health is managed by `health`, why don't you just do `health.TakeDamage(damages);`? You never seem to instantiate `pH` anyway. – Ruzihm Apr 07 '21 at 20:53
  • @user3657449 the PlayerHealth script is striclty for the player. I just tried this method and it didn't change the result I still have the same error :/ – Alokin Apr 07 '21 at 21:04
  • @Ruzihm I just changed that but the result is the same, I guess that my biggest mistake is that I made my code confusing for me and for everyone. – Alokin Apr 07 '21 at 21:05
  • @Alokin Just to confirm, you need to swap the string "PlayerObjectName" with the object that has the script PlayerHealth on it. If the object's name is `Player`, then the line is `GameObject.Find("Player").GetComponent();`. Also, is your player object enabled when the Enemies Start() is called? – TEEBQNE Apr 07 '21 at 21:11
  • @TEEBQNE I think I got ```GameObject.Find("Player").GetComponent();``` right x) Although I didn't understand your question ^^' – Alokin Apr 07 '21 at 21:18
  • If your player object is not enabled in the hierarchy, meaning it is turned on, then the GameObject.Find will not work. It only works on objects that are enabled. If your enemies are created and turned on before your player, they will be unable to find your player object, meaning they can't find the component on the player. – TEEBQNE Apr 07 '21 at 21:27
  • @Ruzihm yeah I know that one .. and that it is Unity specific and gives some examples where this might (or not) come from .. but NullRef is NullRef .. the generic duplicate explicitly says the solution is: **Debug your code** .. that's why I prefer that one ;) – derHugo Apr 08 '21 at 06:03

0 Answers0