Полю нигде не присваивается значение, поэтому оно всегда будет иметь значение по умолчанию null

Сижу уже около недели перерыл весь инет. С С# не на ты, поэтому не знаю что делать. В третьей строчке значение в переменную health не присваивается поэтому оно по умолчанию будет null и если оно null, то у персонажа не отнимается здоровье. Если убрать проверку, то Unity пишет (NullReferenceException).

public class CollisionCollider : MonoBehaviour
{
    public int damage;
    [SerializeField] private Animator animator;
    private HealthPoint health;
    private void OnCollisionEnter2D(Collision2D col)
    {
        HealthPoint health = col.gameObject.GetComponent<HealthPoint>();
        if (health != null)
            animator.SetTrigger("CollisionDamage");
    }
    public void SetDamage()
    { 
        if (health != null)
            health.TakeDamage(damage);
    }
}

HealthPoint скрипт откуда берётся метод TakeDamage().

public class HealthPoint : MonoBehaviour
{
    public int health = 100;
    public void TakeDamage(int damage)
    {
        health -= damage;
        if (health <= 0)
        {
            Destroy(gameObject);
        }
    }

Подскажите пожалуйста как решить данную проблему.


Ответы (1 шт):

Автор решения: Алексей Шиманский

Если писать так

HealthPoint health = col.gameObject.GetComponent<HealthPoint>();

то внутри метода объявляется внутренняя переменная health с типом HealthPoint. Она никак не связана с одноимённой переменной, которая объявлена как свойство класса, т.к. слово HealthPoint перед этой переменной говорит нам об объявлении новой переменной. А вот если опустить это слово HealthPoint, то парсер будет понимать, что значит идентификатор уже где-то объявлен и попытается найти где-то ещё, т.е. в свойстве класса.

Поэтому надо быть с этим внимательнее. Может быть бесконечное количество переменных health хоть в каждом из методов. Но если нужно обращаться к свойству класса - то тип перед переменной писать уже не нужно (кроме как в объявлении в самом свойстве класса конечно же).


P.S. Чтобы постоянно не дёргать компоненты, то можно один раз инициализировать его в методе Start и уже потом пользоваться. И проверки на null уже не нужны. Т.е.

public class CollisionCollider : MonoBehaviour {
    public int damage;
    [SerializeField] private Animator animator;
    private HealthPoint health;

    public void Start() {
        health = col.gameObject.GetComponent<HealthPoint>();
    }

    private void OnCollisionEnter2D(Collision2D col) {        
        animator.SetTrigger("CollisionDamage");
    }

    public void SetDamage() { 
        health.TakeDamage(damage);
    }
}
→ Ссылка