- Home /
 
Door script going crazy on certain angles
Okay, so I looked at an online tutorial to figure out how to make a door open on a button press. I got it to work and used it on one door, so I went and tried it on another... And there were issues.
The door facing forward works fine. The door on the side flips out ever time I interact with it. I've been messing with the code and changing a few things, but everything I do seems to make it even worse. I'm not entirely sure, but I think it has to do with the use of transform.eulerAngles in the code.
I did a short screen recording to illustrate my problem. The door on the left goes crazy when I try to interact with it. http://cl.ly/190h2l2f433l
Here's the code I have for the Door Opening script that controls how the door moves.. I understand how it works but I have no idea how to fix it.
 var smooth = 2.0;
 var DoorOpenAngle = 90.0;
 private var open : boolean;
 private var enter : boolean;
 
 private var defaultRot : Vector3;
 private var openRot : Vector3;
 
 public var GUI_X = Screen.width/2 - 75;
 public var GUI_Y = Screen.height - 100;
 
 function Start(){
 defaultRot = transform.eulerAngles;
 openRot = new Vector3 (defaultRot.x, defaultRot.y + DoorOpenAngle, defaultRot.z);
 }
 
 //Main function
 function Update (){
 if(open){
 //Open door
 transform.eulerAngles = Vector3.Slerp(transform.eulerAngles, openRot, Time.deltaTime * smooth);
 }else{
 //Close door
 transform.eulerAngles = Vector3.Slerp(transform.eulerAngles, defaultRot, Time.deltaTime * smooth);
 }
 
 if(Input.GetKeyDown(KeyCode.E) && enter){
 open = !open;
 }}
 
              Answer by robertbu · Oct 03, 2013 at 06:33 AM
After a brief look, I too suspect eulerAngles is the issue as well. Vector3.Lerp() and Vector3.Slerp() are very literal functions. Imagine that your door has a closed position of 335 degrees, and a open position that passes across the 360/0 boundry to 60 degrees. If you use those two angles, Lerp()/Slerp() will not take into account the 360/0 boundary and instead rotate the long way from 360 down to 60.
The simplest fix for this problem is to make defaultRot and openRot public, remove the initialization of these variables in Start(), and specify the angles in the inspector. That way you can pick values that make Lerp()/Slerp() do exactly what you want. In the 335/60 case above, you could specify 335 and 395 instead.
Another fix would be to rewrite your script using Quaternions instead of Vector3. Quaternions are lazy. Rotations using Quaternion.Slerp() and Quaternion.Lerp() always take the shortest distance between the start and end rotation and don't have any 360/0 boundary issues.
Interesting. I'm tired right now, but I'll look at this in the morning and see if this makes sense.
I just found a very odd fix a few $$anonymous$$utes ago. A comment I found suggested that flipping the Rotate Y of the empty game object attached that is placed on the hinge 180 degrees stops it from flipping out. I redid the process with a flipped empty game object and... Somehow it works. Each door now opens normally, the way I want it. I have no idea why it works... @_@
One problem with eulerAngles is that internally they are stored as Quaternions. When you read them back, they are not necessarily what you put in or what you expect. For example, put these two lines in a script:
 transform.eulerAngles = Vector3(180,0,0);
 Debug.Log(transform.eulerAngles);
 
                  It outputs (0,180,180)...the same physical rotation in a different format. This messes up a lot of code that reads eulerAngles. Your code directly reads eulerAngles on line 13 and indirectly in the Slerp() code. So flipping your door may fix things just because it picks a range of eulerAngles that does not change representation.
The more I think about it, since you are reading eulerAngles, the fix I suggested will not work. What you need to do (assu$$anonymous$$g you want to take on the task now that you have your code working), is to maintain your own Vector3 and only use it for assignments. So a piece of your code might look like:
 myRotation = Vector3.Slerp(myRotation, openRot, Time.deltaTime * smooth);
 ttransform.eulerAngles = myRotation;
 
                 Answer by sethuraj · Oct 03, 2013 at 08:30 AM
If you are using euler angles,it should be normalized example - StartRot=315,EndRot=StartRot+90=315+90=405 is not between 0 to 360. Also Slerp(A,B,Time) will lerp from A to B never do B to A. If we do normalizing,StarRot=315 EndRot=405 EndRotNormalized=45 Slerp(StarRot,EndRotNormalized,time) will lerp but in counter clockwise.
This is the explanation for the problem....
Now for overcoming this you can use Quaternion instead of Euler angles
//SOLVED CODE
 var smooth = 2.0;
 var DoorOpenAngle = 90.0;
 
 private var open : boolean;
  
 private var defaultRot : Quaternion;
 private var openRot : Quaternion; 
 private var enter : boolean;
  
 function Start()
 {
     defaultRot = transform.rotation;
         
     openRot = defaultRot;
     openRot=Quaternion.AngleAxis(openRot.eulerAngles.y+DoorOpenAngle,Vector3.up);
 
 }
  
 //Main function
 function Update ()
 {
     if(open)
     {
         //Open door
         transform.rotation = Quaternion.Slerp(transform.rotation, openRot, Time.deltaTime * smooth);
     }
     else
     {
         //Close door
         transform.rotation = Quaternion.Slerp(transform.rotation, defaultRot,  Time.deltaTime * smooth);
     }
  
     if(Input.GetKeyDown(KeyCode.E) && enter)
     {
         open = !open;
     }
 }
 
               Hope this helps.......
Thanks man, this helped a ton, was stuck on a rotation problem for a hour :)
Your answer
 
             Follow this Question
Related Questions
Limiting rotation based on direction 0 Answers
Make object only rotate in 90 degree increments 1 Answer
Clamped Rotate 3D Object on Y and Z axis only with OnMouseDrag() 2 Answers
How to get rigidbody local z axis rotation in Euler angles? 0 Answers
How can I limit the player's camera to move to the edge of the map centering it on the camera? 0 Answers