Accessing specific Components on GameObjects

Hello,
I’m in the process of setting up a spell system for an RPG game but seem to have hit a problem when trying to access the spells. I have a Spell base class (Monobehavior) and let’s say I have three spells: Fireball, Frostbolt, and Lightningbolt. Each of these three spells have their own script that override functions of the Spell base class.

In the Unity editor, I have a Game Object called PlayerSpells (child to my Player game object). I add each of these spells as components to the PlayerSpells GameObject. Whenever I wish to cast a spell (i.e. Fireball), I’d like to access the component through a button with a script that calls the following on press:

public string spellReference;
public GameObject skillManager
public void OnPress()
{
skillManager.GetComponent(spellReference).GetComponent<Skill>().OnCallSkill();
}

Where the component name, “Fireball”, “Frostbolt” and “Lightningbolt” would each be entered in the Button Game Object under spellReference. The issue I am having is that whenever GetComponent() is called, the first Spell component is always returned (i.e. all 3 return Fireball), even if GetComponent(spellReference) returns the correct spells (Fireball, Frost bolt, and Lightning Bolt). What this leads to is Fireball.OnCallSkill(); always being called. Is there a way to call the Spell function OnCallSkill() without using GetComponent? Because it seems like as soon as I do, it just defaults to the first Spell on the PlayerSpells Game Object.

I don’t understand what you’re trying to achieve by calling GetComponet twice. Components do not have their own sub-components; the second GetComponent is effectively throwing away the first result and going back to the GameObject that all of these components are attached to.

That is a hairy line of code. I recommend you break it apart:

How to break down hairy lines of code:

http://plbm.com/?p=248

Also, I recommend liberally sprinkling Debug.Log() statements through your code to display information in realtime.

Print the string you’re passing into GetComponent()… is it what oyu think?

Doing this should help you answer these types of questions:

  • is this code even running? which parts are running? how often does it run?
  • what are the values of the variables involved? Are they initialized?

Knowing this information will help you reason about the behavior you are seeing.

So when I call just:

skillManager.GetComponent(spellReference);

I cannot access any of the functions from the component it is referencing to or from the base class Spell. For instance, I cannot call

skillManager.GetComponent(spellReference).OnCallSkill();

This is because you are using the string version of GetComponent, which can only return a Component.

You need to cast it to what you think it is before using it.

Personally I recommend using the templated version:

var fireballSpell = foo.GetComponent<Fireball>();

but I accept that you may have structured your program to work with strings. I’m just not sure it will get you the kind of flexibility you currently anticipate.

Another approach is to use interfaces, which are supported in a very typesafe and first class citizen way in Unity. You can even GetComponent<>() with an interface, but in the case where you have multiple scripts expressing the same interface, it will still be undefined which one you get.

2 Likes

If you’ve never done dynamic casts before, the typical way to phrase that would be something like

Spell mySpell = skillManager.GetComponent(spellName) as Spell;

Note: this will return null if the component you got isn’t a subtype of Spell

2 Likes

Thanks! This is exactly what I was trying to achieve. It is working as intended.

1 Like