Recommended Approach to multiple colliders - unity3d

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.
My initial idea was to create two colliders on the gameobject:
Blue border represents a BoxCollider2D - that if collided with - will cause player to lose (notice it is slightly lower from the top)
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.

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.

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.

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

Related

Weapon Pick-Up and shoot

I'm new to Unity and I was wondering if anyone knows how to make the player pick up a weapon and shoot it in Unity 2D. I have already made the sprite for the gun and I've been trying to pick it up with this code:
public GameObject player;
void Update() {
void OnTriggerEnter2D(Collider2D col) {
if (col.tag == "Player") {
gameObject.transform.position = new Vector3(player.transform.position.x + 2, player.transform.position.y, player.transform.position.z);
}
}
}
The gun is set as a trigger and has no rigidbody. All the youtube tutorials show how to pick up an object and then destroys it, but don't show how to "hold" the object.
If you do player.transform.position.x + 2, that sets the gun to the x position of the player + 2. This is not a good way of doing it.
My advice is to do it this way instead.
Copy the gun.
Parent the copy to the camera
Place the gun somewhere on your player.
Disable the gun
In your player script add this line
public GameObject weapon;
Now, in your weapon pickup script, change the player reference to whatever your player script is called instead of a GameObject.
For example, lets assume your player script is called PlayerScript.cs, instead of
public GameObject player;
You should do
public PlayerScript player;
Now, we have a reference to the player script. We can now access the weapon.
Change the OnTrigger to the following:
void OnTriggerEnter2D(Collider2D col) {
if (col.tag == "Player") {
// Set the weapon active
player.weapon.SetActive(true);
// Destroy this pick-up
Destroy(gameObject);
}
}
Also, in your code you have ontriggerenter inside the update method. That is not how it works. Make sure the method is outside of the update method.
Now when you touch the gun on the floor. It should now enable the gun in the players hand and destroy the one on the floor.
In the editor, drag the players gun to the weapon field in the player script.
Also, drag the player to the player field of the gun on the ground.
Hope this helps, feel free to ask more questions if this doesn't work. Keep us updated. :)

how do i make sword work with enemy collider

here is my current code:
public GameObject enemy;
void OnCollisionEnter(UnityEngine.Collision collisionInfo)
{
if (collisionInfo.collider.tag == "sword")
{
Debug.Log("works");
enemy.SetActive(false);
}
else
{
Debug.Log("doesnt work");
}
}
i have attached this to the enemy and also i tried a different script attached to the sword
void OnTriggerStay(Collider col)
{
if (Input.GetButtonDown("Fire1"))
{
if (col.GetComponent<Collider>().tag == "enemy")
{
Destroy(col.gameObject);
}
}
}
both codes don't work, it seems that the problem isnt with the sword collision cus i have also added the tag to another gameobject and it doesnt work. i looked online but havent found anything that works so fat
update: it seems that i have forgot you need a rigid body for collision detection. simple mistake but it made my code not work!
For collision enter to work, both the sword and the enemy colliders need to have the "IsTrigger" box unticked.
For on triggerstay is the opposite, both need to have that box ticked.
Basically, Triggers do not collide they call that OnTriggerEnter function, while non-triggers use the OnCollisionEnter.

Can't detect collision with child and ground

I have the below script attached to the ground game object to detect collisions from my players' child objects but for some reason, the collisions are not detecting.
My player (parent, empty game object) has a Rigidbody and Jump script attached to it, meanwhile, the child game objects (body & feet) have just box colliders on them.
Would love to know why this isn't working :)
private void OnCollisionEnter(Collision collision)
{
if(collision.gameObject.tag == "Body")
{
Debug.Log("Game over!");
}
else if (collision.gameObject.tag == "Feet")
{
Debug.Log("Alive!");
}
}
For some reason, it works when you do collision.collider.tag instead of collision.gameobject.tag, like so:
if(collision.collider.tag == "Head")
{
Debug.Log("Game over!");
}
Not exactly sure why this works, but it works! Defo going to look into this a bit more.

Two Gameobjects collides although they are not on the same place

I have a Gameobject called ball and another called floor. As can be seen in the code, when the ball hits the floor, a printout shall be made.
void OnCollisionEnter2D(Collision2D collision)
{
bg = GameObject.Find(bg_name);
if (collision.gameObject.tag == "floor")
{
//bg.GetComponent<ControlGame>().deleteBall();
//bg.GetComponent<ControlGame>().recreateBall();
print("Ball hit floor");
}
if (collision.gameObject.tag == "rope")
{
bg.GetComponent<ControlGame>().ToggleIsShot(false);
}
}
The problem is that I have moved the floor now, such that the ball and the floor has different depth. Still, the printout is made although the two Gameobjects are not touching. See the screenshots below:
The print is in the lower left corner. Why is that?
According to the comment below, the z-value does not have an effect. But I have also a collision detector for the rope, which is a Bezier-curve with an EdgeCollider2D attached to it. When the rope passes the floor, nothing is triggered in onCollisionEnter2D.
void OnCollisionEnter2D(Collision2D collision)
{
bg = GameObject.Find(bg_name);
if (collision.gameObject.tag == "floor")
{
print("floor collision");
bg.GetComponent<ControlGame>().ShootBall();
}
}
Well, these are Collider2D.
You only changed the Z (depth) position of the floor which basically is completely ignored in a 2D game / by 2D physics.
As you can also see in the GameView for the Physics 2D the objects are still aligned and colliding.
Why isn't it also working for collision between rope and floor?
Please checkout the Collision Action Matrix for which collisions/trigger can be detected.
&rightarrow; At least one of the objects has to be a Rigidbody2D.
If the rope is e.g. moved by script then it has to be a Kinematic &rightarrow; in this case also the floor would need to be a Rigidbody2D and not Kinematic.
The reason I guess it worked just fine for the ball is because it already is a non-kinematic Rigidbody2D so able to detect collisions with static colliders.

Collider2D vs Collision2D

After doing some video tutorials on Youtube, I recognized that these two Classes look similar and repetitive.
-Collision2D-
This method called when an incoming collider makes contact with this object's collider (2D physics only)
void OnCollisionEnter2D(Collision2D coll) {
if (coll.gameObject.tag == "Enemy")
coll.gameObject.SendMessage("ApplyDamage", 10);
}
-Collider2D-
This method called when another collider makes contact with this object
void OnTriggerEnter2D(Collider2D other) {
Destroy (other.gameObject);
}
Both methods have same purpose and look the same. What is the difference?
Collision2D contains the info about the collision, while Collider2D is a component of the colliding object.
http://docs.unity3d.com/ScriptReference/Collision2D.html
http://docs.unity3d.com/ScriptReference/Collider2D.html
As you can see, the purpose is similar, but not the same.