How to access an instance of a class when the class isn't known

Hello,

I have a script called Main that does stuff when you make a mouse click. I have a script called Player and another called Soldier. The Soldier script defines a Soldier class and inherits from Player. Player has a function called playerSelected().

I want to query this function and run other functions from the Main script, but I don’t know whether I’m calling Player or Soldier, or even GameObject. I tried GameObject to no avail.

Here’s the update function of the Main script. It fails at selectedObject.playerSelected(false); because I’m passing it a GameObject when it should be getting a Player object or a Soldier object. How do I determine what kind of object is being passed. Am I going about this the wrong way entirely?

function Update () {

	if (Input.GetMouseButtonDown (0)) {
	
		objectName 	   = common.getObjectNameFromTap();
		selectedObject = GameObject.Find(selectedObjectName);
		
		if (object != null)
		{
			object = GameObject.Find(objectName);
			
			// deselect currently selected object
			if (selectedObject)
				selectedObject.playerSelected(false);

The reason it fails at selectedObject.playerSelected(false) is because GameObjects know nothing about the method playerSelected(). What you need to do, is obtain a reference to your Player script from the GameObject, then proceed from there. Here is an example:

selectedObject = GameObject.Find(selectedObjectName);

// Test to make sure you got something back, not null
if(selectedObject)
{
   // Now, see if the selectedObject has a Player script attached
   var player : Player = selectedObject.GetComponent(Player);
   if(player)
   {
      // The selectedOject IS a Player, do Player stuff with it.
      // This will work for either a Player, or Soldier, since Soldier inherits from Player

      player.playerSelected(false);

      // If you want to see if the player is also a Soldier to do Soldier specific stuff

      var soldier : Soldier = player as Soldier;
      if(soldier)
      {
         // player IS also a Soldier
      }
      else
      {
         // player is NOT a Soldier
      }
   }
   else
   {
      // The selectedObject is NOT a Player
   }

}

Unity is a component-based architecture. Once you get this basic concept in your head, the rest is easy:

The GameObject is just a container of components. Some components are built-in, like Transform, and the rest come from scripts (when inherited from MonoBehavior). So in your case, the Player script defines a Player component.

When you add the Player component to the GameObject, the GameObject does not suddenly “become” a Player. It’s still just a container of components where one of them happens to be Player.

Therefore, when you want to access a function on something, you have to get it’s container (the GameObject like you did above) and look inside for the component that has the function (or method in C#) you want to call.

So in JavaScript:

  var player:Player = selectedObject.GetComponent(Player);
  player.playerSelected(false);

In C#

  Player player = selectedObject.GetComponent<Player>();
  player.playerSelected(false);

You can find discussion of access components here.

And remember, any GameObject an have many different components. It is best to structure your game code into individual components that have a very defined function (i.e. try not to dump everything into one class) and have them work with each other. But also keep in mind that a component might not be there! So check for null if there is any doubt.