I begun the trek into Unity2D development a few months ago, so i'm still fairly new to all the unity engine jargon. In my game, I decided to implement the use of 'Lives'. I scripted out what (in my eyes) should work but every time the player dies instead of decrementing the lives counter and restarting it at the scene, it immediately loads the scene 1 (i.e. the GameOver screen) Is my logic here on this page incorrect or is there just a better way overall to handle lives than PlayerPrefs? (ALSO: Its worth mentioning that the Lives are instantiated/sent to playerprefs in the player script, I don't figure I need to include that one here)
This is the main block of code on my destroyer objects' script to account for 'death':
public static int lives;
void Start()
{
lives = PlayerPrefs.GetInt("lives");
}
void OnTriggerEnter2D(Collider2D other)
{
//If the trigger happens to be tagged as a 'Player', does this.
if (other.tag == "Player")
{
lives--;
if (lives < 0)
{
PlayerPrefs.DeleteAll();
SceneManager.LoadScene(1);
} else
{
SceneManager.LoadScene(0);
PlayerPrefs.SetInt("lives", lives);
}
}
if (other.gameObject.transform.parent)
{
Destroy(other.gameObject.transform.parent.gameObject);
}
else {
Destroy(other.gameObject);
}
}
As I mentinoned in comment, I think you forget to swithOn isTrigger field from Inspector which is under the Collider area.
Probably you thought like you are using onCollisionEnter. Also if you check the differences between OnTriggerEnter and OnCollisionEnter it will be very helpful.
As #Ugur Tufekci answers, But make sure to add BoxCollider2d not Box Collider.The simple box collider is 3d but your are detecting that onTriggerEnter2D that means 2d box collider has to be added
Related
I was creating a multiplayer first-person medieval fighting game based on Skyrim and For Honor combat, with 3 different stances. In it, you can attack from 3 stances, and if the opponent is not holding the same stance, he takes the attack, otherwise he parries and the attacker takes a quick stun.
The problem starts when the Sword's Hitbox hits the player's own hitbox, causing unwanted results.
That's why I want to know if there is a way for making the player's sword ignore the collision with the player itself, so that he can't attack himself.
I also tried to put the method: Physics.IgnoreCollision(collider, selfCollider); Inside the OnTriggerEnter() function, Start() and Update(), and no solution worked.
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "Enemy" || other.gameObject.tag == "Player")
{
//instant enemy combat
CombatManager enemy = other.gameObject.GetComponentInChildren<CombatManager>();
Debug.Log(enemy.currentStance);
//If enemy stance is not the same of the attacker
if(enemy.currentStance != this.currentStance)
{
//enemy is damaged
//Get enemy LifeManager and subtract its health
enemy.GetComponentInParent<LifeManager>().currentHealth -= swordDamage;
}
else
{
anim.SetTrigger("Parried");
}
}
Try:
if(other.transform.root != transform.root)
{
// NOT self collision
}
This basically checks if both objects belong to the same hierarchy. In other words if they have the same top-most GameObject or root.
Obviously I made some presumptions as to how your players avatars are rigged. Perhaps you will need to tweak this solution to suit your hierarchy.
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
}
}
Hi guys I am having a problem in unity with OnTriggerEnter2D.
The player has 2 bullets, any time the player bullet hits the enemy it should increment the score by 100, but for some reason it is incrementing the score by 200 if two player bullets hit the enemy. Both bullets fire at the same time and are at either side of the players gun. So it should only ever increment the score by 100 and not 200.
Here is my code:
void OnTriggerEnter2D(Collider2D col)
{
if(col.tag == "PlayerBullet")
{
this.score += 100;
}
}
Other information:
My player bullet and enemy both have Box Collider and RigidBody2D attached to them. They both have the isTrigger option checked.
If you want it to work just once you can ignore collision after first increment of the score(aka after first collision) like this:
void OnTriggerEnter2D(Collider2D col)
{
if(col.tag == "PlayerBullet")
{
this.score += 100;
Physics2D.IgnoreCollision(col, GetComponent<Collider2D>())
}
}
Note that After this point all collisions between PlayerBullet and Enemy will be ignored.
If I understand it correctly, the player has two guns, and I assume they are fired at the same time.
In this case, we can make it more beautiful with condition-condition statements.
I'm leaving the code block below.
if (Input.GetMouseButtonDown(0) && Input.GetMouseButtonDown(1))
{
Debug.Log("Fire Metod(Score)");
}
else
{
if (Input.GetMouseButtonDown(0))
{
Debug.Log("Fire Metod(Score)");
}
if (Input.GetMouseButtonDown(1))
{
Debug.Log("Fire Metod(Score)");
}
}
Often times you can set a flag to tell the game to only increment once. A flag is just a bool value, and can be private within the scope of the class. Sort of like:
if(canHit)
{
canHit = false;
//add score
canHit = true;
}
That basic formula should get you the results you want.
I'm upgrading my comment to an answer because after reading your question and the comment responses I believe you need a non-code answer.
You want two objects to work together and count as one 'hit' when they collide with another object. That sounds to me like a situation where you should be placing those objects inside another one, let's call it a 'shot' object, and you should be doing collisions and whatnot based on that. That way, if both bullets hit only one 'shot' hit, so it will count with the code as-is and it sounds like it will be implemented more as you've expected it to be.
Right now we work on a Infinity-Runner, and i got this weird bug. After something leaves the Screen it will be catched by a collider that destroys everything. And it works...almost. It will destroy the ground, Background stuff, enemys you jumped over but NOT the newly implemented "roadblocks".
Here is a picture how it looks like, the green placeholder is the roadblock-thingy
http://s4.postimg.org/8uaorv7ot/Bug.png
hope this might help in visualizing what im saying^^.
The Script i use for the Destroyed (the green box collider) is:
void OnTriggerEnter2D(Collider2D other)
{
if (other.tag == "Player")
{
Debug.Log ("Break is gonna happen");
Debug.Break();
}
else if (other.gameObject.transform.parent)
{
Destroy(other.gameObject.transform.parent.gameObject);
}
else
{
Destroy(other.gameObject);
}
}
and this is the script for the roadblocks:
void OnCollisionEnter2D(Collision2D other)
{
if(other.gameObject.tag == "Player")
{
Debug.Break ();
}
}
so basically nothing that would ever disrupt the DestroyerScript. Its even far more simple than the script on the enemys...but they get destroyed.
Thanks in advance for your help, i can provide more information if need.
(ohh, and all the art in this pic is placeholderstuff^^)
You can try to use OnTriggerExit2D to trigger when your player leave the collider. And makesure you added a suitable collider2d to your sprite before
http://docs.unity3d.com/ScriptReference/Collider2D.OnTriggerExit2D.html
I'm not use it before but I think it might works
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.