3

I am have some difficulty with what is probably a very silly thing. I have an enemy gameobject that depending on where it is hit (collision) - either it, or the play dies. I think the simplest way to describe this is by using the classic Super Mario Bros. game as an example.

As you all know, if the player runs into the enemy - the player will lose - UNLESS he jumps on top of the enemy's head, in which case the enemy should die.

enemy with colliders

My initial idea was to create two colliders on the gameobject:

  1. Blue border represents a BoxCollider2D - that if collided with - will cause player to lose (notice it is slightly lower from the top)
  2. Green border represents a BoxCollider2D on a child gameobject - that if collided with - will cause the gameobject to die.

The following is a simplified version of the code I used:

    // Collider #1
    public void OnCollisionEnter2D(Collision2D collision)
    {
        // Trigger 'Game-Over' logic
    }

    // Collider #2
    public void OnCollisionEnter2D(Collision2D collision)
    {
        if (collision.gameObject.tag == "Player")
        {
            Destroy(this.gameObject);
        }
    }

This kind-of works, however momentarily after colliding with Collider #1, Collider #2 is also trigger - and while the enemy is destroyed, the player also loses.

I have been playing with the RigidBody2D values to prevent the player from entering the 2nd collider when hitting the enemy from the top - but apparently with that force / speed, the colliders may be slightly inaccurate (or maybe I'm just doing it wrong?).

I have looked into RayCasts but this seems too complex for something that me appears rather trivial (casting rays on all four sides and four vertices of the player - assuming that the player has a box collider).

What I have resorted to 'for the moment' is a a single collider with a simple piece of code that I am unhappy with, and doesn't always work:

    public void OnCollisionEnter2D(Collision2D collision)
    {
        if (collision.gameObject.tag == "Player")
        {
            float yVelocity = collision.gameObject.transform.rigidbody2D.velocity.y;

            if (yVelocity < 0)
            {
                Debug.Log("Enemy will lose..." + yVelocity);

                Destroy(this.gameObject);
            }
            else
            {
                // Trigger 'Game-Over' logic
            }
        }
    }

I'm currently working in 2D mode, but solutions for 3D mode (while maybe more complicated than necessary for my question) will also be considered.

Thanks guys.

Zuiq Pazu
  • 285
  • 1
  • 4
  • 12
  • Hi! You can just do `Destroy(gameObject);` if you want to destroy yourself. :) – ʇolɐǝz ǝɥʇ qoq Feb 17 '15 at 00:30
  • @Bobthezealot - I definitely don't want to destroy myself :) What I want is for one of the colliders to trigger, without the other one triggering. In the case of the hit coming from the top, both colliders are being triggered - even though I'm trying to destroy the gameobject. – Zuiq Pazu Feb 17 '15 at 00:51
  • No, sorry, I meant you could replace the `Destroy(this.gameObject);` with `Destroy(gameObject);`. – ʇolɐǝz ǝɥʇ qoq Feb 17 '15 at 01:33
  • @ZuiqPazu do you look for a philosophical answer or a possible implementation? anyway I added an answer, was it what you were looking for? – Dinal24 Feb 17 '15 at 06:49

3 Answers3

1

as a game developer you always have many ways to solve a problem or make a gameplay. first of all i have to say you should make a polygon collider 2d fo you objects and chracters. just colliding pictures is not very good as i see you used box cilliders in your game.

a good choice can be that you attach and empty object ot you player and set its position under foots of you player and check of enemy hit that enemy dies else if enemy hit main character object, player dies.

another choice can be when o objects collide check y position of 2 objects. of player was higher he kiils, else enemy kills the player.

if you think more you will find more answers. you have to examin diffrent ways and find most efficient.

virtouso
  • 549
  • 11
  • 30
  • Thank you for your explanation. I am aware that usually BoxCollider2D does not suffice - and will not look pretty, but since my images are pretty much boxes anyway, I think I' fine using boxes. You mentioned about checking the Y-position of objects upon collision, but I have already tried that in the last code sample I have pasted above. It does not always work. Sometimes the value is rather strange and will trigger the enemy to die - when clearly the play ran into it. I think it has to do with the physics? – Zuiq Pazu Feb 17 '15 at 07:00
  • Also, attaching a GameObject to the player's foot seems little different from attaching a GameObject to the enemy's head. However I will try it in conjunction with @Dinal24 's suggestion and see how it goes from there. Will let you know. – Zuiq Pazu Feb 17 '15 at 07:01
  • As I commented on the other answer, while your answer does not really solve the issue by itself, a combination of both answers (and setting one of the colliders as a trigger, does seem to help with the issue). I will accept your answer for coming up with different alternatives. Thanks. – Zuiq Pazu Feb 17 '15 at 22:26
  • You say "I have already tried [checking the Y-position of objects]" but your original question shows you checking only the y-velocity of the player object. – Tim Sparkles Feb 07 '16 at 01:47
1

I think it will be easy to disable the other collider when one is triggered. You can easily enable/disable colliders with collider.enabled = true; or collider.enabled = false;

// Collider #1
public void OnCollisionEnter2D(Collision2D collision)
{
    // Trigger 'Game-Over' logic
    // collider2.enabled = false;
}

// Collider #2
public void OnCollisionEnter2D(Collision2D collision)
{
    // collider1.enabled = false;
    if (collision.gameObject.tag == "Player")
    {
        Destroy(this.gameObject);
    }
}

This way it will be pretty lightweight and easy to implement.

Dinal24
  • 3,162
  • 2
  • 18
  • 32
  • Just to clarify, I'm looking into a possible implementation, and your implementation suffices. However I don't know how this differs much from my current implementation, but I'll give it a shot just the same. Will let you know how it goes. – Zuiq Pazu Feb 17 '15 at 07:03
  • I have just tried the approach you mentioned, along with @virtuoso 's suggestion of using a GameObject at the player's foot. I then set that as trigger and also replaced OnCollisionEnter2D with OnTriggerEnter2D. This seems to work. I like both answers and I really wish I could mark them both as answers, however I will accept the other answer just because he talked about different alternatives (although lacked code). Thank you though... Unless you also wish to come up with other theoretical answers to this question, which might win you the cause :) – Zuiq Pazu Feb 17 '15 at 22:24
0

One way of implementing what you want is to put each collider in its child own game object and use the IsTouching() method.

void OnTriggerEnter2D(Collider2D other){
    if(GameObject.Find("Top Trigger").GetComponent<BoxCollider2D>().IsTouching(other)){
        Destroy(transform.gameObject)
    }
    if(GameObject.Find("Bottom Trigger").GetComponent<BoxCollider2D>().IsTouching(other)){
        Destroy(other.gameObject)
    }
}
Daniel
  • 1
  • 1