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 Instantiate - How to Pass Data to a Script

Discussion in 'Scripting' started by torben-kley, Jun 17, 2023.

  1. torben-kley

    torben-kley

    Joined:
    Jun 12, 2023
    Posts:
    12
    Is there no clean way to provide data to a GameObject's Script directly when Instantiating ? I am currently looking for an option to pass data to my script. I spawn enemies in my game, but the script is empty at first. I found some article how to pass data, but they are always just workarounds, I feel like atleast. Some kind of "Setup" Method that is called after the GameObject is created. Is there no direct way to pass data to the script when created?
     
  2. StarBornMoonBeam

    StarBornMoonBeam

    Joined:
    Mar 26, 2023
    Posts:
    209
    For example

    You would create a reference to your script.

    Code (CSharp):
    1.  
    2. GameObject InstantiatedObject = Instantiate(YourGameObject)!
    3. var MyScript = InstantiatedObject.GetComponent<MyScript>();
    4. MyScript.SomeVariable = SomeValue;
    5.  
     
    Ryiah likes this.
  3. torben-kley

    torben-kley

    Joined:
    Jun 12, 2023
    Posts:
    12
    First of All, thanks for the answer, but that is the way I try to avoid, cause after the Instantiate, the Object is already running and Update/etc will already process. I am looking for a way to set the scipt values before instantiate.
     
  4. StarBornMoonBeam

    StarBornMoonBeam

    Joined:
    Mar 26, 2023
    Posts:
    209
    Oh I see, well then prefabs are the method.

    Start won't occur until next frame. So you shouldn't really be too worried about doing it that way. I have not encountered an issue with that before. You may want to check if assigning variables following an instantiate is actually problematic or whether it's a superstition you have picked up from a mistake in a previous project or something.

    Prefabs will otherwise work for you.
    But if you didn't want to make prefabs you could create a bunch of objects in the hierarchy on start and reference those objects as if they are prefabs.

    You should also check if the instantiated scripts start had set any variables that you wanted to modify on instantiate. Because in that case it could seem to undo any variables you set. But you know that is something I couldn't possibly know that is happening. But it's definitely a possibility.
     
  5. torben-kley

    torben-kley

    Joined:
    Jun 12, 2023
    Posts:
    12
    Okay, good take. Already using Prefabs, but I have the problem that i tyred to have the Variables like Movementspeed/Basedamage etc out of the editor in a seperate xml and ready them at the startt of the program. Dunno if that works then tho.
     
  6. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,468
    This isn't true. Update is called for all scripts during the update cycle of the player-loop, not immediately after you instantiate.

    You are also free to ensure that the root GameObject prefab you're cloning is disabled so you can clone it, set whatever you like then finally enable it so you can react in the Awake callback etc.

    https://docs.unity3d.com/Manual/ExecutionOrder.html
     
    halley and torben-kley like this.
  7. StarBornMoonBeam

    StarBornMoonBeam

    Joined:
    Mar 26, 2023
    Posts:
    209
    Via XML. Very interesting I know what you mean. I am not knowledgeable on how unity specifically is performing that during GO creation. But yes in a VS game. I see what you're going for. I can't be of any more help on that. So il drop here hopefully somebody can answer that. That's an interesting approach.
     
  8. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    5,769
    It's literally the one, only, and best way you pass values to objects that you're instantiating. Doing it before you instantiate it doesn't make sense, as the copy doesn't even exist at that point.

    If you want them to have values before you instantiate them, then those values should already be in the prefab in the first place.

    No idea why you'd keep all your values out of the editor in XML. That just seems like ignoring the primary purpose of the editor... to edit values inside of it.
     
    torben-kley likes this.
  9. torben-kley

    torben-kley

    Joined:
    Jun 12, 2023
    Posts:
    12
    I wanted the parameter of the prefabs combined in an XML. I want to make them editable in the game and saveable but I maybe have to rethink that. I use the Prefabs to give them logic, but want the Variables be loaded of a XML, so I can load the xml on the gamestart.
     
  10. torben-kley

    torben-kley

    Joined:
    Jun 12, 2023
    Posts:
    12
    Good take, have to think about that one.
     
  11. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,563
    Factory Pattern in lieu of AddComponent (for timing and dependency correctness):

    https://gist.github.com/kurtdekker/5dbd1d30890c3905adddf4e7ba2b8580

    Friends don't let friends use XML. It's 2023. Seriously. We have evolved. Use JSON if you must, otherwise keep your data all inside of Unity with something like ScriptableObjects.

    Unity supports extremely robust custom data authoring and custom editor extending to support it. You could make any editor you want within Unity and capture all the data using Unity's in-built classes.
     
  12. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    20,082
    What does this mean precisely? Are you referring to players modding them? Or are you just referring to saving the state of the object?
     
  13. torben-kley

    torben-kley

    Joined:
    Jun 12, 2023
    Posts:
    12
    Did not implement the XML yet, will just do JSON then, thanks man
     
  14. torben-kley

    torben-kley

    Joined:
    Jun 12, 2023
    Posts:
    12
    already found a way. Directly loading the Data in The Contructor instead of passing it in by parameters
     
    SisusCo likes this.
  15. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    20,082
    MonoBehaviour (and ScriptableObject) constructors shouldn't be used. Unity uses these under the hood with the expectation that you don't try to set them up yourself. Trying to use them will lead to problems that are difficult to track down. The code that @StarBornMoonBeam gave earlier is the correct approach.
     
    Last edited: Jun 18, 2023
  16. SisusCo

    SisusCo

    Joined:
    Jan 29, 2019
    Posts:
    1,104
    Parameterless constructors can be defined in components, and they will get executed automatically when Unity creates the instance. There are however a couple of caveats:
    1. The constructor is executed before deserialization takes place, so anything you assign to serialized fields will get overridden during deserialization. This is mentioned in Unity's documentation for Awake.
    2. Constructors are not executed on the main thread (just like ISerializationCallbackReceiver methods).
    3. When instantiating a prefab, the constructor can get executed more than once (on different instances) as part of the deserialization process.
    In this case, since the data will be read from a file, a parameterless constructor could indeed be used.

    Also, I believe File.ReadAllText, for example, can be used to read text from the same file on multiple threads simultaneously.

    If however you need to have support for assigning data to serialized fields, or want to avoid doing unnecessary work during instantiation, you could do the reading in OnAfterDeserialize or Awake instead.


    As an alternative solution, I also do have an asset which makes it possible to pass any arguments to objects during instantiation.
     
    Last edited: Jun 18, 2023
    Ryiah likes this.
  17. halley

    halley

    Joined:
    Aug 26, 2013
    Posts:
    1,834
    In general, you can follow this process to instantiate without allowing the new thing to run any Unity callback code (Awake, OnEnable, Start, Update, etc.):

    * create an Empty
    * deactivate the Empty
    * Instantiate whatever prefab you like, as a child of the inactive Empty
    * do whatever initialization you want before any of the prefab code can run
    * unparent the prefab (set parent to null), or activate the Empty to allow the prefab code to run

    Avoid constructors on MonoBehaviours. As mentioned above, code in constructors and field initializers will run even with this approach.
     
    SisusCo and Ryiah like this.
  18. SisusCo

    SisusCo

    Joined:
    Jan 29, 2019
    Posts:
    1,104
    Also the constructor and OnAfterDeserialize get executed even in edit mode (e.g. when you select a prefab), while Awake won't.
     
    Ryiah likes this.