How do I detect if a sprite is touching another sprite - c#

How do I determine if a sprite (Sprite1) if on top of (Sprite2)
I need this to switch levels when you touch another sprite with your sprite.
I tried:
void OnCollisionEnter2D(Collision2D other)
{
//code to run
}
But this made it so that everything it touched ran the code. :(

You should attach the script that contains oncollisioneneter to your sprite1 game object for example and in your sprite 2 game object add a tag like sp2 or whatever you want , then in your script when collision happens you check if the object that sprite one collided with is sprite 2 you check it with tag property of sprite 2 like this
void OnCollisionEnter2D(Collision2D other)
{
if(other.gameObject.tag == "sp2")
{
//put your change levelcode here
}
}

Your halfway there. Right now you are running the code whenever the sprite collides with another 2D collider. What you then need to do is determine if that collider is the one attached to the particular sprite we want to trigger the code.
Tag the object containing your level exit, and check for the tag when you get a hit.
void OnCollisionEnter2D(Collision2D other)
{
if(other.gameObject.tag == "levelExit")
{
Debug.Log("next level");
}
}

Related

Unity-2d: Why are two trigger colliders interacting?

I thought that trigger colliders were not meant to interact with each other, I have the following game object:
(The "AttackArea Game Object is a child of a "Player" Game Object)You can see I set it to be a trigger, the script "Attacks" only has the following code:
public int attackStrength;
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.GetComponent<Health>() != null && collision.CompareTag("Enemy"))
{
Debug.Log("touched: " + collision.name);
Health health = collision.GetComponent<Health>();
health.ReduceHealthPoints(attackStrength);
}
}
The OnTriggerEnter2D method is getting called when this Polygon collider touches a Circle collider also set as a trigger:
Not sure why the two trigger colliders are interacting at all, I thought that wasn't possible.
These are the RigidBody settings on the game object that has the Polygon Collider 2D (it's parent):
With the isTrigger property set to true, the collider will not collide, but it will send trigger events.
If you do not want to interact with certain game objects you can add tags to the relevant game objects and compare the tags.
For example:
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.CompareTag("CircleCollider")) return;
}

How to hit an uncollidable (invisible) object

So, i have a Player and a End object. The End has no Mesh renderer, but it has a Box Collider with a Slippary. So its invisible in the game, i tagged it with "End" and write this Script (in the Player).
private void OnCollisionEnter(Collision collision)
{
if (collision.collider.tag == "End")
{
Time.timeScale = 0f;
}
}
But when i hit the invisible object called End, the Player goes ahead. I want to fix this problem because my Player moves on when i finish the game and the coordinates influence the reached points. So it has really to stop (the Playermovement is anytime activated)

Detecting collisions between two separate animations

