I Have a game that I am developing, it is a TBS, and will have many creatures involved. I wanted to store all the creatures I have at runtime in an array, which I have successfully done. However, I need to be able to call all scripts from those array items, so: How can I call differently named scripts on GameObjects in an array all at once, OR what alternatives do I have? For background on its use, think about Initiative in D&D.
1 Answer
Assuming you're using inheritance or interfaces, you can create an array of your base class/interface, and add all your creatures into that array (which you say you have an array of all these creatures).
You would simply loop through all the elements in the array, and call the respective method.
For example:
//not a cut-and-paste example, but gives you the general idea.
foreach(var _creature in Array)
{
_creature.Die();
}
However, if you are trying to call a different method for each one, you may find this will not work for you.
If you want to break it down further, you can try and switch on the type and then call a specific method for each type, but then it isn't a truly generic class:
For example:
//not a cut-and-paste example, but gives you the general idea.
foreach(var _creature in Array)
{
switch typeof(_creature):
case LowLevel:
_creature.Flee();
break;
case MidLevel:
_creature.Guard();
break;
case HighLevel:
_creature.Attack();
break;
default:
_creature.Idle();
break;
}
An example of a polymorphic implementation:
public abstract class Combatant : MonoBehaviour
{
//for arguments sake, we are only going to have speed property, attack method which
//all instances have to implement, and a defend which only some might implement their
//own method for (the rest default to the base class)
int speed {get;set;}
//Need to have this method in derived classes
//We don't define a body, because the derived class needs to define it's own
protected abstract void Attack();
//Can be overriden in derived class, but if not, falls back to this implementation
protected virtual void Defend()
{
speed *= 0.5; //half speed when defending
}
}
public class MonsterA : Combatant
{
protected override void Attack()
{
//attack code goes here for MonsterA
}
//to access speed, we simply need to use base.speed
public void SomethingElse()
{
base.speed *= 1.25;
}
//notice we don't have to provide an implementation for Defend, but we can still access it by calling base.Defend(); - this will then run the base classes implementation of it.
}
public class MonsterB : Combatant
{
protected override void Attack()
{
//attack code goes here for MonsterB
}
//Assume this is a 'heavier' class 'monster', speed will go down more than standard when defending
protected override void Defend()
{
base.speed *= 0.3;
}
}
12 Comments
Array<GameObject>, then you will not have these methods exposed to you unless you cast them to the type you are 100% sure they are.public GameObject[] Combatants; and then Combatants = GameObject.FindGameObjectsWithTag("tagname"); and finally be able to get the scripts from all of those items. Is there any way of doing that specifically?Combatants? Or do you want to know what scripts are attached to those Combatant game objects? Your method most definitely works, and it will return an array of GameObject - but you must know that it will be of type GameObject, meaning unless you cast it to the type or assign it to a typed variable, you will not be able to access the methods that are on the Combatant because they do not exist on the GameObject class.ClassName : MonoBehavior? I would suggest, if they all share a common property/properties/methods, to have an Interface (ie. ICombatant) that all the other combatants implement, which then enforce that all Combatants have, for example, a speed variable, an attack method, etc.. Then you can create an Array<ICombatant> and return all objects that implement this interface. Then you can easily compare this variable against other base scripts (ie. MonsterA : MonoBehavior, ICombatant, MonsterB : MonoBehavior, ICombatant). Let me know if this makes sense.