x


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.

more ▼

asked Aug 19 '10 at 09:01 PM

DaveA gravatar image

DaveA
26.8k 153 171 257

(comments are locked)
10|3000 characters needed characters left

2 answers: sort voted first

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");
    }
}
more ▼

answered Aug 19 '10 at 11:21 PM

Eagle32 gravatar image

Eagle32
452 2 6 17

That's just what I needed, thanks!

Aug 20 '10 at 12:09 AM DaveA

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

Nov 13 '10 at 10:18 AM Rodrigo Moraes
(comments are locked)
10|3000 characters needed characters left

Sounds like you should be using SendMessage.

gameObj.SendMessage("Speak");

In that case it doesn't matter what the component is called.

more ▼

answered Aug 19 '10 at 09:08 PM

Eric5h5 gravatar image

Eric5h5
81.5k 42 133 529

That may work, but my example above was simplified, I often need to set several variables, and SendMessage can have only one param, correct? Any idea if you can send a structure as that param?

Aug 19 '10 at 09:52 PM DaveA

Actually, BroadcastMessage worked better for me. For some reason, even though objects using the SAME prefab, some got the message, some didn't, seems like a bug.

Aug 19 '10 at 10:17 PM DaveA

SendMessage() is supposed to work only on the specified GameObject and its components, not any children or components connected to them; use BroadcastMessage to send a message to all children

Aug 19 '10 at 10:46 PM Wolfram

@DaveA: yes, you can make a class with several elements and send that.

Aug 19 '10 at 11:18 PM Eric5h5

Good to know, thanks

Aug 20 '10 at 12:10 AM DaveA
(comments are locked)
10|3000 characters needed characters left
Your answer
toggle preview:

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Topics:

x3420
x1288
x422
x14

asked: Aug 19 '10 at 09:01 PM

Seen: 2804 times

Last Updated: Aug 19 '10 at 09:01 PM