-2

So when enemy is spawned i try to init him here enemy.Init(); but had error Object reference not set to an instance of an object. But here Debug.Log(enemy._enemyHealth); i get number of enemy health. How i can Init my enemy from here if enemy has class 'Usual Enemy' and it extends from this class 'Enemy' and i wiil have more enemy child cllases?

I vave class Enemy

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

public abstract class Enemy : MonoBehaviour
{

    private GameObject _player;
    private Animator _animator;
    private Rigidbody _rigidbody;
    private bool _isSpawned;
    private const int _enemySpavnTime = 5;
    [SerializeField] public float _enemyHealth;
    [SerializeField] protected float _rotationSpeed = 10f;
    [SerializeField] protected float _moveSpeed;
    [SerializeField] protected float _damage;
    [SerializeField] protected DamageBox _damageBox;
    [SerializeField] protected TriggerBox _triggerBox;
    private EnemyCondition _enemyCondition = EnemyCondition.Dead;
    
    private enum EnemyCondition 
    {
        Spawn,
        Run,
        Attack,
        Dead
    }


    void Start()
    {
        _rigidbody = GetComponent<Rigidbody>();
        _animator = GetComponent<Animator>();
        _player = GameObject.FindWithTag("Hero");
        _damageBox.HeroHited += enemyAttack;
        _triggerBox.HeroInAttackRange += enemyGetAngry;
        _triggerBox.HeroOutAttackRange += enemyGetChill;
    }

    void Update()
    {   
        if (_player != null) 
        {
            if (_enemyCondition == EnemyCondition.Run)
            {
                EnemyPlayerRotation(_player);

            } else if (_enemyCondition == EnemyCondition.Attack)
            {
                EnemyPlayerRotation(_player);
            }
        }
        
    }

    void FixedUpdate() {
        if (_enemyCondition == EnemyCondition.Run)
        {
            EnemyPlayerFollow();
        }   
    }

    public virtual void Init() {
        enemySpawn();
    }

    protected virtual void EnemyPlayerFollow() {
        Vector3 direction = transform.TransformDirection(new Vector3(0, 0, 1));
        _rigidbody.velocity = direction * _moveSpeed;
    }

    protected virtual void EnemyPlayerRotation(GameObject target) {
        Vector3 direction = (target.transform.position - transform.position).normalized;
        Quaternion lookRotation = Quaternion.LookRotation(new Vector3(direction.x, 0, direction.z));
        transform.rotation = Quaternion.Slerp(transform.rotation, lookRotation, Time.deltaTime * _rotationSpeed);
     }

    public virtual void EnemyDamage(float damage)
    {
        _enemyHealth -= damage;
        if (_enemyHealth <= 0) {
            PoolManager.Instanse.Despawn(gameObject);
        }
    }

    public virtual void enemySpawned() {
        _enemyCondition = EnemyCondition.Run;
        _rigidbody.isKinematic = false;
        _animator.SetTrigger("Run");
        StopCoroutine(SpawnMoveUp());
        Debug.Log("enemySpawned");
    }

    protected virtual void enemyAttack(Hero trigger) 
    {   
        if (_enemyCondition == EnemyCondition.Attack) {
            trigger.HeroDamage(_damage);
        }
    }

    protected virtual void enemyGetAngry() {
        _enemyCondition = EnemyCondition.Attack;
        _animator.SetTrigger("Attack");
    }

    protected virtual void enemyGetChill() {
        _enemyCondition = EnemyCondition.Run;
        _animator.SetTrigger("Run");
    }

    protected virtual void enemySpawn() {
        _animator.SetTrigger("Spawn");
        _animator.speed = 0.0f;
        StartCoroutine(SpawnMoveUp());
    }

    IEnumerator SpawnMoveUp()
    {  
        float spawnStage = 0.0f;
        Vector3 startPoint = transform.position;
        while(spawnStage <= 1.0f) {
            transform.position = Vector3.Slerp(startPoint, new Vector3(transform.position.x, 0, transform.position.z), spawnStage);
            spawnStage += Time.deltaTime/_enemySpavnTime;
            yield return null;
        }
        _animator.speed = 1.0f;
        
    }
    
}

And I have class that spawns enemies

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

public class EnemiesSpawner : MonoBehaviour
{
    [SerializeField] private Levels[] _levelsList;
    private List<GameObject> _enemiesQueue = new List<GameObject>();
    private List<GameObject> _levelEnemiesList = new List<GameObject>();
    private List<int> _levelEnemiesCount = new List<int>();

