checking if any given element in an array is active

I have spot lights in an array with light covers(a plane) in another array using the arrays to make the lights flicker.

But now I am making the lights destructible and the code calling the flicker is whining about it.

How do I select each element in the arrays to check if they are there before flickering them or should I just attach code to each individual light group for more control?

Unity handily overloads their basic Object (out of which everything in Unity is derived, just about), with a boolean operator that tells you if they exist. Therefore you can just if-check them:

Light MyLightReference;

// to check if MyLightReference exists:
if (MyLightReference)
{
  // now it is safe to do things related to MyLightReference
}

It generally results in easier-to-maintain code if you gather things logically into their areas of concern, but sometimes this isn’t possible. It’s always a tradeoff, but if something truly will never be concerned with anything else, I would say group those things together as much as possible. Don’t go nuts with it and shred your project, but this is the relevant wikipedia discussion:

https://en.wikipedia.org/wiki/Separation_of_concerns

I don’t know if this is helpful, but maybe have a component adjust the intensity of the lights, and keep track of their “health” instead of setting them inactive or destroying them? This way you can track their health to know if their state in game logic is “dead” or not.

Also, as is common with any destructible thing, maybe you will want to pool them to enable re-use and avoid GC? (Of course, not everything that is destroyed gets re-used, but that’s dependent on the game.) Or at least save their destruction till scene change.

Kurt- I have like 40 spot lights in the array which is how I grab them all to flicker them…but if I destroy one the flicker code still tries to access it. So your above code is how I could check if they are there before flickering them? How could I do that for 40 lights?

This seems like a way I could do this but again it is 40 lights. I don’t know how I could track all their health.

You put them in a collection and iterate them!

To get them into a collection in the first place, you may do any of the following:

  • use the inspector to drag each one in
  • add them at runtime programmatically if that’s easier
  • discover them all at runtime with FindObjectsOfType()
  • other ways ?

Kurt

Rgr that, I’ll take a stab at it.

Well, it’s hard to know what your needs and limitations are from the description you’ve given. Two ways to check, however, are:

  1. You have a script that contains an array of all the lights and it goes through that array one by one checking them. This is fine, and it won’t take long. If you have a parallel array for light health also contained by this script, as you go through all the lights you can see what their light health is, and adjust the light intensity accordingly. This method is kind of like the new ECS model, where a system code adjusts data related to several different entities.

  2. Or, you can go the object oriented route, where you have a script on each light that is controlling their light behavior (intensity) based on health, and health is a variable that is on this component of each light. You could have it so that the light dims as health goes down, and you could have the component control a flickering effect - where the intensity rapidly rises and falls a few times before settling - when a light is hit. Since this script is placed on your prefab for the spotlights, it’s automatically included on each light you use.

Basically … you choose how you want to do it based on what direction you want to go with it all.

This is what I ended up doing. Works well.

You guys see anything that is an issue?

public class Lights_covers : MonoBehaviour
{
    public GameObject lightCover;

    public Light _light;

    private float lightIntensity = 3f;

    private bool lightsON = false;
    public int Light_Timer_ON = 0;
    public int Light_Timer_OFF = 0;

    public void Start()
    {
        lightsON = false;

        Light_Timer_ON = 0;
        Light_Timer_OFF = 0;
    }
    public void Update()
    {
        if (lightsON == true)
        {
            float light_Intensity_index = Random.Range(0f, lightIntensity);

            _light.intensity = light_Intensity_index;

            Light_Timer_OFF = Light_Timer_OFF + 1;
            if (Light_Timer_OFF == 50)
            {
                Light_Timer_OFF = 0;
                lightsON = false;
            }
            Material newMat = Resources.Load("Lights_ON", typeof(Material)) as Material;
            Renderer rendererer = lightCover.GetComponent<Renderer>();
            rendererer.material = newMat;
        }
        if (lightsON == false)
        {

            _light.intensity = 0;
           
            Material newMat = Resources.Load("Lights_OFF", typeof(Material)) as Material;
            Renderer rendererer = lightCover.GetComponent<Renderer>();
            rendererer.material = newMat;

            Light_Timer_ON = Light_Timer_ON + 1;

            if (Light_Timer_ON == 500)
            {
                Light_Timer_ON = 0;
                lightsON = true;
            }
        }
    }
}

I would guard line 22 and line 38 so that you’re not banging through all that code every frame for every one of these things.

You can do this by keeping a “previous” notion of lights on, then comparing it to make sure it changes.

At the end of Update() you just copy lightsOn over to the “previous” variable.

I always say beware premature optimization, but this definitely falls well into the basket of doing tons of stuff every frame that doesn’t need to be done.

How would I do that?

I’m in the Update because I am timing the lights.

Philosophically, you want to try to only have things that should be run in Update running in Update. Update runs every frame, so normally you only want things that directly affect each frame of rendering in this phase. Like … I think a rapid light flickering FX logic could go here, based on delta.time, if you want a higher fidelity effect at faster frame rates. By putting it in Update, the effect can update every frame.

I want to underscore this. Update can happen 30 times a second at one point, 60 times a second at another, and even like 500 times per second or more when you are running simple things in the editor. It’s highly variable.

There’s also a FixedUpdate phase, which runs on a regular clock tick regardless of frame. This is normally used for physics, which is something that unfolds at a steady rate regardless of frame rate. Like, you don’t want the player to see projectiles speeding up and slowing down based on frame rate. You want them moving steadily and predictably, based on real world timing.

Your main game logic should probably also run on a regular tick, independent of the frame rate. Like, if you are running an AI, you probably want to have it run at a regular rate, but not necessarily as frequently as physics, which is many times per second. Code for deciding whose turn it is, things like damage to lights, and deciding general light state (is it live / dead), would be the sort of thing to happen under your game clock.

All of that may be more complicated than you probably want to address right now. But it’s the big picture, which you want to be cognizant of, and try to start lining up your code with that in mind.

So in your code above, you should ask yourself if you really need to be doing all of those things every frame, or if you need more state logic in there, so you do certain things only once, when the state changes.

1 Like

@Kurt-Dekker

Isn’t doing this still hitting the Update every ms? I’m having a hard time figuring it out.

@hopeful I get it but I don’t know of any other way to that. Unless I just have the timer in the Updat or FixedUpdate and call the functions from there if the time hits its mark. That’s the only way I know how to do it.

You’ll understand more and more as you continue programming, so don’t worry about it. It sounds like you have this working for now. Probably you can just move on to your next task, and revisit this if/when you need to.

1 Like

@hopeful thank you