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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Code in Start() is running twice?

Discussion in 'Scripting' started by Corva-Nocta, Jan 4, 2019.

  1. Corva-Nocta

    Corva-Nocta

    Joined:
    Feb 7, 2013
    Posts:
    801
    So I'm not sure why this small batch of code is running twice for me. Even weirder, it is in the Start() function so I would think it should only run once.

    Here is the section of code that is running 2 times:
    Code (csharp):
    1.  
    2. public List<GameObject> allParts = new List<GameObject>();
    3.  
    4. Start()
    5. {
    6.    GameObject[] allPartsInLevel;
    7.    allPartsInLevel = GameObject.FindGameObjectsWithTag("Part");
    8.    foreach (GameObject partInLevel in allPartsInLevel)
    9.    {
    10.       allParts.Add(partInLevel);
    11.    }
    12.  
    13.    PopulateVariables();
    14. }
    15.  
    I added in the PopulateVariables() simply because I added a debug in that function to run every time the function runs and it only runs once. So no idea why the rest is running twice.

    Here is what the code actually does.
    I have a bunch of gameobjects in a level called Parts, when the level runs it grabs every single Part in the level and adds it to the list. What happens instead is it grabs every single Part in the level and adds it to the list, twice. No idea why though.

    Any help at all would be great!
     
  2. unitynoob24

    unitynoob24

    Joined:
    Dec 27, 2014
    Posts:
    398
    So I'm thinking this could be a few things. Either you have more than one instance of this script running. Or, you have more things tagged as Part than you know of.
     
  3. WallaceT_MFM

    WallaceT_MFM

    Joined:
    Sep 25, 2017
    Posts:
    394
    I don't see any problem in that portion of code, so the issue is probably something else. You could try doing this just to check:
    Code (csharp):
    1. public List<GameObject> allParts = new List<GameObject>();
    2.  
    3. Start()
    4. {
    5.    allParts.AddRange(GameObject.FindGameObjectsWithTag("Part"));
    6.    Debug.Log("Adding...");
    7.    PopulateVariables();
    8. }
    Based on PopulateVariables()'s name, I'm a bit suspicious of what it's actually doing. It might be adding things to the list again.
     
  4. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,120
    Two things to check:
    1. Are you sure it's being called twice for the same object? Any chance you've just got two instances of this component in your scene?
    2. Any chance you're calling "new" to create this, instead of AddComponent? (You shouldn't use "new" to create new instances of MonoBehaviours, otherwise its Start method can be called multiple times...)
     
    ercindedeoglu likes this.
  5. DownER149

    DownER149

    Joined:
    Sep 11, 2018
    Posts:
    61
    probably have two instances of the same script on the object, (as everyone else here is saying)
    it happened to me a few minutes ago, thought i fixed it once already but i must of forgot to save my scene after fixing it.
    probably stems from having a instance of a prefab in the main scene then creating a prefab of it, adding the script to the prefab, the prefab will only have one instance but the one you left on the scene will have two... at least that is what i believe was my scenario.
     
    ercindedeoglu likes this.
  6. Corva-Nocta

    Corva-Nocta

    Joined:
    Feb 7, 2013
    Posts:
    801
    Lots of answers! Awesome! So to respond in order:


    Unfortunately I do not have any extra instances of the script running, nor do I have extra objects with the Part tag. I tested by adding more part than just the 1 I had in my scene (each part being named differently) and it still adds each part twice for some reason.


    I'll try doing the debug that way. Maybe it's pulling something I am not seeing. As for the populateparts() this is the code for that part:
    Code (csharp):
    1. PopulateParts()
    2. {
    3.    visibleParts.Clear();
    4.    foreach (GameObject visible in allParts)
    5.    {
    6.       if (visible.activeSelf)
    7.       {
    8.          visibleParts.Add(visible);
    9.       }
    10.    }
    11. }
    That code runs just fine like it should. It just populates a second list I have.


    1.) Yup, calling twice for the same object. I added even more objects to test this and for every object I add, it grabs the object twice.
    2.) All the code runs in the start() function so I don't think new or addcomponent would do anything here. No components are being added and the lists are called as new only at the level start
     
  7. Corva-Nocta

    Corva-Nocta

    Joined:
    Feb 7, 2013
    Posts:
    801
    I considered there being two instances, but I don't think its possible. The empty object with this script is part of a prefab with many other objects, but there is only 1 copy of that prefab in the level (and only 1 copy of this script)
     
  8. Corva-Nocta

    Corva-Nocta

    Joined:
    Feb 7, 2013
    Posts:
    801
    I added debugs everywhere to see if any of them fire twice, none of them did. They all operate once. So I must be calling it twice somewhere but I can't see anywhere in my code that I am.

    I even tried commenting out the list allParts to see how many scripts throw up errors. Theoretically if there's a part of the script that is trying to add to the list it should throw the error. I only got 2 errors, and they are exactly where I thought they would be. So I don't believe I am calling the script twice from anywhere within itself
     
  9. Corva-Nocta

    Corva-Nocta

    Joined:
    Feb 7, 2013
    Posts:
    801
    So for a lark I tried moving all of the relevant code from the Start() function into the PopulateParts() function, just to see what happens. Interestingly, the exact same thing happens. So I think there's an issue somewhere with how I'm getting the gameobjects. Is there a better way I should be grabbing all the gameobjects with the tag Part? This is the same methode I've used for tons of projects so I can't see why it would cause problems
     
  10. Corva-Nocta

    Corva-Nocta

    Joined:
    Feb 7, 2013
    Posts:
    801
    I'm narrowing it down, somewhat. The PopulateParts() function is running twice, but I only call it once and that is at the Start() function.

    I've checked my scene with a fine toothed comb, both in the editor and while the game is running. I can't find anywhere that has the same script, so it shouldn't be running twice. And if I did have two copies then other parts of the script should be running twice (but that doesn't happen)

    Still no answers
     
  11. ADNCG

    ADNCG

    Joined:
    Jun 9, 2014
    Posts:
    990
    You can right click the script in your project folder and do Find References in Scene. This isolates all the instances + everything that references to it within the hierarchy, IIRC.
     
  12. Adrian

    Adrian

    Joined:
    Apr 5, 2008
    Posts:
    1,051
    Your allParts list is public and will therefore be serialized. So when the Start method runs, the list might not be empty. If you want to populate the list from code, you should either make it non-public or add the [NonSerialized] attribute.

    To check if you have multiple instances, you can add a debug log like this:
    Code (csharp):
    1. Debug.Log("MyScript.Start " + GetInstanceID(), this);
    Then you can check in the logs if you see multiple instance IDs. Thanks to the ", this", you can also click the log to highlight the object in the scene. (This is also useful when you have multiple objects and you want to see which object a log is coming from.)
     
    Ubrano, Cinged and DownER149 like this.
  13. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,584
    I would try definitely first
    suggestion.

    If that however fails, I would disable all objects, and create one single active object for the scene. Then attach the script to it. And try to run it. Should run once. If so, you may have other references issues somewhere.

    Worth to check what @Adrian suggests.
     
  14. Corva-Nocta

    Corva-Nocta

    Joined:
    Feb 7, 2013
    Posts:
    801
    I ended up rebuilding it on a separate script and it is working fine now. I'm pretty sure I ended up duplicating my code that adds to the list within the PopulateParts() function so it was adding the same thing twice when it was supposed to split it up. But now I have a slightly different way of doing things since I rebuilt the code and its probably a little more efficient.

    Thanks for all the input!
     
    Antypodish likes this.
  15. T5Shared

    T5Shared

    Joined:
    Oct 19, 2018
    Posts:
    152
    I know you have a different version of the code working now, but could you not just put a debugger breakpoint in the PopulateParts() function and check who's calling it? In case you are still curious (and you got ME curious as well ;) )
     
  16. marcypotter16

    marcypotter16

    Joined:
    Oct 30, 2021
    Posts:
    3
    You saved me, I was stuck on this problem of methods running more than expected and I discovered that I had a child object with attached the same script as the parent => duplicating the code
     
    chemicalcrux likes this.
  17. Juice-Tin

    Juice-Tin

    Joined:
    Jul 22, 2012
    Posts:
    233
    Debug.Log is always your friend.

    you could have put a log in the foreach loop, pronting out the name of each part, and at the end, pront out the name of the gameobject itself.

    this would show when the parts were being added (all in this script, or separate scripts, and how many objects the script was running on.
     
  18. chemicalcrux

    chemicalcrux

    Joined:
    Mar 16, 2017
    Posts:
    717
    Another cool thing: Debug.Log can take two arguments

    Debug.Log("Hello!!!", gameObject);


    Clicking on the log message will select the game object.
     
    Oelson likes this.
  19. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,541
    Right, in addition you can add a second argument to Debug.Log. This is a "context" object and can be any UnityEngine.Object derived object (GameObject, Transform, MonoBehaviour, Mesh, Material, ....). When you passed a context object to Debug.Log, this object is linked to the log message. When you click on the message in the console, Unity will highlight / "ping" that object in the hierarchy / project window. So it's very easy to identify the "exact" object, even when the names are identical