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.
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.