0

I'm new at programming. I started a Unity3D course at udemy, I already finished the course, but I'm trying to add a buff to my game. What I want is when my player gets that buff, his shot speed inscreases, I tried to do it but im getting this error when I collide with it

NullReferenceException: Object reference not set to an instance of an object
Powerup.OnTriggerEnter2D (UnityEngine.Collider2D other) (at Assets/Galaxy Shooter/Scripts/Powerup.cs:54)

EDIT Album With usefull images

Player

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

public class Player : MonoBehaviour {

    public bool canTripleShoot = false;
    public bool movSpeedBoost = false;
    public bool shield = false;

    [SerializeField]
    private GameObject _laserPrefabs;

    [SerializeField]
    private GameObject _tripleShootPrefab;

    [SerializeField]
    private GameObject _shieldGameObject;

    [SerializeField]
    private GameObject _explosionPrefab;

    [SerializeField]
    private float _speed = 5.0f;

    [SerializeField]
    private GameObject[] _engines;

    [SerializeField]
    private float _fireRate = 0.25f;

    private float _canFire = 0.0f;
    public int playerHp = 3;
    public int _hitcount = 0;

    private UIManager _uiManager;
    private GameManager _gameManager;
    private SpawnManager _spawnManager;
    private AudioSource _audioSource;



    // Use this for initialization
    void Start () {
        _audioSource = GetComponent<AudioSource>();
        _spawnManager = GameObject.Find("Spawn_Manager").GetComponent<SpawnManager>();
        _uiManager = GameObject.Find("Canvas").GetComponent<UIManager>();
        _gameManager = GameObject.Find("GameManager").GetComponent<GameManager>();

        transform.position = new Vector3(0, 0, 0);

        if(_uiManager != null)
        {
            _uiManager.UpdateLives(playerHp);
        }

        if(_spawnManager != null)
        {
            _spawnManager.StartSpawn();
        }

    }

    // Update is called once per frame
    void Update ()
    {
        Movement();
        //ativar ao pressionar espaço ou botão esquerdo do mouse
        if (Input.GetKeyDown(KeyCode.Space) || Input.GetMouseButton(0))
        {
            Shoot();
        }

    }

    //renderização e cooldown dos tiros
    private void Shoot()

    {

        if (Time.time > _canFire)
        {
            _audioSource.Play();
            if (canTripleShoot== true)
            {
                Instantiate(_tripleShootPrefab, transform.position, Quaternion.identity);

            }
            else
            {
                Instantiate(_laserPrefabs, transform.position + new Vector3(0, 0.95f, 0), Quaternion.identity);

            }
            _canFire = Time.time + _fireRate;

        }
    }
    //calculo de dano
    public void Damage()
    {
        if(shield == true)
        {          
            shield = false;
            _shieldGameObject.SetActive(false);
            return;
        }

        _hitcount++;

        if(_hitcount == 1)
        {
            _engines[0].SetActive(true);
        }

        if(_hitcount == 2)
        {
            _engines[1].SetActive(true);
        }

        playerHp--;

        _uiManager.UpdateLives(playerHp);

        if(playerHp < 1)
        {
            Instantiate(_explosionPrefab, transform.position, Quaternion.identity);
            _gameManager.gameOver = true;
            _uiManager.ShowTitleScreen();
            Destroy(this.gameObject);
        }

    }

    public void ShieldUp()
    {
        shield = true;
        _shieldGameObject.SetActive(true);


    }
    //controle da velocidade de movimento e teleporte
    private void Movement()
    {
        float controleHorizontal = Input.GetAxis("Horizontal");
        float controleVertical = Input.GetAxis("Vertical");

        //velocidade de movimento
        if(movSpeedBoost == true)
        {
            transform.Translate(Vector3.up * _speed * controleVertical * Time.deltaTime * 2.0f);
            transform.Translate(Vector3.right * _speed * controleHorizontal * Time.deltaTime * 2.0f);
        }else
        {
            transform.Translate(Vector3.up * _speed * controleVertical * Time.deltaTime);
            transform.Translate(Vector3.right * _speed * controleHorizontal * Time.deltaTime);
        }


        //limita jogar até o centro da tela
        if (transform.position.y > 0)
        {
            transform.position = new Vector3(transform.position.x, 0, 0);
        }
        //limita jogar até a borda inferior
        else if (transform.position.y < -4.2f)
        {
            transform.position = new Vector3(transform.position.x, -4.2f, 0);
        }

        //teleporta jogar se sair da tela na horizontal
        else if (transform.position.x < -9.45f)
        {
            transform.position = new Vector3(9.45f, transform.position.y, 0);
        }
        else if (transform.position.x > 9.45f)
        {
            transform.position = new Vector3(-9.45f, transform.position.y, 0);
        }
    }
    //duração triple shot
    public IEnumerator TripleShotPowerDownRoutine()
    {
        yield return new WaitForSeconds(5.0f);
        canTripleShoot = false;
    }
    public void TripleShotPowerUpOn()
    {
        canTripleShoot = true;
        StartCoroutine(TripleShotPowerDownRoutine());

    }

    //duração boost de movimento
    public IEnumerator MovSpeedBoostDownRoutine()
    {
        yield return new WaitForSeconds(5.0f);
        movSpeedBoost = false;
    }
    //ativa boost de movimento e inicia contagem de duração
    public void MovSpeedBoost()
    {
        movSpeedBoost = true;
        StartCoroutine(MovSpeedBoostDownRoutine());
    }


}

