Reputation: 3
I have three types of balls(A, B, C) all inherit MotherBall, they all have thesame behavior only some setting is different.
There is an ObjectPool which I can get ball by balltype, then it will contain it's script(AScript, BScript or CScript)
The situation is I will randomly take ball from object pool, and I hope I can handle it in one function not separate. Is there any way to call the Setting function like below code? I'm thinking maybe generic or delegates can slove it, or I need to write three functions. Thanks, everyone. P.S sorry my English is poor, I can't accurate describe my problem.
public void OneBallFire(string ballType){
GameObject ball = ballPool.GetObjectFromPool (ballType);
//I can't cast AScript, BScript or Motherball.
MotherBall ballScript = ball.transform.GetComponent (ballType) as MotherBall;
ballScript.Setting ();
}
public class MotherBall : MonoBehaviour{
public virtual void Setting() {
//Do nothing
}
}
public class AScript : MotherBall {
public void Setting(){
Debug.Log("Do A plan");
}
}
public class BScript : MotherBall {
public void Setting(){
Debug.Log("Do B plan");
}
}
OneBallFire( RandomGetAorBorC() );
string RandomGetAorBorC(){
//random return "AScript, BScript or CString" string.
}
Upvotes: 0
Views: 176
Reputation: 2417
Generic type is better solution for your case , And more Simply
public void OneBallFire<T>() where T : MotherBall
{
GameObject ball = ballPool.GetObjectFromPool<T>(ballType);
//I can't cast AScript, BScript or Motherball.
T ballScript = ball.transform.GetComponent<T>();
ballScript.Setting();
}
// BoolPool Todo This
public T GetObjectFromPool<T>()
{
if(T is AScript)
//Clone && Return a AScript Obj
// Todo all type ....
return null;
}
Upvotes: 0
Reputation: 10720
I am not sure if this will work in your scenario but I would go with classic is
as
to get the actual script:
var component = ball.transform.GetComponent(customScript);
if (component is AScript)
{
(component as AScript).Setting();
}
else if (component is BScript)
{
(component as BScript).Setting();
}
else
{
(component as MotherBall).Setting();
}
UPDATE:
You need to update implementation of BallPool
container in a way that you don't have to worry about sub-types and typecasting.
Here is a simple example:
I imagine you are storing ball gameObjects in a list. First thing I would do is use List<MotherBall>
as container.
public class BallPool : Monobehaviour
{
public List<MotherBall> ballPrefabs = new List<MotherBall>();
...
}
Add all kind of ball prefabs in this list from the inspector.
THen your method will look like this:
public MotherBall GetObjectFromPool()
{
return Instantiate(ballPrefabs[Random.Range(0,ballPrefabs.Count));
}
Then in your other script:
public BallPool ballPool; // assign from the inspector
void Start() // or whatever other method
{
var ball = ballPool.GetObjectFromPool();
ball.Setting();
}
Now ball.Setting()
will use the overridden method from either AScript or BScript depending on what object was selected and You don't need to worry about type as all the prefabs will have a script inherited from MotherBall
so all must have Setting()
if they don't have this method overridden then MotherBall.Setting()
will be called.
Hope this helps :)
Upvotes: 0
Reputation: 28510
No, because you're overriding
the method. If you need to have a method with the same signature as the base class's method you'll need to remove the override
keyword and replace it with new
. Now you'll have two methods that are totally unrelated to each other, you access the one on the Motherball
object by casting to Motherball
.
public class AScript : MotherBall {
public new void Setting(){
//Do something
}
}
var _ball = new AScript();
_ball.Setting() // calls Setting on AScript
((MotherBall) _ball).Setting(); // Calls Setting on MotherBall
What I suspect you want to do though is invoke the base method when you call Setting()
on the AScript
class. You have two options here.
AScript
completely, any call to AScript.Setting()
will invoke the base class's Setting()
method.Setting()
method from the AScript
classes method, to do this use the base
keyword, e.g. base.Setting()
.Upvotes: 1