What I am trying to accomplish now is making an object rotate so that it’s specified axis is parallel to the axis of an empty object used as a reference when a projectile collides with it. Here is what I have so far and already have a problem.
// object to rotate on collision
var myOb : Transform;
// empty reference object to rotate towards
var refOb : Transform;
function OnCollisionEnter(collision : Collision){
// axis of empty ref object to rotate towards
var targetDir = refOb.up;
//axis of object I want to rotate
var upUs = myOb.up;
// get the angle between those two axis
var angle = Vector3.Angle(targetDir, upUs);
// print angle
Debug.Log(angle);
// rotate myOb until the angle between myOb and refOb is close to zero
if(angle>1){
myOb.Rotate(Vector3.right*60*Time.deltaTime);
Debug.Log(angle);
}
}
When it is left as is it gives me the correct behavior, but it just rotates the object a small amount as expected. It does not rotate until the axes are parallel. But this proves that the rotating stuff works fine.
The problem is that I want to change that “if” statement to a “while” so it roatates until the angle between them is zero or close to that. I need this because I want to destroy the projectile after colliding as well.
However,when I change it to a “while”, unity freezes which I am assuming means it get’s hung up in that loop because angle never updates?
If I change the function to oncollisionstay and use “if” it gives me the desired affect, but this prohibits me from destroying the projectile on impact.
So what is wrong? Why, when I change it to a “while” does it freeze? Any help or insight would be great.
Thanks,
Justin
Angle is never updated and is always >1, thus creating an infinite loop. Unity dislikes these and crashes rather than hangs.
If you change “if” to “while”, the expected behaviour would be an instant snap to the target rotation. If you want an instant snap, it’s 100x better to just calculate the target rotation and set it.
If you want a slow movement, you’ll want to run a coroutine like:
Thank you thank you thank you thank you thank you. This is exactly what I needed.
So it was just declaring what angle was again in the loop that made the difference?
Also what is the yield at the end for? I looked at the Unity Script Reference but could not find anything on it except when followed by something like WaitForSeconds();
I see you commented that it waited one frame? What is the need for that? I commented it out to see what would happen and of course it didn’t work right. So it is clearly useful.
Sorry for all of the questions. Especially after you have been so much help. I am just too new to this stuff and need all the help I can get!
Unity can never escape this loop, since there’s no way for angle to change once the loop is entered.
yield; causes Unity to exit the current function and then, on the next update (not sure exactly when that is relative to Update/LateUpdate/whatever), to resume running that function. Without it, the function will run
while (a>1) {
do1;
a=x;
}
until a <= 1, all in one frame, effectively snap-rotating the object.
Questions are good! They make thinking happen and then good code and then everyone is happy.