Laser

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

public class Laser : MonoBehaviour {
    [SerializeField]
    public float _speed = 10.0f;
    [SerializeField]
    public bool _laserBoost = false;
    // Use this for initialization
    void Start () {
        _laserBoost = false;

        if (_laserBoost == true)
        {
            _speed = 100f;
        }
    }

    // Update is called once per frame
    void Update () {

        //código gigante e dificil de decifrar ~irony
        transform.Translate(Vector3.up * _speed * Time.deltaTime);
        if (transform.position.y > 6f)
        {
            if(transform.parent != null)
            {
                Destroy(transform.parent.gameObject);
            }
            Destroy(gameObject);
        }

    }
    public IEnumerator LaserBoostDuration()
    {
        yield return new WaitForSeconds(10f);
        _laserBoost = false;
    }
    public void LaserBoost()
    {
        _laserBoost = true;
        StartCoroutine(LaserBoostDuration());
    }

}

Powerup

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

public class Powerup : MonoBehaviour
{
    [SerializeField]
    private float _speed = 3.0f;
    [SerializeField]
    private int powerupID;
    [SerializeField]
    private AudioClip _clip;


    // Update is called once per frame
    void Update ()
    {
        //movimenta o powerup para baixo
        transform.Translate(Vector3.down * _speed * Time.deltaTime);
        //destroy o power ao sair da tela
        if (transform.position.y <-7)
        {
            Destroy(this.gameObject);
        }
    }
    private void OnTriggerEnter2D(Collider2D other)
    {

        if(other.tag == "Player")
        {
            //acessa o player
            Player player = other.GetComponent<Player>();

            if(player != null)
            {
                if(powerupID == 0)
                {
                    //ativa tripleshoot
                    player.TripleShotPowerUpOn();
                }
                else if(powerupID == 1)
                {
                    //ativa speedboost
                    player.MovSpeedBoost();
                }
                else if(powerupID == 2)
                {
                    //ativar shield
                    player.ShieldUp();
                }
                else if (powerupID == 3)
                {
                    Laser laser = GameObject.Find("laser").GetComponent<Laser>();
                    laser.LaserBoost();
                }


            }


            //detroy powerup
            AudioSource.PlayClipAtPoint(_clip, transform.position);
            Destroy(this.gameObject);
        }
    }
}

The error is occuring at

laser.LaserBoost();
  • Possible duplicate of [What is a NullReferenceException, and how do I fix it?](https://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it) – AresCaelum Jul 14 '18 at 14:44
  • 2
    Basically your GameObject.Find("laser").GetComponent() failed, you shouldn't really daisy chain those functions, as you would also get this error if GameObject.Find failed. you should always check that Laser is not null after calling getcomponent. So start by making sure the scene you are doing this indeed does have a GameObject named laser, and make sure it does have the component Laser. (GameObject.Find can be a very expensive call btw.) – AresCaelum Jul 14 '18 at 14:46
  • `void Start () { _laserBoost = false; if (_laserBoost == true) { _speed = 100f; } }` you know that this if statement will never be true, right? – Rodrigo Rodrigues Jul 15 '18 at 00:08
  • Is the Laser Game Object Active?? Find will only works if the object is active. If not, fund the component in the proper hierarchy. – Walter Palladino Jul 15 '18 at 00:52

1 Answers1

2

One of the two:

1) you don't have a object named "laser" in Scene hierarchy;

2) this object exists but doesn't have a component of type Laser attached to it.


Edit: Now that I saw your image, I can confirm it is the case 1) above. You have a Prefab named "laser", but is doesn't exist in the Scene hierarchy. If you want it to come to existence only when needed, you must instantiate the Prefab in scene.

If you want to search for the Prefab by its name, there is a way, but you'll need to have a folder named Resources inside another named Assets... More info here

Instead, I suggest you another approach. First, you will need a reference to your Prefab in some object, depending on the logic of your program. You seem to have a GameManager class, there could be a good place. Add a new field inside there (if it is the case) like this:

    [SerializeField]
    public Laser laser
    // (...)

Then, change the code that generates the error. GameObject.Find tries to find an object that already exists in scene. In your case, you want to instantiate a clone of a Prefab, by passing a reference to it. Something like this:

     else if (powerupID == 3)
            {
                // I don't know for sure how can you access your GameManager in your program. I will suppose your player have a reference to it.
                // You shall change the position depending on your game logic
                Laser laserClone = (Laser) Instantiate(player.gameManager.laser, player.transform.position, player.transform.rotation);
                laserClone.LaserBoost();
            }

Now, select the object in Scene that will have the reference (again, I am supposing it is gameManager) to see its inspector, than fill the laser field with a reference to your Prefab that has a Laser component. Just be sure the clone object will be destroyed when it is not needed.

But... To be very honest, I don't think you will get the result you are expecting anyway. If what you want is just faster shoot rate, the way you're trying to do it now seems pretty convoluted to me. Why don't you do it just like the triple shoot you have? Add a flag inside your player, when it is true the fireRate value changes.

Rodrigo Rodrigues
  • 4,605
  • 1
  • 16
  • 27