- Home /
 
More efficient Scripting.
Hello, I'm still learning C#, and I ran into whats not really a problem, but what I feel can be heavily improved upon.
The objectClock clock will not be counting in 5s, that's just for a test as the, but I still feel it could be improved. I will be adding more objects to the objectClock and change the clock variable to call the NewRandomObject function at different times.
I don't like the fact that the NewRandomObject function has to call itself over and over to find a new object if its already active. I was wondering if there's a way to check the objects array and grab only inactive objects?
It works for what I need it to do and was just wondering if y'all had any ideas that could make it cleaner and more efficient.
 using UnityEngine;
 using System.Collections;
 
 public class ObjectTimer : MonoBehaviour {
 
     private GameObject[] objects;
     private GameObject randomObjects;
     private int clock = 0;
     
     private void Start()
     {
         objects = new GameObject[transform.childCount];
         for (int i = 0; i < transform.childCount; i++)
         {
             objects[i] = transform.GetChild(i).gameObject;
         }
         StartCoroutine("objectClock");
     }
     
     private IEnumerator objectClock()
     {
         while (true)
         {
             yield return new WaitForSeconds(1);
             clock ++;
             Debug.Log (clock);
             if(clock == 1)
             {
                 NewRandomObject();
             }
             if(clock == 5)
             {
                 NewRandomObject();
             }
             if(clock == 10)
             {
                 NewRandomObject();
             }
             if(clock == 15)
             {
                 NewRandomObject();
             }
             if(clock == 20)
             {
                 NewRandomObject();
             }
             if(clock == 25)
             {
                 NewRandomObject();
             }
             if(clock == 30)
             {
                 NewRandomObject();
             }
             if(clock == 35)
             {
                 NewRandomObject();
             }
         }
     }
     
     private void NewRandomObject()
     {
         randomObject = objects[Random.Range(0, objects.Length)];
         if(randomObject.activeInHierarchy == true)
         {
             Debug.Log("Object already active; finding new object");
             NewRandomObject();
         }
         else
         {
             randomObject.SetActive(true);
         }
     }
 }
 
 
              Answer by Hellium · Jul 14, 2015 at 12:39 PM
This is what I would have done :
  using UnityEngine;
  using System.Collections;
  
  public class ObjectTimer : MonoBehaviour {
  
      private GameObject[] objects;
      private GameObject randomObjects;
      private int clock = 0;
      
      private void Start()
      {
          objects = new GameObject[transform.childCount];
          for (int i = 0; i < transform.childCount; i++)
          {
              objects[i] = transform.GetChild(i).gameObject;
          }
          StartCoroutine("objectClock");
      }
      
      private IEnumerator objectClock()
      {
          for( int clock = 0 ; clock < 36 ; ++ clock )
          {
              yield return new WaitForSeconds(1);
              if( ( clock % 5 ) == 0)
              {
                  NewRandomObject();
              }
          }
      }
      
      private void NewRandomObject()
      {
         int startIndex = Random.Range( 0, objects.Length );
         int index = 0;
         
         // Look for the first active object starting at a random index
         for ( index = startIndex ; !objects[Random.Range(0, objects.Length)].activeInHierarchy ; ++index )
         {
             // Prevent infinite loop
             if ( index - startIndex > objects.Length )
                 return ;
         }
         
         randomObject = objects[index] ;
      }
  }
 
              Where would you activate the randomly selected object, and what if you wanted to customize the clock to activate one random object at, say, 3 seconds and another at 8 seconds?
Oops, I missed the first point. Didn't see it. I changed the condition inside the for loop then.
  private void NewRandomObject()
   {
      int startIndex = Random.Range( 0, objects.Length );
      int index = 0;
      
      // Look for the first inactive object starting at a random index
      for ( index = startIndex ; objects[Random.Range(0, objects.Length)].activeInHierarchy ; ++index )
      {
          // Prevent infinite loop
          if ( index - startIndex > objects.Length )
              return ;
      }
      
      objects[index].SetActive(true) ;
   }
 
                  About the clock, if you don't want it to be regular, define a public array of int / floats called spawnTimes, and modify the coroutine as follow :
  private IEnumerator objectClock()
   {
       for( int clockIndex = 0 ; clockIndex <= spawnTimes.Length ; ++clockIndex )
       {
           yield return new WaitForSeconds(spawnTimes[clockIndex ]);
           NewRandomObject();
       }
   }
 
                  Then, in your inspector, you can specify the different times you want the NewRandomObject() to be called.
I made a mistake in the for loop of the coroutine, make sure you have corrected it.
(I edited my last comment)
Your answer
 
             Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
Unsuccessfully trying to clamp my player object 0 Answers
Weird functioning lists 0 Answers
C# Creating a More Efficient Script 4 Answers