- Home /
Call same function in multiple scripts
Hi! I have six different types of cameras with their own respective script. All the scripts have a function called "CheckForPlayer" wich returns a bool based on if the camera can see the player or not. I also have a game manager that is supposed to loop through an array containing all the cameras and if one of the cameras return true the player will lose. But my problem is that i can't figure out how to store different scripts in the same array and then call the function. Is that even possible?
Thanks in regard!
Answer by Harinezumi · May 02, 2018 at 09:18 AM
What you are looking for is called polymorphism, a very important topic in programming, which in C# can be done with interfaces or subclassing.
Basically, you can need to create a common base type which all of your camera scripts implement or derive from, and then in your game manager store your cameras in an array of that type. It can be either an interface or an abstract base class (there are some differences, but that's not important for now). Something like this:
public interface PlayerChecker {
void CheckForPlayer(); // function that must be public and without implementation, but it can have whatever return type and parameters you want
}
// or you can do this:
public abstract class PlayerChecker : MonoBehaviour {
public abstract void CheckForPlayer (); // very similar to the above
}
// do the same for your other camera classes
// if you use the abstract base class, remove "MonoBehaviour,", because you already subclass it
public class YourCameraScriptVersion1 : MonoBehaviour, PlayerChecker {
// here implement the interface
public void CheckForPlayer () { /* do whatever this camera does */ }
// or here implement the abstract base class. The override keyword tells the compiler that the name is intentional, not named the same as in the base class by mistake
public override void CheckForPlayer () { /* do whatever this camera does */ }
}
public class GameManager : MonoBehaviour {
// put in this array exposed on the Editor your implementors of PlayerChecker, that is your cameras
[SerializeField] private PlayerChecker[] playerCheckers = null;
private void ChecksForPlayer () {
if (playerCheckers != null) {
// now you can call the same function on all cameras, because they all implement the PlayerChecker interface
for (int i = 0; i < playerCheckers.Length; ++i) { playerCheckers[i].CheckForPlayer(); }
}
}
}
Programming-wise there is no significant difference between the 2 approaches, but in Unity if you want to be able to assign the base type in the Editor, you need to use the abstract base class approach.
The limitation of this is that you need to create an interface (functions with parameters) that is good for all of your camera implementations. Try to think about it the way that you cannot know what is the real type, it should work no matter which one it is.
Thanks for the easy and correct answer! I accepted your answer since it is easier to follow along with than the other answers although they are correct as well!
Thanks! I personally liked Bunny83's answer more :D
Answer by Hellium · May 02, 2018 at 09:09 AM
Yes it is possible.
I see two possibilities:
1. Inheritance :
1. Create an abstract class (called CameraScript
for instance), and define the abstract method returning the boolean
2. Make your camera scripts inherit from the abstract class
3. In your game manager, define the array as follow : public CameraScript[] CameraScripts
2. Interface :
1. Create an interface class (called ICameraScript
for instance), and define the method returning the boolean
2. Make your camera scripts implement the interface
3. In your game manager, define the array as follow : public GameObject[] CameraScripts
4. When you want to check the condition, call GetComponent<ICameraScript>().YourMethod()
In fact, Unity is not able to serialize interfaces, explaining why you have to define an array of GameObjects, and not an array of interfaces
Oh! That seems to be the way to go, I will try it out as soon as i get back at my computer! Thanks for the fast reply!
So I attached gameobjects into the GameObject[] array and when running GetComponent().Death(); I get "Object reference not set to an instance of an object error"
It means the gameobjects you've provided don't have the component (or a component implementing the interface) you're looking for. Or one of the gameObjects is null.
Answer by Bunny83 · May 02, 2018 at 09:17 AM
First of all if the check if the player is visible in a certain camera is actually the same for each camera you should have created a seperate component and attach it to each camera. If you actually do something different in your "CheckForPlayer" method in each script you can simply use polymorphism.
If you want to be able to setup the references in the inspector you would need to derive all your scripts from an abstract base class which implements an abstract "CheckForPlayer" method that will be overridden in each concrete implementation of your scripts. That way you can have a List of that base class, assign all cameras in the inspector.
If you actually setup the references at runtime using GetComponent you can simply use an interface like this:
public interface IPlayerDetector
{
bool CheckForPlayer();
}
And then just let each of your script implement that interface:
public class SomeScript : MonoBehaviour, IPlayerDetector
{
// [ ... ]
public bool CheckForPlayer()
{
}
}
You can just do GetComponent<IPlayerDetector>()
and store them in your List
Answer by KaspianR · May 03, 2018 at 06:51 AM
Thanks for all the great answers! These answers are easy to both implement and to understand. Personally I prefer the abstract class since it looks better in the inspector! I accepted Harinezumi's answer because it contains code that you can just copy paste in to your own project!
Your answer

Follow this Question
Related Questions
BCE0019 when using functions 0 Answers
Fill out Event Trigger from Script 0 Answers
Problem with multiple objects using the same script 0 Answers
How to randomize the correct choice 2 Answers