How does no reference for GetComponents() work?

is that different then getting them on a game object? we don’t have a reference for what to get components from…

I might need a little context for this question… do you mean the difference between GetComponent() and enemy.GetComponent(); (difference is the first one is assumed to be this.GetComponent() by the compiler.

in this specific lecture we don’t have a reference in the following code…

private float GetAdditiveModifiers(Stat stat)
        {
            float totalOfAllModifiers = 0;
            foreach (IModifierProvider provider in GetComponents<IModifierProvider>())
            {
                foreach (float modifier in provider.GetAdditiveModifiers(stat))
                {
                    totalOfAllModifiers += modifier;
                }
            }
            return totalOfAllModifiers;
        }

how are we able to Getcomponents plural in that code without a reference

Ah, I think I see what you mean. It’s exactly what I was saying before…
GetComponents() without a reference will look for all components with an IModifierProvider interface on the same GameObject that the BaseStats is connected to.
It’s the same as saying this.GetComponents<IModifierProvider>() which is something we actually use to have to do in much older versions of Unity. (In fact, if you take a course from Penny DeByle, she still uses it because it lends more clarity to the reader of the code).

In short GetComponents<IModifierProvider>() == this.GetComponents<IModifierProvider>()

1 Like

aaaaahhhhhh ok got it! thanks!

I think I might do that too cuz she’s right… that would have explained it to me in the code and I wouldn’t have even had to ask

I think after a while you’ll get used to it. As an example, did this ever occur to you to be a problem when in an Awake statement we have:

void Awake
{
     health = GetComponent<Health>();
     fighter = GetComponent<Fighter>();
}

The same principle is happening here, it’s equivilant to health = this.GetComponent<Health>();

Either way, it’s up to you, there’s no harm in doing it either way. When Unity converts the C# to CLR (the interpreted code that C# becomes), the resulting code will be identical.

well… sometimes I think I get it… but the IModifierProvider isn’t a component of the player… however it’s interface is added onto those that are… so even thinking it through doesn’t quite make sense yet

@Brian_Trotter ok after some more thought… let me see if I understand this…

GetComponents< IModifierProvider >() == // even though IModifierProvider isn’t a component on this object, please find all components on the game object this script is attached to and return any of them that have implemented the IModifierProvider interface.

Ah, but there ARE IModifierComponents attached to your game object. Fighter.cs is a MonoBehavior, an ISaveable, and an IModifierProvider. Everything on that line after public class Fighter: is a characteristic that can be used for Get component

To elaborate a bit on what I just said (last post was from my phone) and couldn’t do any code:

Look at the header for Fighter.cs:

public class Fighter : MonoBehavior, ISaveable, IModifierProvider
{
}

You can find this item in a collection with any of the following GetComponents() functions (actually even more things, but for our purposes, these things are clear:

GetComponents<Fighter>();
This will retrieve every behavior on the GameObject that is a Fighter.

GetComponents<MonoBehavior>();
This will retrieve every script you’ve attached to your GameObject. (i.e. you’d also get PlayerController, Health, Mover, etc)

GetComponents<ISaveable>();
This will retrieve every component on your GameObject that implements the ISaveable interface. At this point in the course, that would be Health, Fighter, Mover, BaseStats, and Experience

GetComponents<IModifierProvider>();
This would retrieve every component on your GameObject that implemented IModifierProvider. At this point in the course, that would be Fighter, but by the next course, this will include other classes as well!

In short, the interface not only says "I do solomly swear to implement these methods in my script’, it also allows you go gather all scripts that implement these methods into a collection. Because of Interfaces, BaseStats doesn’t have to know anything about Fighter. No need to add a using RPG.Combat. It’s not required in the least. It just needs to know that the object it has retrieved is an IModifierProvider, nothing more.

Bear in mind that this also means that BaseStats can ONLY see GetAdditiveModifiers() and GetPercentageModifiers(). It can’t access anything else that is not in the interface. It can’t look at the transform, or tell what the current target is, or anything else. That’s by design, all BaseStats needs to know is “Hey, all you IModifierProviders out there, would you please be so kind as to tally up the AdditiveModifiers for me?”

I hope that was a bit clearer, and not too pedantic (pedantic is my speciality). I’m sorry I misinterpreted your question in the first place.

6 Likes

so you just opened my eyes… I was doing a lot of “OOOOOOOHHHHHHH” reading that… thanks so much. Putting it that way NOW makes sense. That post should be pinned for questions about get component… because until reading that I didn’t realize that anything in class line was a retrievable component. Thanks so much!

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms