Hello, I was hoping someone could help me with a problem I am having.
Lets say I have three C# scripts, ScriptA, ScriptB and ScriptX, all of which inherit from MonoBehaviour.
Say ScriptA is attached to GameObjectA and has a public function FunctionA(), which returns a boolean.
And ScriptB is attached to GameObjectB and has a public function FunctionB(), which also returns a boolean.
Now here is where it gets a little strange.
I want ScriptX to have a type of “unspecified” function called Evaluate() which returns a boolean and has the following ability:
Say I have two empty game objects, GameObjectX1 and GameObjectX2, and I attach ScriptX to both.
When I call Evaluate() from GameObjectX1 I get the result of FunctionA(),
But when I call Evalaute() from GameObjectX2 I get the result of FunctionB().
It is as if I wish ScriptX had a field in the inspector which I could assign FunctionA() or FunctionB() or really any function which returns a boolean, then when I call Evaluate() from ScriptX it acts as that assigned function.
Is this something that can be solved with delegates?
You might want to add the reason why you don’t use an interface or the like? Let’s call it IEvaluable, it really doesn’t matter though.
Two components could then implement said interface and in both, you’ll be able to specify what happens when the method of the concrete implementation is called. They don’t have to have anything else in common, all that matters is that both can be of type ‘IEvaluable’.
In order to achieve that, you can just call GetComponent() on either object and if the return value is not null, you can call Evaluate on it.
There are also other ways to achieve similar behaviour, but this should be sufficient from what you’ve written, unless I didn’t understand it completely.
You could do this with an enum and a switch statement
public class ScriptX : MonoBehavior
{
public enum Function { FunctionA, FunctionB };
public Function myFunction = Function.FunctionA; // This should show in the inspector
public bool Evaluate()
{
switch(myFunction)
{
case Function.FunctionA:
return MyFunctionA();
case Function.FunctionB:
return MyFunctionB();
}
}
private bool MyFunctionA() { return true; }
private bool MyFunctionB() { return false; }
}
I have tried your suggestion Suddoha and it works wonderfully.
I am not too familiar with Interfaces which is why I did not try that.
Here is what I did just to make sure I am getting what you are saying.
I made the interface:
public interface IEvaluable
{
bool Evaluate();
}
Here are ScriptA and ScriptB (attached to GameObjectA and GameObjectB respectively)
public class ScriptA : MonoBehaviour, IEvaluable
{
public bool FunctionA() { /*...code...*/ }
public bool Evaluate() { return FunctionA(); }
}
public class ScriptB : MonoBehaviour, IEvaluable
{
public bool FunctionB() { /*...code...*/ }
public bool Evaluate() { return FunctionB(); }
}
And here is ScriptX (this one does not implement IEvaluable)
public class ScriptX : MonoBehaviour
{
public GameObject Obj;
public bool Evaluate() { Obj.GetComponent<IEvaluable>().Evaluate() }
}
Now when I drag ScriptX onto a game object, it exposes the field Obj in the inspector.
If I drag GameObjectA on to the field, then Evaluate() in ScriptX gives FunctionA().
If I drag GameObjectB on to the field, then Evaluate() in ScriptX gives FunctionB().
Awesome, thank you again Suddoha.
Now I have question which builds on this. I will ask this question in the next post.
Here is my next question which builds on the above.
What is ScriptA has two functions in it, say FunctionA1() and FunctionA2().
I guess I could modify the interface to:
public interface IEvaluable
{
bool Evaluate1();
bool Evaluate2();
}
then ScriptA would look like:
public class ScriptA : MonoBehaviour, IEvaluable
{
public bool FunctionA1() { /*...code...*/ }
public bool FunctionA2() { /*...code...*/ }
public bool Evaluate1() { return FunctionA1(); }
public bool Evaluate2() { return FunctionA2(); }
}
Now this would work, but the problem I have is that ScriptA could have any number of
functions which I want to target in this way.
Can we generalize this technique so that if ScriptA has “n” functions I can some how
target any given one in ScriptX?
At some point you have to determine which method you want to call, like @Kiwasi and others have said, you can always pass parameters but if that’s only a parameter to determine the method to call, you could also declare more methods and call them directly.