Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice
  3. Dismiss Notice

Is Instantiate bad for performance? Unity says it's fast, forums say it's slow...

Discussion in 'Scripting' started by tinman, May 17, 2013.

  1. tinman

    tinman

    Joined:
    Jan 8, 2011
    Posts:
    229
    Hey guys,

    I am trying to optimize my game and I read on the forums that Instantiate can be bad for performance. But I never really had a problem using it because Unity themselves said here:
    http://docs.unity3d.com/Documentation/ScriptReference/index.Instantiate.html
    that:
    "Instantiate is incredibly fast and very versatile. It is essential to using Unity to its fullest. "

    So is it bad for performance or isn't it? Unity also doesn't include it in the section for script or graphical performance here:
    http://docs.unity3d.com/Documentation/ScriptReference/index.Performance_Optimization.html
    or here:
    http://docs.unity3d.com/Documentation/Manual/OptimizingGraphicsPerformance.html

    However on the forums (here) people tend to say it is bad for performance. So what's the deal?
    In my case my target is webPlayer and I use Instantiate for muzzleflashes and bullet marks.

    Thanks!
     
  2. SteveJ

    SteveJ

    Joined:
    Mar 26, 2010
    Posts:
    3,085
    Do you have any examples of people saying it's bad for performance?
     
  3. tinman

    tinman

    Joined:
    Jan 8, 2011
    Posts:
    229
  4. Univerb-Gaming

    Univerb-Gaming

    Joined:
    Jun 28, 2012
    Posts:
    255
    It's all about context. If you're instantiating objects that are not common, the cost is fairly low overall. If you're instantiating a bullet firing rapidly as in one of the example links - it's going to add up frame for frame memory and performance wise.

    Bottom line, use when you need it and be smart for when it's not really required, example, instantiate object, add to pool and re-use as and when required

    Of course if the game is really small or simple enough, keep gameobjects hidden until you need them, that way you already have them in the scene.
     
    dangakun and Ryiah like this.
  5. tinman

    tinman

    Joined:
    Jan 8, 2011
    Posts:
    229
    Thanks Univerb, by "objects that are not common" do you mean things which are not instantiated often? In this case, what about something like bullet marks in a multiplayer environment? there could be tens or eveb hundreds of them at any given time, is it better to pool such a huge number of prefabs?
    EDIT: Sorry I misread your post, I see what you mean now :)
    But would you recommend pooling hundreds of prefabs? such as bullet marks?
     
    Last edited: May 17, 2013
  6. hellcaller

    hellcaller

    Joined:
    May 19, 2010
    Posts:
    381
    check it out :

    world is generated/destroyed on the go with instantiate/destroy functions, no lags.
     
    zchek, Shin4ko, ozerufuk3322 and 2 others like this.
  7. OceanBlue

    OceanBlue

    Joined:
    May 2, 2013
    Posts:
    251
    I'm a firm believer in using a pooling system for objects that are instantiated and destroyed frequently.

    In my initial set up, I had instantiate and destroy, then switched to pooling, and noticed substantial difference in performance, particularly on the iPhone 4/Touch 4. I have up to max 160 objects on screen at any one time plus bullets - so I do have a lot.

    For your purposes, with bullet holes where you could potentially have 100s, I would definitely be pooling them.
     
    image28 and krougeau like this.
  8. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Instantiate is awful mostly when used with destroy. It's terrible for mobile. You won't however notice anything if you're making empty-world(tm) like the above misguided video.

    You use instantiate to create copies to reuse from a pool. Don't do it during gameplay for mobiles. If you do it once every few seconds you probably will not ever notice a problem. But if you do it often, ie once a frame, enemies spawning etc - you will notice a problem.

    Basically, just use instantiate. If your game is slow, fix it by pooling.
     
  9. tinman

    tinman

    Joined:
    Jan 8, 2011
    Posts:
    229
    Thanks OceanBlue and Hippocoder!
     
  10. OceanBlue

    OceanBlue

    Joined:
    May 2, 2013
    Posts:
    251

    Take a look at plugin called poolmanager 2.0.... I think it's on the store... will make life easy for you.
     
    khaled24 likes this.
  11. tinman

    tinman

    Joined:
    Jan 8, 2011
    Posts:
    229
    Thanks! Looks like a good tool, although in the meantime I created my own little system, just using and array of GameObjects which are used and recycled, using SetActve instead of Instantiate/Destroy.

    Saw a small performance improvement :)
     
  12. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Don't forget to use profiler - that'll tell you where the slowdown actually is. Mobile has a free version of it built in.
     
    krougeau and JoeStrout like this.
  13. SlyRipper

    SlyRipper

    Joined:
    Jun 19, 2012
    Posts:
    251
    Well, I still think it depends on the usage and the platform..

    I've recently used Instantiate for displaying some kinda ghost-version of the building/unit that get's placed and destroyed it after I had no use for it. No performance issues and it's like before when it's destroyed. Still as a lot of units were instantiated for testing purposes, no performance issues. But this was only tested on PC Version.

    So I think you have to look at different variables, like:
    - Which Platform? (PC works best ofc)
    - How many units/Objects?
    - How many of them are animated?
    - When do you instantiate them? Just one at a time but pretty often, many at once?
    - There might be more reasons :D

    So if you notice performance issues, I would change the system or reduce the instantiate amount, like only instantiate 1 bullet or 10 and placing them beneath the map so it's not visible. If you need that bullet just move it to the place it's gonna needed. This will work for most stuff. (But also think about long loading times if you instantiate everything at beginning just to make use of them later on when u have to move something..)

    Might be wrong on some parts, just my oppinion my 2 cents :)
     
  14. tinman

    tinman

    Joined:
    Jan 8, 2011
    Posts:
    229
    Thanks Hippocoder, will do that. I was actually just checking framerates. I assume Instantiate() will be under 'scripts'? Am just wondering because there's a lot running in the background with it (as opposed to 'just' a calculation).
     
  15. tinman

    tinman

    Joined:
    Jan 8, 2011
    Posts:
    229
    Thanks SlyRipper! :) I wil take that into account :D
     
  16. Ippokratis

    Ippokratis

    Joined:
    Oct 13, 2008
    Posts:
    1,521
    Hi,
    The problem with instantiate is that it takes CPU cycles, so, if you use a pool instead, you will save those. This practice cuts your app loading time and prevents performance spikes that can occur when objects get instantiated.
    Destroy creates another problem. The memory occupied by the objects you destroy must be cleaned by the garbage collector. It can happen anytime and it will create a performance spike.
    So, using instantiate and destroy, is not a good idea at 99% of the cases. I do not know where they are useful actually, but they must be useful somewhere since they exist. Try to use pooling instead.
     
  17. jc_lvngstn

    jc_lvngstn

    Joined:
    Jul 19, 2006
    Posts:
    1,508
    Great point. The only situation I can think of would be...if memory is scarce, and cpu/framerate is not.
     
  18. tinman

    tinman

    Joined:
    Jan 8, 2011
    Posts:
    229
    Thanks Ippokratis and jc_lvngstn!
     
  19. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,574
    The pooling plugins use Instantiate to create the items in the pools in fact when the scene is loaded. I know, because I use that code in my Master Audio plugin. Also saw similar code in Pool Manager.

    I agree, always pool if you can. It prevents a lot of sudden jittery garbage collection moments on mobile devices. Absolutely essential!
     
  20. Rafes

    Rafes

    Joined:
    Jun 2, 2011
    Posts:
    764
    We created PoolManager because we had trouble with both sides of the equation; instantiate and destroy.

    Instantiate shows up on the profiler and seems to do so more the first time. We assume this is because Unity has to load dependencies in to memory the first time. This is why we also added preloading; to instantiate as many instances as possible when a game/level/prefab loads so we can design pool loading so it doesn't happen during game-play.

    Avoiding destroy was the bigger issue for us though. The garbage collection was causing stutters after awhile. It took us a while to track it down because it seemed pretty random and required a lot of variables to come together to make it happen. We couldn't even reproduce it reliably. Once we started pooling it went away. We even added a mechanism for destroying pool items over time just in case there is a big event that overfills the pools so they could be reduced back to normal levels automatically. This reduced the destroy calls to rare cases where memory is critical (seems quite rare though).
     
  21. tapticc

    tapticc

    Joined:
    Jan 16, 2014
    Posts:
    379
    From most pool managers I have seen in the store, they allow up to a fixed number of pre-loaded objects. If you are making a block building game for example where the number of blocks could be huge, and unknown number of each block, I'm thinking using Instantiate is OK in this scenario. Have I missed the point of pooling i.e. can it be used for an "infinite" number of prefabs being placed in a scene, or is it limited to the number of predetermined items and when you need to expand more than predefined number, it would need to increase the pool size (with a more noticeable delay as many new items are instantiated)?
     
  22. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,598
    NOTE - you revived an old thread...



    The pool manager I wrote for our system allows for runtime resizing.

    Basically I have a start size, and a resize count. When the pool manager loads it creates all the start counts. If we use them all up, and the resize count is greater than 0, I create as many as the resize count and hand 1 off. If it's 0, I just create 1 and hand it off... acting just like Instantiate, and the object won't be pooled back in on 'Kill'. This pool resizing can happen over multiple frames to avoid frame drops.

    Then if the pool remains very large, but unused for the most part, for a long period of time. I'll resize it back down destroying pool unused entries.

    This allows the pool to grow very large when needed, with out needing to know initially how many will be needed.

    Of course, having a good idea of how many will be needed in your scene makes it smoother.
     
    Ryiah likes this.
  23. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,574
    Sometimes a single Instantiate will cause frame rate stutter. Moreso on lower powered platforms (mobile), but it can definitely happen on powerful PC's too when you have lots of scripts and things on the prefabs. So I avoid it at all costs.

    We Instantiate nothing, ever. Everything is pooled. In a game like you describe, I'd calculate the maximum number of each block and set up the spawn pool accordingly. For example, we have a puzzle game coming out soon that has a 20 x 30 square grid, so the items that aren't limited by the level generator indeed have 600 copies in the pool (20 x 30). That way there's no slowdown ever from Instantiate and Destroy. It's probably a little overkill but it doesn't matter. The scene starts up after a couple seconds during which music plays and a game tip is shown to read. Thankfully, there's only a handful of items that need this many copies.
     
  24. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    I just want to add: if you're to the point in your game development where you should be worrying about this level of optimization, congratulations! Most people never make it that far.

    On the other hand, if your game is not already mostly finished, and you're now putting on final touches and profiling to find out where your performance problems are, then you really should quit worrying about it. Do whatever makes your code simple, clear, and correct, and gets you to that nearly-finished stage as quickly as possible.

    Premature optimization may not be the root of all evil, as some famous (and very smart) developers have claimed... but it certainly is the root of a lot of evil. :)
     
  25. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,598
    Honestly, I've seen the stutter from Instantiate very early on in development. I once made an infinite runner with a friend for a 24 hour game jam. It was our first time using Unity, and we used it as a chance to familiarize ourself with it.

    Only 8 hours into dev I already had stutter.

    Furthermore, swapping out Instantiate for a spawnpool can be very cumbersome.

    My spawnpool is probably one of the first things I built for Unity.

    Some other games I've worked on though, I've never come across any stutter, just because we don't spawn things all that often... or what is spawned just isn't too complicated.
     
    khaled24 likes this.
  26. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Yeah, I can totally see how in an infinite runner, with things coming in and departing very rapidly, the benefit of a spawn pool might be noticeable.

    But in many other games, it isn't. And it's clear from the OP that he's not actually seeing a problem... he's wondering if there will be a problem.

    I still stand by the claim that you should first observe a problem, before attempting to solve it. The right way to be proactive in programming is to separate concerns and hide implementation details, so that later on, when you have clearly identified a real problem, it's easy to change your code to fix it. But fixing it before you see it — not usually a good idea.

    Of course, sometimes there are design patterns which are not only more efficient, but shorter, clearer, and easier to maintain too. Obviously you should pick those right away!
     
  27. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,574
    Generally I'd agree with that. Not in this case for me though. For certain things (such as pooling), there really is no discernible disadvantage to starting a project the right way (using pooling). Changing it in later means changing a bunch of code and some amount of smoke testing. If you end up not "really needing it", you still haven't lost anything. If your game design later changes and it would help to use pooling, well - you're already using it.

    To put it simply, there's not really any additional work to use pooling from the get go, so no point using slower and more expensive alternatives (Instantiate / Destroy).
     
  28. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,598
    I'd like to point out OP is 2 years ago.

    The context of the conversation is currently with tapticc, who is asking about resizing the pool at runtime.

    @tapticc - this is why necroposting is considered taboo, it causes for these kinds of confusions.
     
    Last edited: May 24, 2015
  29. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    It's still a largely relevant subject, so we're not locking it. But it's worth pointing out Unity 5 apparently has better instantiate/destroy performance. Still should pool those bullets and regularly spawned things though ;)

    In the interests of adding value, has anyone done any testing regarding what is instantiated? for example object with scripts, without. And where from (resources/cached object) ?
     
  30. tapticc

    tapticc

    Joined:
    Jan 16, 2014
    Posts:
    379
    Apologies for being taboo, normally when I'm being taboo I do it privately ;)

    I think the best approach is going to be "try instantiate and see if it's slow, if it is try pooling with the option to instantiate when the pool is full but try to make the pool big enough in the first place"
     
  31. adventurefan

    adventurefan

    Joined:
    Jan 17, 2014
    Posts:
    232
    Bumping an old topic to ask did anyone ever test if destroy got any better with unity 5?

    Is pooling still pretty much a must for anything you're using a lot of?
     
  32. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Yes, pooling is still fastest. It's only worth pooling if you're doing things often or that the things you are copying are complex. It's a deep copy, which can add up to being very expensive depending on complexity.

    It's not just for a lot of either. Some complex prefabs may well take enough time to cause stutters. Testing is best.
     
    adventurefan likes this.
  33. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,355
    I haven't really heard anything about a big performance hike for destroying objects in 5.

    The same advice as always goes, though; if you're not seeing in the profiler that this specific thing is causing a slowdown, don't try to optimize it. If it is, try a different solution, and see if it works.
     
    Kiwasi and adventurefan like this.
  34. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    5.4 improves destroy perf.
     
  35. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,355
    Is there any release notes or blog post saying what they did differently? Just curious.
     
  36. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Yeah somewhere buried in 5.4 release notes :D
     
    Baste likes this.
  37. Rafes

    Rafes

    Joined:
    Jun 2, 2011
    Posts:
    764
    I'm unaware of any change. People are still using PoolManager at the same rate as before. The issue was always more about garbage collection than direct performance, though both can show up depending on the game. Plus, the round trip of reuse has to be taken in to account as well.
     
    Kiwasi likes this.
  38. jwinn

    jwinn

    Joined:
    Sep 1, 2012
    Posts:
    89
    There is "Core: Optimizations made to SetParent() and Destroy(), with potentially dramatic performance increases. Please let us know how much it helps on your projects." underneath "THE FOLLOWING ARE CHANGES AND FIXES TO 5.4.0 FEATURES AND REGRESSIONS". I'm not sure if this in reference to the SetParent problems in this build or a general improvement to previous versions?

    Some interesting comments here about best performance and what to avoid: http://forum.unity3d.com/threads/extremely-poor-transform-setparent-performance.406606/#post-2673733
    "Unity now allocates a big block of memory that is as big as the entire hierarchy, containing transform rotation / scale / position / parent indices etc...."
     
  39. superfryme

    superfryme

    Joined:
    Jun 9, 2017
    Posts:
    26
    I found instantiate to take up a lot of the pc too. It caused a lot of lag. Luckily i learnt about coroutines. Now there is no lag. I suggest everyone learns how to use coroutines for any piece of code that will cause glitches in your update code. If you have a player that glitches when you instantiate a lot of objects its because unity is doing all your code at once where coroutines can split it up between multiple frames doing one section of your code then yield return null to do an update frame then back to your coroutine for the next instantiate
     
  40. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    coroutines aren't the reason it is not lagging. You should time slice and look into jobs for future. What is happening here is that the coroutine is merely running your code less - something you can do anyway?

    Unity's messaging for coroutines is annoyingly bad. They have a number of tutorials suggesting you should use it widespread but their documentation indicates you should not.

    https://docs.unity3d.com/Manual/BestPracticeUnderstandingPerformanceInUnity3.html
     
    JoeStrout likes this.
  41. superfryme

    superfryme

    Joined:
    Jun 9, 2017
    Posts:
    26
    without the coroutines there is lag. i guess it depends what you are doing but as for me I am Generating Galaxies with 50000 stars all with rigid bodies. Then searching through a dictionary or 10000+ objects to find the closest and parent to it. I suppose I could just wait and think unity is freezing for all that or i could use the ui to show each star is placed and move around in a ship with 0 lag while they are still generating using coroutines. I will however look into this Time Slicing you speak of. What is the messaging for coroutines? I have no idea why you mentioned it really...
     
  42. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    The point is, anything a coroutine is doing, you could do just as well without coroutines, by just dividing your work up among multiple Update calls. Coroutines don't make anything faster; they're just a convenience for splitting work up among multiple frames.
     
  43. Ippokratis

    Ippokratis

    Joined:
    Oct 13, 2008
    Posts:
    1,521
    @superfryme, thanks for sharing your findings.
    I believe that you should reconsider how you approach the Galaxy Generation. Think about those tiny dispersed pieces of memory you generate using 50k Instantiate(), all over the RAM. Think about the stress Physics Engine has to suffer when it is dealing with +50k new Rigidbodies.
    Messaging refers to the communication between the CSharp layer and the C++ core in Unity.
     
  44. superfryme

    superfryme

    Joined:
    Jun 9, 2017
    Posts:
    26
    the only thing I need in my update code is the player movement. Otherwise I am just asking for performance hits when I try to move. The point I am trying to make is Coroutines can be used to make player movement smoother especially when loading other objects into the scene. So in essence yes they do make things faster in particular the player movement. Ever notice in games when you walk to the ede the game pauses to load the next area and the player glitches for a second. Well gamers hate that and this fixes it for me. I hope it will for someone else too.
     
  45. boxhallowed

    boxhallowed

    Joined:
    Mar 31, 2015
    Posts:
    513
    I've noticed when using instantiate allot, I have to manually run a garbage collection at some point. Is this normal?
     
  46. superfryme

    superfryme

    Joined:
    Jun 9, 2017
    Posts:
    26
    if you parent your objects based on distance and hide them if too far from the player the ram for 50k objects is only 1 gig lol
     
  47. superfryme

    superfryme

    Joined:
    Jun 9, 2017
    Posts:
    26
    What is this Garbage Collection? Is this just bad code filling ram because i have experienced that in the beginning when i tried to create 50k objects without parenting them to another object. Unity does not like when you fill hierarchy with 50k objects but its fine with parenting them say 100 per object ect.
     
  48. boxhallowed

    boxhallowed

    Joined:
    Mar 31, 2015
    Posts:
    513
    If i just use instantiate/destroy allot, it doesn't need to even be a thousand times, I need to use some sort of garbage collection (usually the built in .net one) or things freeze solid.
     
  49. superfryme

    superfryme

    Joined:
    Jun 9, 2017
    Posts:
    26
    I see. I dont destroy objects in my scene really. they need to be there at all times but when im not looking at them or at a certain distance i can just hide them. objects hidden have no impact on performance that i can see. have them all shown at once and yeah huge performance hit. thats why everything beyond 150,000 is automatically hidden when you look at or away from it in my script. I have used OnBecameVisible to accomplish this.
     
  50. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Sounds like you should look into Unity closer, it has solutions for everything you're mentioning and can probably reach AAA level performance these days (particularly with SRP/Instancing and ECS/Jobs).

    Simply getting into a car does not make you a race driver :D