# How can I grab the script component of a collided object without knowing what script it is?

CalculateDamage() is an animation event called at a point during the character's animation in my 2D game. The commented out code is before I realized that not all of my pirates will be of class MeleePirateUnit, so I'm trying to do things more generically here. My order of inheritance is like so:

MonoBehaviour > Unit > MeleePirateUnit, RangedPirateUnit.

So sometimes, the collidedobj is a MeleePirateUnit, sometimes it's a RangedPirateUnit, etc etc. How do I set pirateUnit to the correct type of the script component of my gameObject? I thought just getting component of type monobehaviour would work since RangedPirateUnit and MeleePirateUnit both derive from monobehaviour but I'm getting an error of

Assets/Scripts/Combat Scene/RangedPirateUnit.cs(72,56): error CS1061: Type UnityEngine.MonoBehaviour' does not contain a definition forhealth' and no extension method health' of typeUnityEngine.MonoBehaviour' could be found (are you missing a using directive or an assembly reference?)

public void CalculateDamage(){
if (!isDestroyed){
var pirateUnit = collidedObj.GetComponent<MonoBehaviour>();
//MeleePirateUnit pirateUnit = collidedObj.GetComponent<MeleePirateUnit>();
pirateUnit.health = pirateUnit.health - (damage - pirateUnit.defence);
if (pirateUnit.health<=0){
Destroy(pirateUnit.gameObject);
isDestroyed = true;
didAttack = false;
}
}
}

• Unity favours the principle of Composition Over Inheritance, so anytime you're using inheritance, it's worth asking whether you could accomplish the task by composition instead. In this case, you could have a Health component that handles HP & death, and guarantee that all unit classes have one using [RequireComponent()]. You don't need to do it this way, but it's often easier to go with the flow of how Unity likes to do things, and the modularity can have unexpected side benefits (like being able to give health to destructible objects like crates or breakable walls, which aren't units) – DMGregory Jun 9 '15 at 2:45

Assuming your Unit class has the health var, try:

Unit pirateUnit = collidedObj.GetComponent<Unit>();

• my unit class doesn't have a health var -- I set the health/attack/defence in the inherited class (so PirateMeleeUnit/PirateRangedUnit). – Jeff Burghess Jun 9 '15 at 2:46
• Move those vars into the Unit class; your child classes will inherit them. – Chris McFarland Jun 9 '15 at 2:49
• Good point, just to clarify things a bit, if I create a new child class it's as if a new parent class is also created, correct? So if I create two new instances of MeleePirate, each MeleePirate class inherits from a separate Unit class, rather than both MeleePirate classes inheriting from a single common Unit class. – Jeff Burghess Jun 9 '15 at 2:55
• Yes. And you can use typeof() to get the exact class you grabbed with GetComponent then use a switch statement to parse over the ones you want to perform actions on. But really grouping values like Health in the Unit class is a better idea. – Jeremiah Leslie Jun 9 '15 at 3:38
• Might be better to have a TakeDamage(int) method or something on your Units rather than changing health externally. If you wanted a separate implementation of this method for melee/ranged pirates, you would declare the method as abstract in Unit. This basically makes the code say "I don't know or care what kind of Unit this is, because it's guaranteed to have a TakeDamage(int) method on it, and I'm calling it." It's like a contract that states anything that inherits from the class going to have that method, but it would do completely different things as required – greenland Jan 8 '16 at 19:45