I am making a game that as of right now has alot of get component calls, and im kinda worried since from what i understand those can be bad for performance and i plan on releasing my game to mobile.
The game is a top down twin stick shooter. The bullets are each instantiated then their component is got to modify certain attributes of the bullets depending on the circumstances (damage, speed, lifetime etc.) the if the bullet hits a monster it will try to get its component and do damage to it. Currently the starting weapon is an AR that spawns a lot of bullet projectiles. Their isnât any real way I can think of to cache this, also monsters are infinitely spawning (with a 40 monster limit) every half a second so I cant cache that either.
Also another question, Iâve been connecting everything through dragging components in the inspector whenever possible (so navmeshes, rigid bodies etc) instead of doing it in a start/awake method, is that bad? Iâve seen a lot of tutorials do it in start/awake so Iâm curious.
You can instantiate all the bullets off screen at the start of the game and then simply move them into position when needed. When a bullet collides with something, instead of destroying it, you hide it or move it off screen.
And because all the bullets have been instantiated at the start of the game you can cache their components.
BTW - this technique is called âObject Poolingâ.
Keep in mind that using GetComponent() and its kin (in Children, in Parent, plural, etc) to try and tease out Components at runtime is definitely deep into super-duper-uber-crazy-Ninja advanced stuff.
This sort of coding is to be avoided at all costs unless you know exactly what you are doing.
If you run into an issue with any of these calls, start with the documentation to understand why.
There is a clear set of extremely-well-defined conditions required for each of these calls to work, as well as definitions of what will and will not be returned.
In the case of collections of Components, the order will NEVER be guaranteed, even if you happen to notice it is always in a particular order on your machine.
It is ALWAYS better to go The Unity Way⢠and make dedicated public fields and drag in the references you want.
In general, DO NOT use Find-like or GetComponent/AddComponent-like methods unless there truly is no other way, eg, dynamic runtime discovery of arbitrary objects. These mechanisms are for extremely-advanced use ONLY. If something is built into your scene or prefab, make a script and drag the reference(s) in. That will let you experience the highest rate of The Unity Way⢠success of accessing things in your game.
Profile your game on your target hardware. You wonât know until you test.
Nonetheless like most things, GetComponent is fine in moderation. Though, helps to know you can reference prefabs by a component on their root game object, and get an instance of said component as the return from Instantiate<T>. This can save a lot of GetComponent calls.
Both ways are fine. Often I hook these things up in the inspector, but in Awake also check if theyâre null, try and find the component, and post a warning in the console in either case.
Sorry, but youâre losing me with this one Kurt. Since when is GetComponent<T>extremely advanced territory??? Itâs a fundamental part of Unity and something every beginner should learn to use!
I feel like youâre hamstringing users with this attitude, sorry.
I think beginners should spend a little time with statically-defined games, games that start already with all the parts present in scene and dragged in, just in order to get used to what is in the scene, what the code interoperates with, before they start doing crazy procgen and late-instantiation tricks.
I just see far too many posts here are about mis-using GetComponent().
In rough order of the ways I have seen it misused again and again and again:
using it when itâs not necessary:
declaring a public MyClass foo; and thenâŚ
doing a foo = GetComponent<MyClass>(); in Start()
looking on the wrong GameObject (usually by issuing a plain GetComponent() call and not specifying another GameObject on which to look)
mistaking GetComponent() for GetComponents() (and the reverse of course)
using GetComponent() to look for things other than Components (Materials, etc.)
And thatâs not even getting into the InParent and InChildren varieties! those cause even more issues.
In general when you issue a GetComponent() call, you and I know where it will look, what it will look for, etc., such that when it fails we just instantly go digging and find out why it failed.
My main point about âstay away from itâ is that new users just donât have the domain knowledge of where to look for all the ways GetComponent() can fail.
Iâm a little guilty of posting code with an unnecessary GetComponent, GameObject.Find or FindObjectOfType. This is partly because itâs difficult to know if a new user knows how to setup a scene properly. Sometimes the user canât speak English and so itâs impossible to explain how to setup external references.
I sometimes feel Unity would be better off without the editor and everything was setup programmatically. Although I know itâs the editor that brings all the boys to the yard.
Great!. And just to clarify, the biggest benefit you gain from doing this is not having to use Instantiate. The Instantiate function is supposed to be quite heavy. The caching of components is just a bonus.
Completely disagree. Caching and pooling is a complete waste of time. and it WRECKS your clean project.
Donât believe me, try it for yourself: do honest side-by-side performance tests with real world amounts of objects. Until you reach the level of a million-bullet bullet hell game, caching and pooling just screws up your codebase and makes it far harder to work with.
Hereâs my standard blurbs:
The costs and issues associated with object pooling / pools:
I mean I agree a lot of people use it wrong, but we should be telling them how to use it right, as opposed to not using it at all.
Literally one of the first tutorials on the Unity Learn programmer course I did had me rigidbody = GetComponent<Rigidbody>(); alongside explain why we were doing this, and that taught me a lot about how Unity works.
Yeah, I will give you that is gold knowledge to have⌠but!
I donât know your background but it sounds like you came in with previous experience, or at least an extremely strong software engineering mindset, so picking stuff up like that is natural for you.
I just think this capability is in the tiny minority on the board, which is why people are here looking to learn.
I say keep it simple. But I do appreciate how powerful such Get- and Find- things can be to streamline. Just not on day zero.
The basic uses of GetComponent should be fine. These are things like changing speed starting with r=GetComponent<Rigidbody>(), or when you hit a GameObject, using ms=thingWeHit.GetComponent<MonsterScript>() to see which monster it was. Likewise when you instantiate a GameObject and want to play with a script on it. Technically, GetComponent searches the list, but most things donât have many components, so looking through them isnât a big deal.
Even so, some people like to pre-save these, like setting myRB=GetComponent<RigidBody>(); at the start. For lists of objects, a trick is you donât have to only link to GameObjects. If you have a list of monsters, the list can be links to their scripts: MonsterScript[ ] M;. Then you donât need to use GetComponent to get those scripts. The same trick woks for instantiate: you can have public MonsterScript monsterPrefab; and use that in MonsterScript newMonster = Instantiate(monsterPrefab);. Unity makes the full object, but knows it should return a link to that component instead of the entire GameObject.
Iâm gonna go with Spiney on this one and say just donât worry about it until itâs an issue. People say itâs âslowâ but that actually means it takes a few dozen microseconds. Always worry about this stuff when you need to scale. Never worry about it for one-off situations. If the player is doing it once per frame then donât worry. If a million bullets are doing it multiple times a frame then⌠also donât worry. Instead CREATE A TEST and actually confirm that any caching will help before you fully commit.
It might seem in this day and age of gigbytes that a few extra megabytes of RAM wonât matter but they can cause all kinds of issues with the GC and CPU cache so try to stay frugal. This is why confirmation through profiling is the one and only way you can truly ensure you are actually getting better performance. And if youâre hitting your target framerate already, that time could be better spent adding new features instead. If youâre just starting out this stuff is really just going to bog you down in a mire of micro optimizations that probably wonât even matter.
For the record in a bullethell-esque game I made a while back I used a combination of GetComponent when I really had to and caching on occasion along with a good old fashioned object pooling and things turned out fine. It was a matter of profiling to ensure the pools and caching helped when I did use them.
Within the context of DOTS (which includes ECS) he was right to throw it under the bus, but with that same context you could also throw every one of these little speed ups weâve used over the years to increase the performance on the MonoBehaviour-side.
For example pooling in DOTS has a high chance of losing you performance not gaining it.