Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question Monitor another GameObject until their `Start()` is Finished?

Discussion in 'Scripting' started by redapplesonly, Jun 11, 2023.

  1. redapplesonly

    redapplesonly

    Joined:
    Nov 8, 2021
    Posts:
    42
    In my Unity game, I have two GameObjects, "GO1" and "GO2". In GO1, the `Start()` method initializes a number of global variables:

    Code (CSharp):
    1. public class GO1 : MonoBehaviour
    2. {
    3.     public AudioSource[] mySounds;
    4.  
    5.     void Start()
    6.     {
    7.         // Initialize mySounds here
    8.     }
    9. }
    And elsewhere in the game, GO2 will need to access those 'mySounds' variables. The trouble is, GO2's code tries to access 'GO1.mySounds' BEFORE `GO1.Start()` is finished executing.

    So, how to delay GO2 long enough to `GO1.Start()` to finish? Through research, I hit on this code:

    Code (CSharp):
    1. public class GO1 : MonoBehaviour
    2. {
    3.     public AudioSource[] mySounds;
    4.     public bool started = false;        // Added!
    5.  
    6.     void Start()
    7.     {
    8.         // Initialize mySounds here
    9.         this.started = true;   // Allows others to check that Start() is finished
    10.     }
    11.  
    12.  
    13. public class GO2 : MonoBehaviour
    14. {
    15.     public void accessSounds()
    16.     {
    17.         GO1 go1 = GameObject.Find("GO1").GetComponent<GO1>();
    18.         go1.StartCoroutine(stall(go1, () =>
    19.         {
    20.             Debug.Log("go1.Start() is done!");
    21.         }));
    22.         go1.mySounds[i].Play();     // Access GO1's variables
    23.     }
    24.  
    25.     IEnumerator stall(GO1 go1)
    26.     {
    27.         // Stall long for GO1.Start() to finish
    28.         while (go1.isActiveAndEnabled && !go1.started)    // Check the new variable
    29.             yield return null;
    30.     }
    31. }
    On paper, this solution looks good, I guess. When I implement this, it seems to work... but I dunno. It does "feels" like a bit of a hack. Do I really need that entire `stall()` method, just to watch a remore bool? Does anyone have any smarter suggestions?

    EDIT: I did find this post... and while it seemed to follow my logic, I'm still hoping someone else has found a smarter solution. All suggestions welcome...
     
    Last edited: Jun 11, 2023
  2. DevDunk

    DevDunk

    Joined:
    Feb 13, 2020
    Posts:
    4,362
    Don't try to organize start methods.

    1. Use awake to set up everything and start to actually implement logic and references

    2. Have a manager class setting up both in order

    3. When absolutely necessary change the script order in project settings
     
  3. redapplesonly

    redapplesonly

    Joined:
    Nov 8, 2021
    Posts:
    42
    @DevDunk This is excellent advice for a rookie like me, thank you. Is this something like what you would recommend:

    Code (CSharp):
    1. public class EverythingManager : MonoBehaviour
    2. {
    3.     void Awake()
    4.     {
    5.         GameObject go1 = Instanciate(SoundMaker_prefab);
    6.         GameObject go2 = Instanciate(SoundPlayer_prefab);
    7.         go1.AddComponent(GO1.GetType());  // Attach C# script for this GO
    8.         go2.AddComponent(GO2.GetType());  // Attach C# script for this GO
    9.     }
    10. }
    11.  
    12. public class GO1 : MonoBehaviour
    13. {
    14.     public AudioSource[] mySounds;
    15.     void Awake()
    16.     {
    17.         // Initialize mySounds;
    18.     }
    19. }
    20.  
    21. public class GO2 : MonoBehaviour
    22. {
    23.     void Awake() {...}
    24.  
    25.     public void accessSounds()
    26.     {
    27.         GO1 go1 = GameObject.Find("GO1").GetComponent<GO1>();
    28.         go1.mySounds[0].Play();   // Plays initialized sound
    29.     }
    30. }
     
  4. DevDunk

    DevDunk

    Joined:
    Feb 13, 2020
    Posts:
    4,362
    Except using AddComponent in a weird way (I always use AddComponent<component>()
     
    redapplesonly likes this.
  5. redapplesonly

    redapplesonly

    Joined:
    Nov 8, 2021
    Posts:
    42
    @DevDunk Thanks Dev! I'll try it out. Much love!
     
    DevDunk likes this.
  6. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,561
    Find and Get and Add mechanisms really are sooper dooper crazy advanced ninja territory... you may wish to stop it with that stuff and just do like you do in Unity: drag references into prefabbed objects and fill out stuff.

    Remember the first rule of GameObject.Find():

    Do not use GameObject.Find();

    More information: https://starmanta.gitbooks.io/unitytipsredux/content/first-question.html

    More information: https://forum.unity.com/threads/why-cant-i-find-the-other-objects.1360192/#post-8581066

    In general, try NOT to use "find" or "get" or "add" style methods unless there truly is no other way, eg, dynamic runtime discovery of arbitrary objects. If something is built into your scene or prefab, make a script and drag the reference(s) in so that you experience the highest rate of The Unity Way(tm) success of accessing things in your game.
     
    redapplesonly and Ryiah like this.
  7. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    20,082
    That link (and the base URL for that matter) leads to a 401 page not found.

    GameObject.Find() has a high performance cost, and it's dependent on a string which the compiler can't catch if it somehow becomes set it to a value that doesn't line up with the object it's searching for making it potentially very difficult to find the problem.

    https://en.wikipedia.org/wiki/Magic_string
     
    Last edited: Jun 11, 2023
    redapplesonly likes this.
  8. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,561
    redapplesonly likes this.
  9. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    20,082
    How odd. I just tried again and it worked this time. I flush my cache daily so I wonder if it wasn't just timing.
     
    redapplesonly and Kurt-Dekker like this.
  10. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,561
    Thinking on it, this isn't the first time that site has chonked...

    I wonder if it is because if you are logged into github, somehow gitbooks.io can use that token but cannot refresh it the way github can when it expires?

    But I ain't no network guy these days...
     
    redapplesonly and orionsyndrome like this.