Is there a way to make a hitbox ignore another one? - c#

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.

Related

Unity get the trigger that has caused a OnCollision... event

I'm trying to make a player controller that jumps only when a specified in a property Collider collides with anything. For now, I can detect when a collision has occurred, but can't detect which are the two bodies that have collided. Does the event trigger only when one of the colliding bodies is the one that the script is applied to. If so, how can I handle events on behalf of other objects (or even better, detect global collisions)
Here is my player controller hierarchy:
Capsule
|
+- Camera
|
+- Floor Collider
P. s.: Sorry for the question's short length
Let me see if i got your question, you want to detect when the player is touching the floor so that it can only jump when on the floor. Is this right?
The floor has a Collider as well right? Add a tag on the floor object so that we can identify who is the Collider.
And then on the Player Controller do something like:
void OnCollisionEnter(Collision other)
{
if(other.gameObject.tag == "floor")
{
allowJump = true;
}
}
And the opposite so that we know that the player can't jump
void OnCollisionExit(Collision other)
{
if(other.gameObject.tag == "floor")
{
allowJump = false;
}
}

Lives Implementation in Unity2D

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

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

Collision not getting detected in unity3d

I am making a 2D game. I have 2 game objects, a player, and some obstacles and I want the player object to be destroyed on collision. I have added box colliders to both the objects as well as tags but the collision is not taking place as there are no log messages in the console.
void OnCollisionEnter2D (Collision2D col)
{
Debug.Log("collision name = " + col.gameObject.name);
if (col.gameObject.tag == "cow") {
Destroy(gameObject);
}
}
As we discussed in comments:
Add Rigidbody2D component to at least one of colliding objects.

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