Is this the best for performance?

Hello,

I need to have health bars above enemies.
There is a LOT of enemies in the map and I need the most optimized solution.
I want to enable the OnGUI only when the camera is near enough to those objects.

What I did is I attached separate Script to each object, which has only OnGUI with drawing of the healthBar.

What I am doing now is enabling / disabling this component when the object is around like this:

(This function is called only once half a second to optimize it even more)
 void updateGUI()
    {
        GUI_SpaceShip[] script = GameObject.FindObjectsOfType<GUI_SpaceShip>();
        foreach(Component ship in script)
        {
            Vector2 distance = ship.gameObject.transform.position - cameraTransform.position;
            if (distance.magnitude < 300)
                ship.GetComponent<GUI_SpaceShip>().enabled = true;
            else
                ship.GetComponent<GUI_SpaceShip>().enabled = false;
        }
        
    }

But ofc the thing is there could be even 500+ objects in the scene.
Do you think it could be done better way?

This is very bad. Very, very bad. I’ll run through some of your performance fails here.

  1. From the documentation of FindObjectsOfType:

Please note that this function is very slow. It is not recommended to use this function every frame. In most cases you can use the singleton pattern instead.

Build a single manager script. Have every GUI_SpaceShip register in Awake and deregister in OnDestroy. (Or use OnEnable and OnDisable if you prefer). Then run through your loop.

  1. Store the actual components you wish to access. Using GetComponent is relatively slow. Calling GetComponent to get the component you already have is madness. So change your for loop to

    foreach(GUI_SpaceShip ship in script)

  2. For straight distance comparisons use sqrMagnitude, instead of magnitude. Its cheaper and achieves the identical result. Don’t use square roots unless you have to.

@GrahamDunnett’s approach of only registering when ready to display is another valid optimisation. Typically you don’t display health bars on items with no damage, so that could be further used to optimise.

The other big optimisation would be to abandon OnGUI. OnGUI is notoriously slow and inefficient, and is seldom used on high performance published games.

I think what I would do is have a script which handles the health bar drawing. The spaceships can then individually call this script and tell the script that they are close enough to be drawn, or have moved too far away to be visible. All the health bar script then needs do is iterate over the list of spaceships it contains and draw the health bar for each.