Search Unity

  1. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice

Help Wanted a simple question about instantiation from a beginner.

Discussion in 'Scripting' started by ostrasull, Sep 21, 2020.

  1. ostrasull

    ostrasull

    Joined:
    Apr 6, 2020
    Posts:
    2
    hello and thanks for reading.
    When i'm making an enemy spawner/generator I usually instantiate my enemy object, and then, call a custom method that will set the values nessesary for the enemy script to run ;it would read something like this :
    Code (CSharp):
    1. GameObject currentEnemy =  instantiate(enemyPrefab);
    2. currentEnemyAI = currentEnemy.getComponent<enemyAI>();
    3. currentEnemyAI.setValues(enemyDefense, enemySpeed, enemyHealth);
    this is just an example code
    When I need my instantiated enemy to not iterate Update() untill those values are set I use a "areValuesSet"/"canStart" bool that is checked in every Update() method iteration but i hate this.
    Is there any better/cleaner/built in unity/faster way to do that ?
     
  2. WarmedxMints

    WarmedxMints

    Joined:
    Feb 6, 2017
    Posts:
    1,034
    When you instantiate an object, you can think of it as queuing it for creation. It isn't going to be created and have its update method called until the next frame. So you can create it, set the values and they will all be set for the first update call in the next frame, there is no need for a bool in your example.

    Falining that if you disable a script on an object, then its update method will not be called, so you could just disable it until you want it to do something.
     
  3. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    1,627
    I sure hope it is, since Instantiate() is written with a capital I, and GetComponent() with a capital G :D

    Unless i'm missing your point, there is no reason to do this at all. Code is execute sequentially and Unity runs on one thread. When you write Instantiate and a couple lines below that you setValues, then Update() of the instantiated object will not have been called yet. Update will only be called in the next frame. It's worth taking a look at the lifecycle of scripts in Unity, as that should clear some of these confusions: https://docs.unity3d.com/Manual/ExecutionOrder.html
     
  4. cpuRunningHot

    cpuRunningHot

    Joined:
    May 5, 2018
    Posts:
    68
    A cleaner way is to make sure that the enemyAI component is disabled by default. This can be done in the prefab via the inspector OR it can immediately set to disabled after instantiating. Update will not be called until the prefab has been enabled.

    1. GameObject currentEnemy = instantiate(enemyPrefab);
    2. currentEnemyAI = currentEnemy.getComponent<enemyAI>();
    3. >>> currentEnemyAI.enabled = false; <<<
    4. currentEnemyAI.setValues(enemyDefense, enemySpeed, enemyHealth);
    When the enemy has been fully initialized, set enabled to true and Bob's your uncle.

    By as Yoreki mentioned, if this is the only place where initialization takes place, that won't be necessary since Update() will not be called before setValues(). But if the initialization also depends on a more complicated scheme in which Update() may be called before it is fully setup, then the above is a way of making sure enemyAI.Update() does not get called.

    Hope this helps
     
  5. ostrasull

    ostrasull

    Joined:
    Apr 6, 2020
    Posts:
    2
    thank all of you for your replies.
    I get that it's useless in my example but it's not always so thank you for the enabled trick.
     
    cpuRunningHot likes this.
  6. cpuRunningHot

    cpuRunningHot

    Joined:
    May 5, 2018
    Posts:
    68
    There is another pattern to consider as well... you could declare a custom onUpdate delegate, and call it in update. Only add to the delegate when the setup is complete.

    Action onUpdate;

    void Initialize()
    {
    // do stuff
    onUpdate += ()=> { StuffToDoOnUpdate() };
    }


    void Update()
    {
    onUpdate?.Invoke();
    }
     
unityunity