- Home /
Odd collision behaviour with If/while statement
//That boring intro
Hi I have a bit of a problem with a script,
I have a cannon that fires 20 bullets per second, for a second and then stops. I've tested this with different amounts of rounds per second ranging from 1, to 2, up to 120 and I'm getting some weird behaviour from an if/while statement:
var health : int;
function OnCollisionEnter(col : Collision) {
//print (col.gameObject);
var primaryGun = gameObject.Find("bullet(Clone)");
while (col.gameObject == primaryGun) {
var instance = col.gameObject.GetComponent(impact);
var damage : int = instance.primaryBulletDamage;
//print (damage);
health = health - damage;
print (health);
yield;
}
if (health <= 0) {
print ("I'm Dead");
}
}
//The reason you hate me
The reason I'm using an if/while type statement is because I want to create different bullet types which are essentially duplicate prefabs with some additional style changes and the parameters are different including damage, hence why the script is asking what hit it for the damage int from the collision object.
//The actual problem
When I use the first print, outside of the while statement, without it's comment: print (col.gameObject); the correct amount of collisions is printed to the console per bullet fired. However in my While loop it repeats the print function multiple times. I think this is something to do with the game refreshing each frame producing all the console prints. Without the yield; the script crashes unity/the game, also, adding WaitForSeconds(0.1); helps but it's inaccurate and sometimes still throws a good 10 prints or so for each 1 collision.
I've tried the If statement instead of while however this has the reverse effect, it only registers 1 hit per few seconds. In order for the hit to count I have to fire, wait for my original bullet(Clone) to destroy itself then it will count the next hit.
Furthermore, my final error is that, "The object of type 'BoxCollider' has been destroyed but you are still trying to access it."
I know this is to do with the bullet destroying script that deletes the clones over time. However I don't know how to get rid of this error, the log hints at telling the script to check for null.
//The afterword
I hope there is someone who can help me understand better why this is happening and if there is a fix and what it might be (: also, sorry for my poor sense of humour at this time in the morning with all the cheesy //comments...
Thanks for reading -Axi5.
EDIT: I just retried the first print as I mentioned earlier in this post and even though it gave 1-2 prints per 1 bullet (1 bullet sometimes counting as two or rarely, more collisions) it still didn't give nearly as many prints as while and yet it was still more than if. So I still consider this question valid despite my original test being a little off (I'll play with the collision boxes setup and see if it improves things).
Answer by whydoidoit · Apr 13, 2013 at 06:29 AM
So you've made OnCollisionEnter a coroutine and every time you hit the primary gun the coroutine starts and keeps running forever. I think you've not quite got how coroutines, as response function, work - you can actually have that same routine running multiple times (every time you hit the primary gun it starts again).
The idea of a coroutine in this circumstance would be to do something over a period of time, like play an animation, show and explosion then respawn etc.
I think you actually need to use OnCollisionStay and an if rather than a while statement to continue to do something every frame the collision is maintained.
hmm I'm not quite sure if I've misunderstood you, or you me, but as some more information:
the print doesn't show forever it seems to show for a few tens per hit, for instance one bullet would create about 20 prints (estimate dfigure), so a few more rounds into the cube and there's a few hundred prints. I'm almost completely new to unity script, but if OnCollisionStay were to be used as you said, that would make it continue forever right?
The problem I'm trying to counteract is the script doing something each frame the collision is maintained. This is where I'm a little sketchy in my knowledge. OnCollisionEnter printing outside of the while statement seems to produce the correct/accurate number of collisions which is what I want. Whereas introducing the "while" seems to continually post for each frame the collision is maintained, like OnCollisionStay.
However "if" only works with one version of my bullet(Clone) active in the scene, which means if a second bullet(Clone) hits the cube while the first bullet(Clone) exists then it wont print.
What I'm trying to do is make the cube know which type of bullet hit it e.g. bulletCloneA, with a damage of 25, bulletCloneB with a damage of 10. So I can do the mathematical calculation to work out when to "kill" the cube. That's where my if statement came in, my plan was to add as many if statements as there are types of bullet so the cube would identify how much damage to subtract from the health. I will probably edit this into my question.
Thanks for the reply though you did get a decent handle on what I said (which to me, my question is starting to seem like a ramble).
Well it will continue running "forever", but that really means until the object that that its running on is Destroyed, disabled or made inactive. It isn't like OnCollisionStay and it doesn't stop when the collision exits (it wouldn't be much use for its primary purpose if it did).
This should do it:
var health : int;
function OnCollisionEnter(col : Collision) {
var impact = col.gameObject.GetComponent(impact);
if(impact)
{
health -= impact.primaryBulletDamage;
if(health <= 0)
print("I'm Dead");
}
}
In your current code the while will never exit and the if won't print until such a time as the bullet is destroyed (at which time it will return null and fail the while condition).
BTW OnCollisionStay would continue to be called while the collision continued - i.e. while you are standing on something etc.
2 words, that's brilliant. Sorry for putting up with my working all night and it's 7am mood! That's truly put life back into my moral for this project. I had a funny feeling that I had misunderstood, so I'm going to have to revise this on a fresh $$anonymous$$d.
Ah that's what OnCollisionStay is used for, tonight was my first time tackling collisions so hearing your explanations has really helped.
Thank you so much for the help :)