-1
\$\begingroup\$

i use this code , but when the health is below to 0 and destroy the gameobject , unity show the error "MissingReferenceException: The object of type 'CapsuleCollider' has been destroyed but you are still trying to access it."

void OnTriggerEnter(Collider other)
    {
        if (canAttack && other.CompareTag("Player"))
        {
            canAttack = false;
            if(other != null)
            {
                StartCoroutine(AttackPlayer(other));
            }
        }
    }
    IEnumerator AttackPlayer(Collider playerCollider)
    {
        while (true)
        {
            playerCollider.GetComponent<Player>().TakeDamage(damageAmount);
            yield return new WaitForSeconds(0.1f);
        }
    }

and i alreally check the colider is null before.

here is the player script

public void TakeDamage(float damage)
    {
        Health -= damage;
        if (Health < 0)
        {
            Die();
        }
    }

    private void Die()
    {
        Destroy(gameObject);
    }

i try to check is null still no work, no debug log

IEnumerator AttackPlayer(Collider playerCollider)
    {
        
        while (true)
        {
            if (playerCollider.gameObject == null)
            {
                Debug.Log("111");
                yield break; 
            }
            playerCollider.GetComponent<Player>().TakeDamage(damageAmount);
                yield return new WaitForSeconds(AttackSpeed);
        }
    }
```
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

If the player has been destroyed (eg. by taking lethal damage), then every component attached to the player will be treated as null, including the player collider.

Once the collider is being treated as null, trying to use the dot operator to access anything about the collider will throw an exception. That includes:

  • playerCollider.GetComponent<Player>() - if playerCollider is null, then this is null.GetComponent, and null does not have a getComponent method --> exception!

  • playerCollider.gameObject == null - if playerCollider is null, then this is null.gameObject, and null does not have a gameObject member --> exception!

So if you think something could have been destroyed, don't use the dot operator! Check it for null first!

A better version of this code would look like this:

void OnTriggerEnter(Collider other)
{
    // You know players have the Player component, so check for that, not a tag.
    if (canAttack && other.TryGetComponent(out Player player))
    {
        canAttack = false;
        // Now we can pass the player component itself to the attack function.
        StartCoroutine(AttackPlayer(player));
    }
}

IEnumerator AttackPlayer(Player player)
{
    // If the player is killed, STOP LOOPING.
    while (player != null)
    {
        // No more GetComponent() search in the middle of the loop.
        player.TakeDamage(damageAmount);

        // You could construct the wait once and cache it.
        yield return new WaitForSeconds(0.1f);
    }

    // My target is dead, I can try to attack a different target now.
    canAttack = true;
}
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .