Search Unity

Should instantiates be done in Update or Start ?

Discussion in 'Scripting' started by starazure, May 28, 2017.

  1. starazure

    starazure

    Joined:
    May 28, 2017
    Posts:
    31
    I have to load a default of 10 gems per bucket at game startup - I am doing this using update () as well. Then when a user clicks on bucket 2 for example, I need to make its count to zero (remove all gems from it) and update that bucket with 0 gems and add gems to some other buckets. I am able to get the logic of removing gems and adding to other buckets etc right but cannot figure out how to update my game screen using update(). And this logic goes on each time user clicks on a bucket - all its gems gets removed. I want to do this efficiently, only when user clicks on a bucket. Right now my instantiate happens in update() every frame... (oh no !!)
    So - Should I instantiate in Start () ?
    If I instantiate in Start(), how can I add or move the gems in the buckets based on the count of gems that I calculate and pass through the script ?

    Here is a part of my code:
    1. void Update()
    2. {
    3. gemCount_Bucket1 = Bucketscript.gemCount_Bucket1;
    4. gemCount_Bucket2 = Bucketscript.gemCount_Bucket2;
    5. //Trying to do this instantiate update below only once upon mouseclick. Basically recalculate gemcount in each bucket upon mouseclick and update them once each mouseclick. Also, instead of instantiation, is there another way I can use new gemcounts and update these buckets ?
    6. for (int i = 0; i < gemCount_Bucket1; i++)
    7. {
    8. list.Add(Instantiate(prefab, new Vector3((i + xPos_Bucket1) * 2.0F, -14, 0), Quaternion.identity));
    9. }
    10. ........
     
  2. WarmedxMints

    WarmedxMints

    Joined:
    Feb 6, 2017
    Posts:
    1,035
    Update is called every frame so every frame it would be adding to your list, that's not what you want.
     
  3. starazure

    starazure

    Joined:
    May 28, 2017
    Posts:
    31
    Correct - Update is called every frame. But if I dont call update, I am not able to update the game with new count of gems in each of my bucket. I have the new counts calculated but I want to destroy old gems and instantiate new ones based on new count.. Where and how should I do this?
     
  4. Socrates

    Socrates

    Joined:
    Mar 29, 2011
    Posts:
    787
    If it is a user click which is changing the gem counts, I would call the code which instantiates gems from the OnClick() event. (Or whichever way you're noting that the bucket has been clicked.)
     
  5. starazure

    starazure

    Joined:
    May 28, 2017
    Posts:
    31
    This is excellent. I will do this. However, I need to load a default of 10 gems per bucket at game startup - This is before any mouse click. Do I just do that in Start () ?
     
  6. Socrates

    Socrates

    Joined:
    Mar 29, 2011
    Posts:
    787
    Doing it in Start() should work out fine since Start() is only called once for each object. If not every bucket starts with gems in it, you could have a game manager type object that filled the appropriate buckets during Start().

    By the way, if your game involves moving a lot of these gems around, doing all that destroy/instantiate will start running into garbage collection issues. At some point, you may need to look into either moving the gems directly from bucket to bucket or use an object pooling system so that the same gem objects get used over and over. This would be especially important if you are targeting mobile platforms.
     
  7. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Pooling would be a good idea, for sure.
    Just some quick comments that follow what other posters have said, too.

    If you need setup at the beginning, use Start.
    For something that happens during the game, update whatever you need when it's needed (ie: on-demand, rather than looping update to figure it out, for this it isn't needed).
    :)
     
  8. starazure

    starazure

    Joined:
    May 28, 2017
    Posts:
    31
    This is very good advice and makes sense .. I will be moving gems all around and targeting mobile. So do you suggest writing a script attached to all of my 36 gems? I guess no. All gems look alike so unlike chess, all that matters for me is the count in each bucket. I have one script right now and like you said looking for an alternative to not instantiating and destroying to update my buckets
    Sorry - I am new to unity. If you want me to look at some videos or docs I can. If you can simplify something for me for may be 2 buckets, I can catch up from there.
    Thanks for your help
     
  9. starazure

    starazure

    Joined:
    May 28, 2017
    Posts:
    31
    I like this advise too. So I am writing my own "update" function instead of the update that runs every frame.. Now just trying to not instantiate and destroy gems each time to match the counts I calculate for each bucket ! Thanks
     
  10. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Here's 1 from Unity: https://unity3d.com/learn/tutorials/topics/scripting/object-pooling

    A quick summary would be: create the objects when you need them (maybe even start the game by having some made (in the scene), at the game's start. Then, when one would have been destroyed, you deactivate it.
    When you need new ones, you check your list for deativated ones, and if there is one available, you move it where you need it, etc.. and re-activate it -- if you didn't find one, you then create a new one and also add it to the pool..
    :)
     
    Socrates likes this.
  11. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Exactly.. I mean you may need to update your buckets when players get gems or .. I don't know your game, but whatever "event" happens. or maybe new ones spawn because they won something - I have no idea.
    But that's a lot less infrequent than every frame, so it makes more sense to do whatever needs doing at those specific times ;)
     
  12. starazure

    starazure

    Joined:
    May 28, 2017
    Posts:
    31
    Thanks again - Object pooling sounds cool. My game is about moving gems around buckets.. the count of gems will always be the same on the board. When a user clicks a bucket, all its gems gets distributed to other buckets based on my game logic which I have figured out. Then the next player clicks a bucket and the same thing - some other buckets gets the gems as their counst get updated. I have 36 gems so controlling them individually will be a nightmare. I know at any point of mouseclicks what each buckets gem count is. Just want to distribute these 36 gems across those buckets based on my generated count.
     
  13. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Ah okay, that makes sense to me now. For sure, doing the distribution (and keeping track of the gems/bucket count) should be done on the mouse click (on the bucket) :)
    Sounds like fun -- enjoy your game ;)
     
  14. starazure

    starazure

    Joined:
    May 28, 2017
    Posts:
    31
    Before you go - At some point I would like to show the gems moving from one bucket to another. Should I just use my own --transform to new position logic based on vector3 --or is there another animation feature that can be used? Thanks !
     
  15. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    I think when they can go anywhere, you want some transform changing script. Lerp, transform adjustment (speed + deltaTime), movetowards.. there are several options. I can't imagine using an animation (clip) would be worth it, for this.
    Maybe that's just me. :) I'm sure moving it from 1 bucket to the other will be pretty easy for you, I wouldn't worry about it :)
     
  16. Socrates

    Socrates

    Joined:
    Mar 29, 2011
    Posts:
    787
    Don't have the gems control themselves. Instead, let your game logic have a list of possible gems and distribute them to the appropriate buckets.

    Note that what I've babbled on about below is not the only way to do this. I've thought of two other ways just while typing it in. It's just a possible way to think about.


    Since you talk about moving the gems around, I am going to assume that each gem is its own object. You'll have 36 cloned prefabs for your 36 gems. Instantiate them in a location off of the screen. Store them in an array of those objects of size 36. (Any gem-specific setup like randomizing color would most likely be handled by a script on the gem. The code would be in Start() and would activate after the instantiation.)

    Each bucket would have a script for handling its gems. It would have an array of ints of whatever maximum size a bucket could possibly hold. These ints would represent the index of a gem in the array of all 36 gems. I would set all values to -1 at first, since that would throw an error if you accidentally try to access that gem so that you can spot holes in your game logic.

    The buckets would have a function for void AddGem(int gem). This would add the gem to the end of the array and increase its gem count.

    There would be a int TakeGem(). This would remove the last gem from the array, set that index's value to -1 since there is no gem there, and then decrease the gem count. I would have that function return the int value so that the game manager knows what gem to move.

    I would use a single game manager style script to handle the buckets and gem movement in order to keep all of my logic in one place. I'd probably call it GemManager. At Start(), the game manager would work its way through the main array of gems calling AddGem() on buckets to distribute the gems. You could also call whatever animation code you want to use at that point, such as if you were having the buckets fall in from the top of the screen.

    When a bucket gets clicked, it would notify this GemManager object through a method call like BucketWasClicked(bucket). The GemManager would then call RemoveGem() on the clicked bucket and AddGem() on the new bucket. Any animation calls would be put into here as well.

    The BucketWasClicked() function would also call whatever code checks for a win or lose state in the game... possibly after giving time for animations to finish.

    I would personally get the code which puts gems into buckets and moves between buckets done and working without any kind of animation first. Just set the transform directly and move it instantly. Then when you're sure you've got it working properly, you can start adding in code to move it between buckets in a more interesting way. (Remember to block player input while the gems are flying around or things could get weird.)

    Also, put your special effects code, like animation or sounds or whatever, into a separate method. This helps with keeping code easier to understand, debug, and change. So, you might have something like:
    Code (csharp):
    1.  
    2. public void MoveGem(Bucket oldBucket, Bucket newBucket)
    3. {
    4.     int _gem = oldBucket.TakeGem();
    5.     newBucket.AddGem(_gem);
    6.     AnimateGem(_gem, oldBucket, newBucket);
    7. }
    8.  
     
  17. starazure

    starazure

    Joined:
    May 28, 2017
    Posts:
    31
    Thank you for taking the time to write this. Really appreciate it. I am sure I will struggle with some parts like animation but for now lots to learn and miles to go before I sleep.