Unity / C# - 在另一个对象上引用方法

时间:2014-08-25 22:48:30

标签: c# unity3d

我决定几天前和Unity合作,尽管是编程方面的老手,Unity和C#对我来说都是全新的。我在2D工作。

我创造了一个小游戏来尝试和学习引擎,它(独特地)涉及向外星人发射子弹。我正在使用子弹对象来检测它何时命中(并自我毁灭),并且在它遇到需要反应的东西的情况下 - 目标对象来决定它的响应应该是什么。

以下是 BulletController 的相关部分,它附在子弹的每个实例上:

    // Check to see if the bullet is colliding with anything.
void OnCollisionEnter2D(Collision2D col)
{
    if (col.gameObject.tag == "Terrain") {
        this.audio.Play ();
        int smokeIndex = 0;
        GameObject smoke = (GameObject) Instantiate(bulletSmoke[smokeIndex],transform.position,transform.rotation); 
        Destroy (smoke, 5f);
        Destroy (gameObject,0.05f);
    }

    if (col.gameObject.tag == "Enemy") { 
        col.gameObject.GetComponent<BasicAlienController>().TakeHit (1,1);
    }

}

为了完整起见, BasicAlienController 中的(占位符)部分:

public void TakeHit(int damageType, int damageAmount) {
    print ("Taking hits");
}

我最初输入了一个关于如何在外星人的剧本上调用 TakeHit 的大问题,但经过一段时间的试验和错误后,我发现上述情况,它运作良好,但我对它的编写方式感觉不太好。盲目地认为每个敌人都有一个 BasicAlienController 似乎是不对的,因为稍后,我可以用外星人特定的控制器来扩展它,这样他们就能以不同的方式做出反应。盲目地认为在标记为'异形'的所有东西上也有一个 TakeHit()方法似乎也不正确,我的意思是,我想应该有,但它可能并不总是是这样的。

所以这是一个多部分的问题:

  1. 如果我有(例如) FlyingAlienController WalkingAlienController ,我怎样才能确保我根据敌人类型调用相关控制器必须专门查询对象的名称,然后做一个潜在的大转换?如果我只能将一个脚本附加到GameObject上,那么为什么我不能只引用“脚本”,无论其名称是什么?

  2. 如何检查是否有可用的 TakeHit()方法,还是由我决定是否始终将该方法暴露在标记为'Alien'的任何内容上“?

  3. 奖金问题,与&lt; &GT;围绕控制器名称,我是C#的新手并且之前没有看到过这种语法,为什么它不会只是 gameObject.GetComponent(“BasicAlienController”)或者类似的?

1 个答案:

答案 0 :(得分:2)

<强> 1。我怎样才能确保我根据敌人的类型调用相关的控制器,如果我有(例如)FlyingAlienController和WalkingAlienController而不必专门查询对象的名称然后做一个可能很大的开关?如果我只能将一个脚本附加到GameObject,那么为什么我不能只引用“脚本”,无论其名称是什么?

实际上,您可以在GameObject上拥有任意数量的脚本。我的建议是使每个控制器实现的接口使用“SendMessage”。 SendMessage的性能受到了打击,但对于这种情况,我认为这是正确的选择。

http://docs.unity3d.com/ScriptReference/GameObject.SendMessage.html

不幸的是你不能严格打电话,但它会这样做。您的代码可能如下所示:

<强> BasicAlienController:

public class BasicAlienController : MonoBehavior, ITakeHit
{
    // It can only take a single input
    public void TakeHit(object args) 
    {
        // Logic here
        print ("Taking hits in BasicAlienController ");
    }
}

FlyingAlienController:

public class FlyingAlienController : MonoBehavior, ITakeHit
{
    // It can only take a single input
    public void TakeHit(object args) 
    {
        // Logic here
        print ("Taking hits in FlyingAlienController ");
    }
}

BulletController:

// Check to see if the bullet is colliding with anything.
void OnCollisionEnter2D(Collision2D col)
{
    if (col.gameObject.tag == "Terrain") 
    {
        this.audio.Play ();
        int smokeIndex = 0;
        GameObject smoke = (GameObject) Instantiate(bulletSmoke[smokeIndex],transform.position,transform.rotation); 
        Destroy (smoke, 5f);
        Destroy (gameObject,0.05f);
    }

    if (col.gameObject.tag == "Enemy") 
    { 
        int[] hit = new int[] {1, 1};
        col.gameObject.SendMessage("TakeHit", hit);
        // If you don't want to require a receiver
        // col.gameObject.SendMessage("TakeHit", hit, SendMessageOptions.DontRequireReceiver);
    }
}

第3。奖金问题,与&lt;的交易是什么? &GT;围绕控制器名称,我是C#的新手并且之前没有看到过这种语法,为什么它不会只是gameObject.GetComponent(“BasicAlienController”)或者类似的? C#通用。见安迪的链接。