简体   繁体   English

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

[英]Unity/C# - Referencing a method on another object

I decided to have a play with Unity a couple of days ago and despite being an old hand at programming, both Unity and C# are completely new to me. 几天前,我决定与Unity一起玩游戏,尽管在编程方面起了很大的作用,但Unity和C#对我来说都是全新的。 I'm working in 2D. 我正在2D模式下工作。

I've created a little game to try and learn the engine, which (uniquely) involves firing bullets at aliens. 我创建了一个小游戏来尝试学习引擎,该引擎(唯一)涉及向外星人发射子弹。 I'm using the bullet object to detect when it hits something (and destroy itself), and in the cases where it hits something that needs to react - the target object to decide what its response should be. 我正在使用bullet对象来检测它何时击中某些东西(并摧毁自身),以及在其击中需要做出反应的东西的情况下-目标对象来决定其响应。

Here's the relevant part of BulletController which is attached to each instance of the bullet: 这是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);
    }

}

And for completeness, the (placeholder) part from BasicAlienController : 为了完整起见,来自BasicAlienController的(占位符)部分:

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

I had originally typed up a massive question on how to call TakeHit on the alien's script, but after a fair bit of trial and error, figured it out to the above, it works well but I don't feel great about how it's written. 我最初在如何在外星人的脚本上调用TakeHit时打了一个大问题,但是经过一番尝试和错误之后,发现上面的内容很有效,但是我对它的编写方式并不满意。 It doesn't seem right to blindly believe that there's a BasicAlienController on each enemy, because later on, I might extend that with alien-specific controllers so they can react in different ways. 盲目相信每个敌人上都有一个BasicAlienController似乎是不对的,因为稍后,我可能会使用特定于外星人的控制器来扩展它,以便它们可以以不同的方式做出反应。 It also doesn't seem right to blindly believe that there is also a TakeHit() method available on everything tagged as being 'Alien', I mean, I guess there should be, but it might not always be the case. 盲目相信标记为“外星人”的所有内容上也都可以使用TakeHit()方法,这似乎也不对,我的意思是,我想应该有,但并非总是如此。

So this is a multi part question: 所以这是一个多部分的问题:

  1. How can I make sure I make sure I call the relevant controller based on the enemy type, if I have (for example) FlyingAlienController and WalkingAlienController without having to specifically query the name of the object and then do a potentially big switch? 如果我有(例如) FlightingAlienControllerWalkingAlienController,而不必专门查询对象名称,然后进行潜在的大切换,如何确定自己根据敌人的类型调用相关的控制器? If I can only have one script attached to a GameObject then why can't I just reference 'the script', whatever its name is? 如果我只能在一个GameObject上附加一个脚本,那么无论我叫什么名字,为什么我不能只引用“脚本”?

  2. How can I check that there is a TakeHit() method available, or is it just up to me to make sure I always expose that method on anything that's tagged as being 'Alien'? 如何检查是否有TakeHit()方法可用,还是要确保我始终在标记为“ Alien”的任何内容上公开该方法?

  3. Bonus question, what's the deal with the < > around the controller name, I'm new to C# and haven't seen that syntax before, why wouldn't it just have been gameObject.GetComponent("BasicAlienController") or similar? 额外的问题是,控制器名称周围的<>有什么用,我是C#的新手,以前没有看过这种语法,为什么不只是使用gameObject.GetComponent(“ BasicAlienController”)或类似名称呢?

1. How can I make sure I make sure I call the relevant controller based on the enemy type, if I have (for example) FlyingAlienController and WalkingAlienController without having to specifically query the name of the object and then do a potentially big switch? 1.如果我有(例如)FlyingAlienController和WalkingAlienController,而不必专门查询对象名称,然后进行潜在的大切换,如何确定我根据敌人的类型调用相关的控制器? If I can only have one script attached to a GameObject then why can't I just reference 'the script', whatever its name is? 如果我只能在一个GameObject上附加一个脚本,那么无论我叫什么名字,为什么我不能只引用“脚本”?

You can actually have as many scripts as you want on a GameObject. 实际上,您可以在GameObject上拥有任意数量的脚本。 My suggestion is to make an interface that each of your controllers implement then use "SendMessage". 我的建议是为每个控制器实现一个接口,然后使用“ SendMessage”。 There's a performance hit with SendMessage, but for this situation I think it's the right choice. SendMessage会对性能产生影响,但是对于这种情况,我认为这是正确的选择。

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

Unfortunately you can't strict type that call, but it'll do. 不幸的是,您不能严格键入该调用,但是可以。 You code might look something like this: 您的代码可能看起来像这样:

BasicAlienController: 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 : 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 : 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. Bonus question, what's the deal with the < > around the controller name, I'm new to C# and haven't seen that syntax before, why wouldn't it just have been gameObject.GetComponent("BasicAlienController") or similar? 3.奖励问题,控制器名称周围的<>有什么用,我是C#的新手,以前没有看过这种语法,为什么不只是使用gameObject.GetComponent(“ BasicAlienController”)或类似的名称? C# generic. C#通用。 See Andy's link. 参见安迪的链接。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM