Home > Back-end >  How to check if a game object is active when outside of its script?
How to check if a game object is active when outside of its script?

Time:10-05

I have a function in the Patient script which adds the patients to the DoctorsPatients list, effectively "assigning" that patient to the doctor. This works fine, but now I want to remove the patients from this list if they are inactive. I am trying to use the Update() function in Doctor to periodically check the list for inactive patients and remove them.

Doctor script:

 public class Doctor : Monobehaviour
{

 public List<Patient> DoctorsPatients = new List<Patient>();

 void Update()
    {
        foreach(Patient pat in DoctorsPatients)
        {
            if (pat.activeSelf == false)
            {
                DoctorsPatients.Remove(pat);
            }
        }
    }
}

I also tried adding in

Patient patient;

in the variables section and changed the loop to this:

        foreach(Patient pat in DoctorsPatients)
        {
            patient = pat.GetComponent<Patient>(); //Target the script?? sometimes works
            if (patient.activeSelf == false)
            {
                DoctorsPatients.Remove(patient);
            }
        }

and I get the same error: " error CS1061: 'Patient' does not contain a definition for 'activeSelf' and no accessible extension method 'activeSelf' accepting a first argument of type 'Patient' could be found (are you missing a using directive or an assembly reference?)"

It seems like I get an error like this every time I want to access game objects from other game objects but this time I cannot solve it with google alone. Thanks.

CodePudding user response:

Two things:

  • activeSelf is implemented in GameObject so since your Patient class seems to be a MonoBehaviour you can get it via its property gameObject so it would simply be

    if(!pat.gameObject.activeSelf)
    
  • BUT while iterating a collection using foreach you may not alter this collection by removing elements from it!

    You could however combine both things using List<T>.RemoveAll which in one call goes through the entire list and removes all elements fulfilling a certain condition

    DoctorsPatients.RemoveAll(pat => !pat && !pat.gameObject.activeSelf);
    

    where pat is the iteration variable just like in foreach(var pat in DoctorsPatients).

    I just added also the !pat to first filter also out any already destroyed instance before accessing and checking the gameObject of it to prevent any exceptions.

CodePudding user response:

Realized from the answer by DerHugo that I needed to use pat.gameObject.activeSelf(). It appears gameObject is a separate thing from the MonoBehaviour object. I came up with my own solution since I couldnt figure out how to get RemoveAll to cooperate with my foreach loop as DerHugo suggested.

Here's my solution using a standard for loop that allows me to remove elements while iterating:

for(int i = 0; i<DoctorsPatients.Count; i  )
{
    if (!DoctorsPatients[i].gameObject.activeSelf)
    {
        DoctorsPatients.RemoveAt(i);
    }
}
  • Related