- Home /
OnTriggerEnter function giving mixed results
I have an on trigger enter function for my projectile class. The class iss very simple. It is created when the player uses an ability and has information (such as the target) passed to it from the ability class. It then tracks towards the target and eventually collided with the target. I call the OnTriggerEnter() function and use the following code:
void OnTriggerEnter(Collider other)
{
Debug.Log("collision");
other.gameObject.GetComponent<Enemy>().TakeDamage(_damageOnHit);
Destroy(gameObject);
}
It calls the working function in the enemy class TakeDamage() that applies the damage worked out when casting the ability taking into account modifiers and such.
This works and I see the health of the target deplete... However this only works some of the time. When I first finished creating the code it appeared to always work until I changed the enemies game object to make it look like a cube instead of an elongated sphere. When I did this the collision would only happen some of the time (and the debug message would only appear some of the time. The rest of the time the projectile flies from one side of the enemy, recalculates its direction and the goes flying back towards it again until it is destroyed not there is not collision registered for any of the many obvious collisions.
I get one error message: "NullReferenceException: Object reference not set to an instance of an object Tracking.OnTriggerEnter (UnityEngine.Collider other) (at Assets/MyAssets/Scripts/Abilities/Tracking.cs:45)"
However I know for a fact the enemy script does exist as I can see it and its variables in the inspector at run time.
[UPDATE] I solved the problem at the following link: http://answers.unity3d.com/questions/173916/ontriggerenter-doesnt-work-if-the-colliding-object.html
Could it be that your projectile is moving so fast that in one frame it goes straight past the enemy and therefore the collision is never detected?
No for several reasons:
1) Its not travelling fast enough 2) That wouldn't cause an error 3) The OnTriggerEnter() function is being entered but causes an error therefore it is registering collision
But that is a problem I have experienced in the past :)
Answer by aldonaletto · Dec 07, 2012 at 11:05 AM
Based on the error message, I suspect that something without the script Enemy is being hit by the projectile. Have you childed some object to the enemy? If you child a weapon to the enemy, for instance, and this weapon have a collider, the projectile can hit the weapon collider instead of the enemy and cause this error - the code will try to call TakeDamage in the Enemy script, but this script is attached to the character, not to the weapon.
A possible solution: call TakeDamage via SendMessageUpwards - this way any collider childed to the enemy will broadcast the message to it:
void OnTriggerEnter(Collider other)
{
Debug.Log("collision");
other.SendMessageUpwards("TakeDamage", _damageOnHit, SendMessageOptions.DontRequireReceiver);
Destroy(gameObject);
}
This code will try to call the function TakeDamage in any script attached to the object hit or to any other object above it in the hierarchy.
Although a little slower than the GetComponent version, SendMessage has some advantages: you can apply the damage to any object you want - just add a TakeDamage function to its script. This is used in the FPS Tutorial to apply damage to the robots, to the enemy turrets, fuel barrels, etc.
Anyway, you can modify your current code to avoid errors and produce more info about what was actually hit:
void OnTriggerEnter(Collider other)
{
Debug.Log("collided with " + other.name); // show what was hit
Enemy enScript = other.GetComponent<Enemy>; // try to get the script
if (enScript){ // if script found apply damage:
enScript.TakeDamage(_damageOnHit);
}
Destroy(gameObject);
}
I don't think that is the problem although the information about Send$$anonymous$$essage is very interesting. You can use it to call functions contained in parent classes?
I think I have found the reason. I didn't mention before that I set the rigid body of the enemy to ignore gravity because the sphere that was rolling around was annoying me. When I use gravity again the problem is solved? Not sure why this would make any difference though.
On a side note is it possible for the spell to hit the player if the enemy is close enough and if so it wouldn't cause the error but would probably damage the player.
Gravity doesn't have anything to do with your problem. The symptom makes me think that your trigger is colliding with other objects (that, consequently, does not have the "Enemy" script attached). Try to put a Debug.Log(other.name); to see if it's triggering correctly.
Well the problem still happens when the gravity is off yet I have the following guards:
if (other.CompareTag("Enemy"))
{
other.gameObject.GetComponent().TakeDamage(_damageOnHit);
Destroy(gameObject);
}
This means it will only collide with gameObjects tagged with "Enemy"
That should solve the problem (just don't forget to put the component name in GetComponent function).
Send$$anonymous$$essage and family (Send$$anonymous$$essageUpwards and Broadcast$$anonymous$$essage) are used to call functions by name in this object (if without prefix) or in any other (if prefixed by a reference to the object or to one of its components). Send$$anonymous$$essageUpwards searches the scripts in objects towards the top of the hierarchy, thus you can call a function in the parent object.
Gravity definitely has nothing to do with this problem - it looks like another object being hit ins$$anonymous$$d of the one you expect. By the way, you've said "I call the OnTriggerEnter function..." - are you really calling OnTriggerEnter? This is an event handling function, and it's not supposed to be called directly - the collision system call it when a collider enters the trigger.
Your answer
Follow this Question
Related Questions
Collision problem in C# 4 Answers
How can I detect a collision between two clones and delete them both? 1 Answer
Multiple collisions not working.Plz help 0 Answers
Shooting myself 0 Answers
Destroying object on collision 3 Answers