通过使用带有名称的GetComponent来调用函数,而不知道它实际上是类型

时间:2017-12-20 10:23:11

标签: c# unity3d

我有三种类型的球(A,B,C)都继承了MotherBall,它们都有相同的行为只有一些设置不同。

有一个ObjectPool,我可以通过balltype获得球,然后它将包含它的脚本(AScript,BScript或CScript)

情况是我会从对象池中随机取球,我希望我能在一个不能分开的功能中处理它。 有没有办法调用如下代码的设置功能?我认为可能是通用的,或者代表可以解决它,或者我需要编写三个函数。 感谢大家。 P.S对不起我的英语很差,我无法准确描述我的问题。

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.
}

3 个答案:

答案 0 :(得分:1)

不,因为你是overriding方法。如果您需要使用与基类方法具有相同签名的方法,则需要删除override关键字并将其替换为new。现在,您将拥有两种完全无关的方法,您可以通过转换为Motherball来访问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

我怀疑你想要做的是在Setting()课程上调用AScript时调用基本方法。你有两个选择。

  1. 只需完全删除AScript中的方法,对AScript.Setting()的任何调用都将调用基类的Setting()方法。
  2. Setting()类方法调用基类的AScript方法,为此使用base关键字,例如base.Setting()

答案 1 :(得分:0)

我不确定这是否适用于您的方案,但我会使用经典的is as来获取实际的脚本:

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();
}

<强>更新

您需要以不必担心子类型和类型转换的方式更新BallPool容器的实现。

这是一个简单的例子:

我想你正在将球类游戏对象存储在一个列表中。我要做的第一件事是使用List<MotherBall>作为容器。

public class BallPool : Monobehaviour
{
    public List<MotherBall> ballPrefabs = new List<MotherBall>();
    ...
}

从检查员中添加此列表中的所有类型的球预制件。

你的方法看起来像这样:

public MotherBall GetObjectFromPool()
{
    return Instantiate(ballPrefabs[Random.Range(0,ballPrefabs.Count));
}

然后在你的另一个剧本中:

public BallPool ballPool; // assign from the inspector

void Start() // or whatever other method
{
    var ball = ballPool.GetObjectFromPool();
    ball.Setting();
}

现在ball.Setting()将使用AScript或BScript中的重写方法,具体取决于所选择的对象,并且您不必担心类型,因为所有预制件都将具有从{{1继承的脚本所以如果他们没有覆盖此方法,那么所有人都必须拥有MotherBall,然后才会调用Setting()

希望这会有所帮助:)

答案 2 :(得分:0)

泛型类型更适合您的情况,而且更简单

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;
}