My animations enters a state and it's collision with enemy projectiles either defends himself or gets hurt depending on what animation he is currently in. I'm trying to detect collisions with the ONTRIGGERENTER function and boxcollider2D's but it's not having any affect. I want to figure out how to correctly facilitate trigger enters and collisions between these animations.
I've already tried giving my sprite a tag and calling that tag when the ONTRIGGERENTER function is called but it didn't work. I also tried a more complicated way of calling the tag of the collider but that didn't work either. How do you access the trigger when it's an animation?
string DefenceAnimTag = "Defending";
string DestroyEnemTag = "Eliminated";
//This code is connected to the enemy projectile and trying to
//sense when it's collided with the player
void OnTriggerEnter(Collider2D col)
{
if (col.tag == Defending)
{
GetComponent<Animator>().SetBool("Elim", true);
}
else { //deal damage to the player }
}
//The first method didn't work so I tried a second method.
//Here is an alternative attempt at detecting triggers in
//animations.
void OnCollisionStay2D(Collider2D col)
{
if (col.gameobject.CompareString("Defending"))
{
GetComponent<Animator>().SetBool("Elim", true);
}
}
//This method didn't work either even though the Animation
//WOULD be Defending
I expected enemy projectiles to collide with my player when he was defending himself and get defeated. I knew that it was working when the Enemy projectiles transition into their Elim state, where they get defeated by enemy defenses, however they made collisions and then continued unaffected.
Okay, okay, I figured it out. Because a Gameobject can have many animations to it, you cannot go by the tag that the GameObject in the inspector has. You have to go by the title of the Animations that is currently playing. In order to access the animation currently playing we must use the following code:
AnimatorClipInfo[] m_AnimClipInf;
string m_ClipName;
void Start()
{
//Set up our projectile for possible Elimination
//upon Collision
Getcomponent<Animator>().SetBool("Elim", false);
}
void OnTriggerEnter2D(Collider2D col)
{
m_AnimClipInf = col.GetComponent<Animator>
().GetCurrentAnimatorClipInfo(0);
m_ClipName = m_AnimClipInf[0].clip.name;
if (m_ClipName == "Defending")
{
GetComonent<Animator>().SetBool("Elim", true);
//Projectile gets eliminated
}
}

How to check collision between the player and a specific TileBase object in Unity?

I have a couple of tilebase variables that are set using the unity inspector:
public TileBase obstacle; //obstacle tile
public TileBase spikes; //instant death tile
I'm using OnCollisionEnter2D in a script that is set to the tilemap asset.
void OnCollisionEnter2D(Collision2D col)
{
if (col.gameObject.name == "Player")
{
PlayerPrefs.SetInt("Collision", 1);
}
}
I want to be able to detect when the player has collided with the spikes TileBase as that should trigger a game over. The asset name that is set to the spikes variable through the inspector is also called Spikes or Spikes (Tile) in the palette.
I tried using adding collision detection to a script that is used on the player asset to check what objects it collides with
void OnCollisionEnter2D(Collision2D col)
{
Debug.Log(col.gameObject.name);
}
But all it comes back with is the name of the tilemap.
First you should add Layers to your objects. An easy example is to add a "TileBase" or "Tile" Layer to your TileBase objects.
You can then allow your Player to only collide with certain things and NOT your tilemap. See the collision matrix for this.
Then alter your code like this:
void OnCollisionEnter2D(Collision2D col)
{
var tilebase = col.GetComponent<TileBase>();
if (tilebase != null)
{
Debug.Log(tilebase.gameObject.name);
}
}

Identify a selected enemy prefab to play death particle system

I am trying to play a particle effect when an enemy is killed but it seems to play on a randomly selected one rather than the one that was hit. However the enemy that was hit still disappears and still add points to the score.
At the moment I have three scripts to carry this out (All have been shortened so I'm only showing the relevant code):
One which is attached to boxes that are thrown at enemies that detects if they have collided with an enemy prefab.
void OnCollisionEnter (Collision theCollision) {
if (canProjectileKill == true) {
// If the projectile hits any game object with the tag "Enemy" or "EnemyContainer".
if (theCollision.gameObject.tag == "Enemy") {
GameObject.Find("EnemyExplosion").GetComponent<enemyDeath>().ProjectileHasHitEnemy();
// Destroy the projectile itself.
Destroy (gameObject);
// Destroy the game object that the projectile has collided with (E.g. the enemy).
Destroy (theCollision.gameObject);
GameObject.Find("Manager").GetComponent<projectileSpawner>().deleteProjectile();
}
}
}
Another that is attached to the enemy prefabs which detects if they have been hit by a box.
void OnCollisionEnter (Collision theCollision) {
if(theCollision.gameObject.tag == "Projectile") {
GameObject.Find("EnemyExplosion").GetComponent<enemyDeath>().EnemyHasBeenHit();
}
}
I then run an if statement asking if both the box has hit the enemy prefab AND if the enemy prefab has been hit by the box in an attempt to identify a single prefab rather than all of them. However this still doesn't work.
public bool HasProjectileHitEnemy;
public bool HasEnemyBeenHitByProjectile;
void Start () {
gameObject.particleSystem.Stop();
HasProjectileHitEnemy = false;
HasEnemyBeenHitByProjectile = false;
}
public void ProjectileHasHitEnemy () {
// From projectile.
HasProjectileHitEnemy = true;
}
public void EnemyHasBeenHit () {
// From enemy.
HasEnemyBeenHitByProjectile = true;
PlayParticleSystem();
}
public void PlayParticleSystem () {
if (HasEnemyBeenHitByProjectile == true && HasProjectileHitEnemy == true) {
gameObject.particleSystem.Play();
HasProjectileHitEnemy = false;
HasEnemyBeenHitByProjectile = false;
}
}
}
I am aware this is a long question but I have been stuck on this for over a week, so any help would be much appreciated. Thank you :)
I'm not sure what kind of object EnemyExplosion is, but your problem seems to be the search for this object. During OnCollisionEnter you know exactly between which objects the collision occurred. But now you're starting a search for any object that is called EnemyExplosion. That's the reason your particles appear random.
Update:
Ok, with your structure something like that
EnemyContainer
- EnemyExplosion
- Particle System
- EnemyModel
- Collider
If EnemyModel contains the collider, you can get to EnemyExplosion and finally enemyDeath the following way.
var explosion = theCollision.transform.parent.gameObject.GetComponent<EnemyExplosion>();
explosion.GetComponent<enemyDeath>().ProjectileHasHitEnemy();
Now that you're accessing the correct object, you can remove some of your double checks and rely on one collider event.
I seem to have found a way around this. Instead I've just set it to instantiate the particle system whenever an enemy detects that it has collided with a projectile. I then use a Coroutine to delete the particle system 2 seconds after.

Categories