    private bool _isBossSpawned = false;
    // private int _currentLevel = PlayerPrefs.GetInt("currentLevel") - 1;
    private int _currentLevelNumber = 0;
    private float _reloadPause = 0;
    private int currentEnemiesListPos = 0;
    private int allEnemiesCount = 0;

    private float _reloadTime;
    private float _spawnRadius;
    private float _spawnOfsetRadius = 2f;

    [SerializeField] private GameObject _boss;
    [SerializeField] private GameObject _spawnPoint;

    void Start() {
        Levels currentLevelObj = _levelsList[_currentLevelNumber];
        _levelEnemiesCount.AddRange(currentLevelObj.enemiesCount.ToArray());
        _levelEnemiesList = currentLevelObj.enemiesPrefabs;
        _spawnRadius = currentLevelObj.spawnRadius;
        _reloadTime = currentLevelObj.spawnReload;

        foreach(int num in _levelEnemiesCount) {
            allEnemiesCount += num;
        }

        while(_enemiesQueue.Count < allEnemiesCount){
            int randomIndex = Random.Range(0, _levelEnemiesCount.Count);
            if (_levelEnemiesCount[randomIndex] == 0) {
                continue;
            } else {
                _enemiesQueue.Add(_levelEnemiesList[randomIndex]);
                _levelEnemiesCount[randomIndex] --;
            }
        }
    }

    public void SetPlayerForSpawn (GameObject player) {
        _spawnPoint = player;
    }

    void Update ()
    {           
        if (_spawnPoint != null){
            SpawnEnemies();
        }
        
    }

    public void SpawnEnemies() 
    {
        _reloadPause += Time.deltaTime;
        if (_reloadPause >= _reloadTime && currentEnemiesListPos < allEnemiesCount) {
            GameObject go = PoolManager.Instanse.Spawn(_enemiesQueue[currentEnemiesListPos],new Vector3((Random.value < 0.5f) ? Random.Range(_spawnPoint.transform.position.x + _spawnOfsetRadius, _spawnPoint.transform.position.x + _spawnRadius) : Random.Range(_spawnPoint.transform.position.x - _spawnOfsetRadius, _spawnPoint.transform.position.x - _spawnRadius), -5, (Random.value < 0.5f) ? Random.Range(_spawnPoint.transform.position.z + _spawnOfsetRadius, _spawnPoint.transform.position.z + _spawnRadius) : Random.Range(_spawnPoint.transform.position.z - _spawnOfsetRadius, _spawnPoint.transform.position.z - _spawnRadius)), Quaternion.identity);
            Enemy enemy = go.GetComponent<Enemy>();
            Debug.Log(enemy._enemyHealth);
            enemy.Init();
            _reloadPause = 0;
            currentEnemiesListPos ++;
        } else if (currentEnemiesListPos == allEnemiesCount && _isBossSpawned == true) {
            Instantiate(_boss,new Vector3(0,0,0), Quaternion.identity);
            _isBossSpawned = true;
        }
        
    }
}

So when enemy is spawned i try to init him here enemy.Init(); but had error Object reference not set to an instance of an object. But here Debug.Log(enemy._enemyHealth); i get number of enemy health. How i can Init my enemy from here if enemy has class 'Usual Enemy' and it extends from this class 'Enemy' and i wiil have more enemy child cllases?

  • Please provide full call stack of where you get `NullReferenceException` – bashis Jun 01 '23 at 11:00
  • @bashis NullReferenceException: Object reference not set to an instance of an object Enemy.enemySpawn () (at Assets/Scripts/PlayScene/Enemies/Enemy.cs:113) Enemy.Init () (at Assets/Scripts/PlayScene/Enemies/Enemy.cs:65) EnemiesSpawner.SpawnEnemies () (at Assets/Scripts/PlayScene/Enemies/EnemiesSpawner.cs:67) EnemiesSpawner.Update () (at Assets/Scripts/PlayScene/Enemies/EnemiesSpawner.cs:55) – Андрей Королёв Jun 01 '23 at 11:09
  • 1
    Post the full exception text *in the question itself*. That call stack shows that the error occured in `Enemy.enemySpawn()`, not `Init()`. That method is trying to access three fields. One of them is null. Which line is `Enemy.cs:113`? – Panagiotis Kanavos Jun 01 '23 at 11:20

1 Answers1

0

The problem is not about "enemy" object. It is not null. If you look at the last reference on your call stack, you see that it is "_animator" field.

It's probably because you call the "Init" function before the "enemy" object's "Start" method called by Unity engine.

Cenkisabi
  • 1,066
  • 8
  • 25