How can I access a function without knowing the script/class name to which it belongs?

Here is the situation. (This situation is purely hypothetical for now, I’m explaining the situation so you can tell me the best approach before I attempt to write the code).

The game isn’t exactly a beat-em-up; but for the purposes of this example, you can think of it like a beat-em-up for now.

I have a hundred different character prefabs that each of which needs to have a script attached to it with some kind of “Attack” function. The function will include different code depending on which character prefab it is attached to. So for example, one character might swing a sword when the attack function is called, whereas another character might shoot a bow.

It is a multiplayer game, and so, each player picks a character in a menu screen, and afterwards battle commences. Depending on which characters were selected, a prefab of each character is instantiated and assigned to a player at the beginning of combat.

Separate to all of this I have an InputManager script that is checking what inputs have been pressed by either player and then needs to call the attack function on that player’s character accordingly.

Is there an easy way to do this without having to have a massive 100-long “switch/case” statement on a single script which the InputManager attempts to access? The moment that I try to separate out the attack function so that is inside of multiple scripts/classes I get the problem of finding a way of identifying the class to which the attack function belongs (at least as far as I’m aware). Because different players can pick the same character I can’t really have some static function for each of the characters different attacks (again as far as I’m aware).

My question is this; how would you go about solving this kind of issue?
(I’m aware I might be thinking about it the wrong way, so any suggestions are welcome).

P.S. I will be using C#, although javascript solutions are also welcome.

This is a design issue. You should have all your script sharing the same interface.

class MyPlayer_1_Script : MonoBehaviour , PlayerScript
{
    public void attack(){/*You attack specific to player 1 goes here*/}
    blabla
}
class MyPlayer_2_Script : MonoBehaviour , PlayerScript
{
    public void attack(){/*You attack specific to player 2 goes here*/}
    blabla
}
interface PlayerScript
{
    void attack();
}

etc.

In this case all you would need to grab is PlayerScript myPlayer = “your selected Player” , and input would just have to call myPlayer.attack();

Now if you’d like to directly call that just knowing the gameObject, you would use a MonoBehavior base class like so:

class MyPlayer_1_Script : PlayerScript
{
    public override void attack(){/*You attack specific to player 1 goes here*/}
    blabla
}
class MyPlayer_2_Script : PlayerScript
{
    public override void attack(){/*You attack specific to player 2 goes here*/}
    blabla
}
class PlayerScript : MonoBehavior
{
    public virtual void attack(){}
}

You would then with your gameObject simply do:

PlayerScript player = myGameObject.GetComponent<PlayerScript>();
player.attack();

A good solution is to use SendMessage(“Attack”) - the function Attack is called by name, thus you don’t have to worry about the script name. This is used in the good (but unfortunately no more available) FPS Tutorial: the function “Fire” is called via SendMessage in the weapon script, no matter which weapon is select. If you want to call a function by name in another object, just prefix SendMessage with a reference to the object:

somePlayer.SendMessage("Attack");

If Attack is in a script attached to a child of somePlayer, use BroadcastMessage instead: this version calls the specified function in any script down in the hierarchy.