I am trying to destroy a child object but I've come across an error that I have no idea about

This is my Guns script and I want it to create a new bullet when user presses space and call the event which gives its initial velocity dependent on what type of bullet it is and what type of gun it was shot off of inside Bullets class,
For determining the type of the bullet I just simply drag one of my bullet prefabs onto gameobject field in the inspector

public class Guns : MonoBehaviour
{
  
    [SerializeField] GameObject bullet;
    [SerializeField] float initialBulletDistance = 0.05f;
    [SerializeField] float fireRate = 1f;
    [SerializeField] float bulletVelocity = 3f;



  
    float gunHeight;
    public event EventHandler<BulletArgs> Fire;

    private void Awake()
    {
        Sprite[] temp = new Sprite[] { };
        FindObjectsOfType<Sprite>().CopyTo(temp, 0);

        foreach (var item in temp)
        {
            if (item.name.ToUpper().Contains("GUN"))
            {
                gunHeight = item.rect.size.y / item.pixelsPerUnit;
                break;
            }
        }
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
            Shoot();
    }

    void Shoot()
    {
        var args = new BulletArgs();
        bullet = Instantiate(bullet, transform.position, Quaternion.identity);
        bullet.transform.position = new Vector2(transform.position.x, transform.position.y + gunHeight + initialBulletDistance);
        args.BulletSpeed = bulletVelocity;
        OnShoot(args);
    }

    protected virtual void OnShoot(BulletArgs e)
    {
        Fire?.Invoke(this, e);
    }


}

Then I want bullets to destroy themselves when they get out of the perpective of the camera
But whenever a bullet is out of the camera and get destroyed,I can not instantiate another bullet and receive an error.I’ve tried many things to solve it but I couldn’t figure a way out.

public class Bullets : MonoBehaviour
{

  
    Guns parentGun;
    float maxy;

    private void Awake()
    {
        parentGun = FindObjectOfType<Guns>();
        parentGun.Fire += Shoot;
        maxy = Camera.main.ViewportToWorldPoint(new Vector3(0, 1, 0)).y;
    }

    private void Update()
    {
        CheckIfBulletOut();
    }

    void Shoot(object sender, BulletArgs e)
    {
        gameObject.GetComponent<Rigidbody2D>().velocity = new Vector2(0, e.BulletSpeed);
    }

    void CheckIfBulletOut()
    {
        if (transform.position.y > maxy)
            DestroyImmediate(gameObject);
    }

and I uploaded my error message below(I don’t know where it will pop up since it’s my first time creating a thread)

I’m pretty new in unity and am not sure if any of the codes I’ve written is correct in terms of general usage/implementation.So you are totally free to criticise me and my code.I would like to learn better/easier ways to implement things

Edit: Thanks to all of you guys for your helps and sharing knowledge with me,I eventually found the answer.It was becasue I did not deregister the event from my Shoot() method,so the program tried to call destroyed bullets’ Shoot method and I received the error even if I do null checking

6679456--765469--error.png

The error should also list the line of code causing it. It means you have destroyed the object you had a reference for yet are still trying to use it. Your code should be organized in a way that this can never happen and you should not be creating nor destroying objects during runtime; while you are accepting player input; during game play. You should be pooling and recycling.

What is pooling and recycling exactly?I think I have to destroy bullets somehow for the sake of memory,could you explain in more detail?

Use Destroy() instead Unity - Scripting API: Object.DestroyImmediate (unity3d.com)
Use null checking where need:

if (!System.Object.ReferenceEquals(anObject, null))

In the Bullet use OnBecameInvisible() instead frequent check in Update.

I actually used Destroy() in the first place,it does not actually help the error.I will try implementing null checking as soon as I understand where I should actually implement it

You use too complex way here:

parentGun = FindObjectOfType<Guns>();

Better use classes Bullet and BulletPool.
No need to find all guns inside every bullet.
I use usually Unity - Scripting API: GameObject.FindWithTag for object finding.
And mark the object by tag in inspector.
Better when shoot take the bullet from pool in gun and place it there back when it is out of the screen.
About pools I recorded two video. I don’t know how it understandable because it is with subtitles on the game example without voice and any code. Could you check it for understandability?

Pooling is creating a array of objects, in your instance bullets, at load time. You create more then you would ever use and then activate them when you need them and deactivate them instead of destroying; this way you never create or destroy after the load sequence.

On a separate note…
A null check could be used before the error occurred when accesing the object that did not exist anymore; as in your case. ‘if(theGameObjectBeingReferenced != null)’ then this will not happen if there is no object preventing the error.

yeah I could use FindWithTag() but the things is I have a pair of guns on a ship,so I would have to name two guns differently and somehow I don’t find it practical for my case(am not sure tho),btw your videos are understandable but you should make enemies harder :slight_smile:

But I need to figure out why and where the problem occurs,otherwise even if I prevent the error,the player will possibly not be able to shoot again once some previous bullets are destroyed.And is deactivating an object as efficient as destroying it?If player shoots a thousand times,then there will be 1000 disabled objects but they are still objects and do take space in the memory?Or am I getting the point wrong?

Ok. Yes I made the error with space orientation for sprites. Now I changed sprites (I painted in paint3d my own sprites for one of versions of the game, for other version took existing flying sauser and painted it - it is the main ship now) and do testing. I replaced the bottom ship with sauser - it is like top enemies in 3d now.