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.

Immediately adjusting a newly instantiated object

Discussion in 'Scripting' started by gnhaines, Dec 23, 2017.

  1. gnhaines

    gnhaines

    Joined:
    Dec 4, 2017
    Posts:
    13
    I have a number of prefab projectiles in a public array in my "shooting" script.

    Code determines the appropriate index, then instantiates using this index, and immediately passes player and target positions to the behaviour script of the new projectile (The affect of these positions on the projectile's transform, velocity and other behaviours are very different for each of the projectiles).

    Is it possible to change the transform of the newly instantiated projectile so that it is not displayed in the wrong transform for one frame? From the documentation, it looks like Awake is the correct method to do this in? And Start will not work? Will awake run before or after the player and target positions are passed? If Awake runs before the line of code that passes the positions, one other option would be to use awake to set isNew = true and then apply the initial transform in LateUpdate using a conditional? I don't like that solution at all though.

    Or I could change settings in the Monomanager?

    and optionally: What's the best way to do this?

    Thanks!
     
  2. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Could you post your code for spawning these new projectiles?
    What version of Unity are you using, because there was a bug that's been fixed (I believe), with regard to the position being wrong in Awake().

    Should be no problem to pass the information when you create it.
    When you instantiate an object (just tested this to be sure), what I see is this:
    Awake called
    printed msg that I instantiated (this is where I could pass/set values)
    Start was called.

    If it were me, and I wanted to set the position and other values when I created the object, I would use the reference from the newly created object to do that, in many cases.
    Just depends on who should say where it goes. If it's the object that should say, then in its own awake is okay, but if it's the manager (script spawning it) that knows best, then that's where I'd set it, as it seems to make more sense to me.
     
    gnhaines likes this.
  3. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    6,476
    You can pass the position and rotation to the GameObject.Instantiate method:
    https://docs.unity3d.com/ScriptReference/Object.Instantiate.html

    You could also modify the transform right after Instantiate. That would be after Awake has been called, but before Start. In both cases, the object should appear at the correct position without being one frame off.

    That being said, there is/was an issue in Unity with modifying the transform inside Awake:
    https://issuetracker.unity3d.com/is...ect-dot-instantiate-after-awake-function-call

    You might also want to look into object pooling, as frequently instantiating GameObjects, can be rather expensive.
    https://unity3d.com/learn/tutorials/topics/scripting/object-pooling
    http://catlikecoding.com/unity/tutorials/object-pools/

    If you want to find out in what order Unity's magic methods like Awake, OnEnable, Start, etc are called, you can take a look at this documentation:
    https://docs.unity3d.com/Manual/ExecutionOrder.html
     
    samana1407 and gnhaines like this.
  4. gnhaines

    gnhaines

    Joined:
    Dec 4, 2017
    Posts:
    13
    Thanks, this actually helped a lot. I was running into other issues with my code because I had to GetComponent by type to reference the behaviour script, and then since at compile time I hadn't explicitly defined which script I was getting or even which prefab was going to be loaded, I couldn't actually change a variable or run some kind of import method.

    "who should say where it goes". The projectile, because it knows what type of projectile it is. Otherwise I need a switch in the manager with 15 different cases. And the projectile can just get the player and target position and then apply transform in awake.

    I'm still really confused by the syntax of GetComponent when you are getting a script. All the Unity official examples have something like:

    Code (CSharp):
    1. OtherScript otherScript = GetComponent<OtherScript>;
    So the first OtherScript is the class defined by the script you are trying to access, and otherScript is a variable within the current script to reference it? And then the OtherScript within <> is the name of the script as well? I've read that it's better to access a component by type if possible for performance reasons, but this example is referencing a script by name within the type field? Is there a way to GetComponent a script by type? Sorry to put in a follow up question like this, but I've spent probably around 2 hours in total trying to find an answer to this, GetComponent examples usually aren't talking about scripts, and the only time they are they seem to be the otherscript otherscript otherscript example.
     
  5. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    The only GetComponent I ever use is :
    Code (csharp):
    1. OtherScript otherScript = GetComponent<OtherScript>();
    Almost exactly as you wrote it, but you missed the parentheses. :)
    It's not actually getting it by name, but by type. Type and name just happen to be the same in Unity lots/most/almost always :)

    is your first question resolved, yeah? :)
     
    gnhaines likes this.
  6. gnhaines

    gnhaines

    Joined:
    Dec 4, 2017
    Posts:
    13
    Yeah, thanks for doing the simulation. If I had kept the previous solution and applied the transform in Awake it wouldn't have worked, so it was good to learn that too.
     
  7. gnhaines

    gnhaines

    Joined:
    Dec 4, 2017
    Posts:
    13
    Hey, thanks Peter. The position and rotation would be different depending on the projectile. It's actually a spell based game, one of the spells causes the projectile to spawn at the target, another throws a projectile towards the target, another spawns a hammer out to the side of the player that then swings fowards. I can't efficiently decide the transform using the script that spawns it.

    I will be setting the transform in Awake, not translating, so it should be ok. But thanks for the heads up.

    I definitely should look at object pools, that sounds important for my project, although maybe it doesn't qualify as "frequently instantiating". In any case it's on my reading list, Thanks!

    I had a look at the Execution Order documentation, and I came to the conclusion that Start would not run at all on a newly instantiated object, and Awake might run the instant I instantiated the object, before my the transform I wanted to apply had the arguments it needed to calculate it properly. So I had two potentially problematic methods so I came here :).
     
  8. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Glad it's resolved for you. Enjoy your game :)
     
  9. guneyozsan

    guneyozsan

    Joined:
    Feb 1, 2012
    Posts:
    99
    If you have a reference can you lead me to the relevant bug? Because on 2018.4.12f1 setting
    someButton.interactable = false
    on Awake right after Instantiate gets effective on second frame, causing a blink unless I save defaults right on the prefabs. I would like to see if it is a related issue.