- Home /
Any way to 'GetComponent' as a base class?
Let's say I have a base class like 'animal' and 3 subclasess like 'dog', 'cat', 'bird' Let's say the base has a function 'speak' that all 3 subclasses implement (bark, meow, chirp).
Then these get added to prefabs.
Now, I'd like to have a script be able to access the script component and call 'speak' and whatever the subclass happens to be, it will make the corresponding sound. Follow?
So, can I just call gameObj.GetComponent(Animal).speak() ?? I would think Unity expects the exact class name (subclass), or GetComponent will fail.
Answer by Eagle32 · Aug 19, 2010 at 11:21 PM
In short I believe it (gameObj.GetComponent(Animal).speak()
) should work, but it may not work with the non-typed versions of GetComponent like that. Here's what I've done that seems to work.
I've got a Component Damageable that extends Monobehaviour. From that I have 2 components that extend from Damageable. DroneHealth and ShipHealth.
DroneHealth and ShipHealth are attached to prefabs. In my collision test code I do
Damageable damagable = gotHit.transform.parent.GetComponent<Damageable>();
To get the component (the DroneHeralth or ShipHealth component that is, I never attach the Damageable component to anything).
I then call applyDamage, which has the signature public virtual void applyDamage(float amount, NetworkPlayer fromPlayer)
in Damageable (and is overridden in the child classes) via RPC and the correct override in the subclass gets called (I was suprised this worked by RPC when I tested it, but it does. If it works that way I'm pretty sure it'll work for local calls).
Bare bones versions of the components
using UnityEngine; using System.Collections;
public class Damageable : MonoBehaviour {
private float inVulnDuration = 0.0f;
private float inVulnStart = 0.0f;
protected bool damagable = true;
public bool Damagable
{
get { return damagable; }
}
protected virtual void Update()
{
// if invulnerable
if (!damagable)
{
//check and see if we should become damageable yet
if ((inVulnStart + inVulnDuration) < Time.timeSinceLevelLoad)
{
damagable = true;
}
}
}
[RPC]
public virtual void applyDamage(float amount, NetworkPlayer fromPlayer)
{
Debug.Log(": " + "applyDamage in Damagable ");
}
}
using UnityEngine; using System.Collections;
public class ShipHealth : Damageable { protected override void Update() { base.Update(); // if invulnerable if (!damagable) { // code to make ship blink when invulnerable } }
[RPC]
public override void applyDamage(float amount, NetworkPlayer fromPlayer)
{
Debug.Log(": " +"applyDamage in shipHelath");
}
}
Although this answer was really helpful, it confused me a bit because of the RPC stuff which is not needed (as said but... well. I'm lost sometimes). All you need to do is:
gameObject.GetComponent();
Thanks anyway. :)
Answer by Eric5h5 · Aug 19, 2010 at 09:08 PM
Sounds like you should be using SendMessage.
gameObj.SendMessage("Speak");
In that case it doesn't matter what the component is called.
That may work, but my example above was simplified, I often need to set several variables, and Send$$anonymous$$essage can have only one param, correct? Any idea if you can send a structure as that param?
Actually, Broadcast$$anonymous$$essage worked better for me. For some reason, even though objects using the SA$$anonymous$$E prefab, some got the message, some didn't, seems like a bug.
Send$$anonymous$$essage() is supposed to work only on the specified GameObject and its components, not any children or components connected to them; use Broadcast$$anonymous$$essage to send a message to all children
@DaveA: yes, you can make a class with several elements and send that.