- Home /
 
Modify a boolean for all instances of a class
Hello friends, I'm in my first week of learning Unity. What I am trying to achieve in this script is:
All prefabs "ssr", of type "aircraft" move on their y axis once every 5 seconds.
My approach is probably quite inefficient as I'm still learning, but I'm achieving this by running a script gameControl on an object also called gameControl. This script contains a coroutine that loops once every 5 seconds.
The aircraft script has a condition boolean "a" that will ensure that as part of the 5 second looped coroutine, the aircraft will only move by the variable groundSpeed a single time.
I have it working on the first instance of ssr, but subsequent instantiated prefabs are not working and stay still.
Scripts are below, I'm losing my mind a little on this one... thanks for your help!
 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 public class aircraft : MonoBehaviour
 {
     public float groundSpeed;
     //public aircraft ssr; do I actually need this?
     public static gameControl controls;
     public static bool a;
 
     void Awake()
     {
         controls = GetComponent<gameControl>();
         groundSpeed = 10.0f;
     }
     void Update()
     {
         if (gameControl.radarUpdate == true)
         {
             while(a == true)
             {
                 transform.position += Vector3.up * groundSpeed;
                 Debug.Log("moved by " + groundSpeed);
                 a = false;
                 Debug.Log("a is " + a);   
             }
         }
     }
 }
    
 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 public class gameControl : MonoBehaviour
 {
     public GameObject aircraftSymbol;
     public int track, x, y, a;
     public static bool radarUpdate = false, gameOver = false; //removed static
     public static aircraft link;
 
     void Awake()
     {
         //Application.targetFrameRate = 30; force framerate if required
         link = GetComponent<aircraft>();
         StartCoroutine(radar());
     }
 
     void Update()
     {
 
         if (Input.GetKeyDown("w"))
         {
             print("w");
             Vector3 pos = transform.position + new Vector3(50, 50, 1);
             Quaternion rot = Quaternion.Euler(0, 0, 0);
             Instantiate(aircraftSymbol, pos, rot);
         }
     }
 
     public IEnumerator radar()
     {
         while (gameOver == false)
         {
             aircraft.a = true;
             radarUpdate = true;
             print("updating radar");
             yield return new WaitForSeconds(1.0f);
             radarUpdate = false;
             print("not updating radar");
             yield return new WaitForSeconds(2.0f);
         }
     }
 }
 
              Answer by mjrsaunders · Nov 30, 2021 at 07:47 AM
Worked it out by using FindObjectsWithTag in conjunction with GetComponent as per below script replacing the old coroutine:
 public IEnumerator radar()
     {
         while (gameOver == false)
         {
             GameObject[] go;
             go = GameObject.FindGameObjectsWithTag("ssrTag");
             foreach (GameObject ssr in go)
             {
                 aircraft sc = ssr.GetComponent<aircraft>();
                 sc.a = true;
             }
 
 
             radarUpdate = true;
             print("updating radar");
             yield return new WaitForSeconds(1.0f);
             radarUpdate = false;
             print("not updating radar");
             yield return new WaitForSeconds(2.0f);
         }
     }
 
              Shouldnt this be?
 public IEnumerator radar()
      {
          while (gameOver == false)
          {
              print("updating radar");
              radarUpdate = true;
 
              GameObject[] go;
              go = GameObject.FindGameObjectsWithTag("ssrTag");
              foreach (GameObject ssr in go)
              {
                  aircraft sc = ssr.GetComponent<aircraft>();
                  sc.a = true;
              }
              
              radarUpdate = false;
              print("not updating radar");
              yield return new WaitForSeconds(3.0f);
          }
      }
 
                 Yes, your way is much cleaner. It still worked fine with the code I posted, just wasn't that worried about that part while I was working on the single update every 5 seconds (which does work with my messy code).
Answer by andrew-lukasik · Nov 30, 2021 at 11:35 AM
Entertain this:
AircraftComponent.cs
 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 public class AircraftComponent : MonoBehaviour
 {
     public static List<AircraftComponent> Instances = new List<AircraftComponent>();
     public static HashSet<AircraftComponent> InstancesSsrActive = new HashSet<AircraftComponent>();// hashset is similar to list<t> but also prevents duplicate entries
     
     public Vector3 velocity = new Vector3( 0 , 10 , 0 );
     public bool isSsrTransponderActive = true;
 
     void OnEnable ()
     {
         Instances.Add( this );
         if( isSsrTransponderActive ) InstancesSsrActive.Add( this );
     }
     void OnDisable ()
     {
         Instances.Remove( this );
         InstancesSsrActive.Remove( this );
     }
     void Update ()
     {
         transform.position += velocity * Time.deltaTime;
     }
 
     public void DisableSsrTransponder ()
     {
         isSsrTransponderActive = false;
         InstancesSsrActive.Remove( this );
     }
 
 }
 
               RadarComponent.cs
 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 public class RadarComponent : MonoBehaviour
 {
     [SerializeField] float _radarRefreshRate = 5f;
     [SerializeField] Mesh _iconMesh = null;
     [SerializeField] Material _iconMaterial = null;
     Matrix4x4[] _iconTransforms = new Matrix4x4[0];
 
     void OnEnable ()
     {
         InvokeRepeating( nameof(RadarPing) , 0 , _radarRefreshRate );
     }
     void OnDisable ()
     {
         CancelInvoke();
     }
 
     void LateUpdate ()
     {
         Graphics.DrawMeshInstanced(
             mesh:            _iconMesh ,
             submeshIndex:    0 ,
             material:        _iconMaterial ,
             matrices:        _iconTransforms
         );
     }
 
     public void RadarPing ()
     {
         int newLength = AircraftComponent.InstancesSsrActive.Count;
         if( _iconTransforms.Length!=newLength ) _iconTransforms = new Matrix4x4[ newLength ];
         
         int i = 0;
         foreach( var ssrTransponder in AircraftComponent.InstancesSsrActive )
             _iconTransforms[i++] = Matrix4x4.Translate( ssrTransponder.transform.position );
     }
 
 }
 
               PlayerInputController.cs
 using UnityEngine;
 
 public class PlayerInputController : MonoBehaviour
 {
     [SerializeField] GameObject _aircraftPrefab;
     void Update ()
     {
         if( Input.GetKeyDown(KeyCode.W) )
             Instantiate( _aircraftPrefab , Random.insideUnitCircle*10f , Quaternion.identity );
     }
 }
 
               player input is separated from radar & aircraft-specific code
aircrafts move however they want, radar does not control aircrafts
radar looks for aircrafts in dedicated & easy to manage lists

Thankyou so much for the detailed alternative. I was vaguely aware of lists being an option and will have a proper look at your suggestion so I can learn how to do it that way as well. Really appreciate it!
Your answer
 
             Follow this Question
Related Questions
Are sprites reference (script) loaded every time? 0 Answers
Persisting Prefabs across scenes 1 Answer
Animations on instantiated prefabs not working 0 Answers
how do i get the audio and prefabs to work in space shooter? 0 Answers
Switching between prefabs 0 Answers