Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by AlucardJay · Mar 21, 2012 at 05:37 PM · raycastterrainquaterniongimbal-lockdelta

why am I getting a flipped-out effect from my transform.rotate

I have a hoverboard that adjusts it's angle depending on the terrain below it. Every so often the board jerks to a strange angle for a moment. My only guess on why is that the raycasts are hitting joining faces of the terrain , And the only solution I can see is somehow logging the last change in angle, if it is an extraordinary leap , then don't transform.rotate What is happening, and what should I do / be looking at ? thanks.

  • Edit - the problem actually seems to be a Gimbal Lock.

  • SOLVED with a completely different approach . see answers.

Sample script :

 // -- X ANGLE calculations
     // vectorBoardLeft
     if (Physics.Raycast((transform.position + Vector3((widthRaycastX / 2), 0, 0)), Vector3.down, rayHit)) {
         vectorBoardLeft = rayHit.point;
     }
     // vectorBoardRight
     if (Physics.Raycast((transform.position - Vector3((widthRaycastX / 2), 0, 0)), Vector3.down, rayHit)) {
         vectorBoardRight = rayHit.point;
     }
     // calculate X angle
     differenceYX = vectorBoardLeft.y - vectorBoardRight.y;
     angleBoardXtan = differenceYX / widthRaycastX;
     angleBoardRotZ = Mathf.Rad2Deg*Mathf.Atan(angleBoardXtan);
     
     // -- rotate board to align to terrain (Z angle is on the X-axis, and vice verca)
     transform.rotation = Quaternion.Euler (angleBoardRotX, 0, angleBoardRotZ);

webplayer publish : http://www.alucardj.net16.net/unityquestions/hoverboard%201-1b.html

full script : http://www.alucardj.net16.net/unityquestions/ScriptHoverBoard2.js

  • I have just changed the Title of this post as the problem seems to be as described by Kryptos below (thanks for the pointer).

  • I have just changed the Title of this post as I have inadvertently stirred controversy , and created a conversation that is off-topic . Very sorry to all involved :)

Comment
Add comment · Show 9
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image AlucardJay · Mar 21, 2012 at 05:53 PM 0
Share

after watching the publish for a few $$anonymous$$utes I notice the huge angle leap occurs around when transform.rotation.x is approximately 0 (zero) . So maybe the problem is the rotation angle (number value) rather than the raycast ? I tried to put a limiter in for near absolute zero in , but it didn't work .

 if ((angleBoardRotX < 0.000001)&&(angleBoardRotX > -0.000001)) {angleBoardRotX = 0;}

 if ((angleBoardRotZ < 0.000001)&&(angleBoardRotZ > -0.000001)) {angleBoardRotZ = 0;}
avatar image Jason B · Mar 21, 2012 at 06:17 PM 0
Share

You're not multiplying your rotation by Time.deltaTime, so essentially you're letting the object rotate as fast as the frames can be rendered. Not only are you getting a weird angle, but because there's no real speed limit, it's trying to reach that weird angle REALLY fast. If multiplying your rotation by Time.deltaTime doesn't help, you still need some sort of rotation limiter (if conditions stating that it can only rotate if it's not already past certain axial limits).

avatar image AlucardJay · Mar 21, 2012 at 06:30 PM 0
Share

thanks for the reply . I don't understand where to add the Time.deltaTime , as it Is a 'snap to' (transform.rotation) rather than a slerp (which I don't understand either! http://answers.unity3d.com/questions/230010/rotating-to-the-current-facing-position.html )

$$anonymous$$ultiplying the transform.rotation = Quaternion.Euler would just give weird angles in itself. .. and I am now more convinced that the problem is occuring when the rotation.x is reaching absolute zero (from + or - degrees).

avatar image Kryptos · Mar 21, 2012 at 07:04 PM 0
Share

You should never set rotation using euler angles. Otherwise you can reach a narrow case called 'gimbal lock'.

If you want to change the rotation, you should consider calculating a delta rotation and addindg this delta to the current rotation (by combining quaternions).

avatar image AlucardJay · Mar 21, 2012 at 07:08 PM 0
Share

thankyou , I think you are correct about gimbal lock but I have no idea how to start learning about calculating a delta rotation.

this is part of a bigger project. I wanted to rotate the gameObject (Player) with this method, and move the Player (including the Y-axis) with the following player input methods :

$$anonymous$$oving : http://answers.unity3d.com/questions/230008/capping-the-speed-of-a-rigidbody.html

and Rotating : http://answers.unity3d.com/questions/230010/rotating-to-the-current-facing-position.html

Show more comments

2 Replies

· Add your reply
  • Sort: 
avatar image
2
Best Answer

Answer by aldonaletto · Mar 22, 2012 at 04:10 AM

The easiest way is to align the character to the terrain normal, like @Dakwamine suggested - but smoothly, or it will shake a lot.
The script below keeps the alignment relative to the ground. It doesn't take care of movement or gravity, what I suppose you're doing in another script.

private var curNormal: Vector3 = Vector3.up; // smoothed terrain normal private var iniRot: Quaternion; // initial rotation

function Start(){ iniRot = transform.rotation; }

function Update(){ var hit:RaycastHit; if (Physics.Raycast(transform.position, -curNormal, hit)){ // curNormal smoothly follow the terrain normal: curNormal = Vector3.Lerp(curNormal, hit.normal, 4*Time.deltaTime); // calculate rotation to follow curNormal: var rot = Quaternion.FromToRotation(Vector3.up, curNormal); // combine with the initial rotation: transform.rotation = rot * iniRot; } } I answered a question some time ago where a complete CharacterController movement, gravity and terrain alignment were provided by a single script (in C# - click here to see it).

Comment
Add comment · Show 6 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image AlucardJay · Mar 22, 2012 at 04:28 AM 0
Share

Thanks, am reading up now. Yes, this is part of a bigger project. I wanted to rotate the gameObject (Player) with this method, and move the Player (including the Y-axis) with the following Player Input methods :

$$anonymous$$oving : http://answers.unity3d.com/questions/230008/capping-the-speed-of-a-rigidbody.html

and Rotating : http://answers.unity3d.com/questions/230010/rotating-to-the-current-facing-position.html

I have previously searched and seen your post on 'Orient vehicle to ground normal' , but as it was in C# I didn't try very hard to understand the steps taken. I have enough trouble understanding the commands and classes of UnityScript! (is it java, javascript?). I shall read the other question, break down what the steps are, thx.

avatar image AlucardJay · Mar 22, 2012 at 04:55 AM 0
Share

I'm having some trouble converting your script. Although I think your vars curDir and turn are what i need for the $$anonymous$$oveRotation in this : http://answers.unity3d.com/questions/230010/rotating-to-the-current-facing-position.html .

This is what I have converted so far, basically my stuck points are the command controller.isGrounded/$$anonymous$$ove , out hit on the raycast ; and % (which remembering from AS2 is the remainder after evenly dividing number by X[360]) ;

converted script so far :

 var curDir : float = 0.0;
 var vertSpeed  : float = 0.0;
 var curNormal : Vector3 =  Vector3.up;
 
 var turn : float;
 var movDir : Vector3;
 
 
 function Update () 
 {
     turn = Input.GetAxis("Horizontal") * turnSpeed * 100 * Time.deltaTime;    
     curDir = (curDir + turn) % 360; // rotate angle modulo 360 according to input //- [ % is ? ]    
     var hit : RaycastHit;
 
     if (Physics.Raycast(transform.position, -curNormal, out hit)) //- [ out hit ? ]
     {
         curNormal = Vector3.Lerp(curNormal, hit.normal, 4 * Time.deltaTime);
         var grndTilt : Quaternion  = Quaternion.FromToRotation(Vector3.up, curNormal);
         transform.rotation = grndTilt * Quaternion.Euler(0, curDir, 0);
     }
 
     movDir = transform.forward * Input.GetAxis("Vertical") * speed;
 
     // moves the character in horizontal direction (gravity changed!)
     if (controller.isGrounded) {vertSpeed = 0;} // zero v speed when grounded //- [ controller.isGrounded ]
 
     vertSpeed -= 9.8f * Time.deltaTime; // apply gravity
     movDir.y = vertSpeed; // keep the current vert speed
 
     controller.$$anonymous$$ove(movDir*Time.deltaTime); //- [ controller.$$anonymous$$ove ? ]
 }
avatar image AlucardJay · Mar 22, 2012 at 05:50 AM 0
Share

I am silly sometimes, was so engrossed in your C# answer on the other questions' page, I didn't notice you had already given me a script on this page. It's good to understand rather than copy-pasta hey. The behaviour is working (although infrequently it will 'shake' in the Vector3.forward axis), so thankyou for your answer.

Here is the working test project :

webplayer build : http://www.alucardj.net16.net/unityquestions/hoverboard%201-1d.html

your working script : http://www.alucardj.net16.net/unityquestions/ScriptHoverBoardA1.js

I have to say I am also blown away by how you replaced all my script vars and 4 raycasts with a short script and just 1 raycast. wow.

avatar image aldonaletto · Mar 22, 2012 at 11:52 AM 1
Share

It's quaternion magic... these damned quaternions are hard to understand, but may save a lot of code (or sometimes drive us nuts too!).
I saw the current webplayer version, and suspect that the jerky forward movement is being caused by lack of synchronicity between the character and the camera. How is the camera following the character? If a separate script moves the camera, it should do it in LateUpdate ins$$anonymous$$d of Update - something like this (camera script):

var target: Transform; // <- drag the player here var distance: float = 8.0;

function LateUpdate(){ transform.position = target.position - distance * transform.forward; }

avatar image aldonaletto · Mar 22, 2012 at 03:46 PM 1
Share

Your JS version seems ok: only the out keyword must be removed from the Physics.Raycast arguments (JS doesn't use it):

if (Physics.Raycast(transform.position, -curNormal, hit))... 
I also forgot to include the controller variable: just add this code to the script:

var controller: CharacterController;

function Start(){ controller = GetComponent(CharacterController); }

Show more comments
avatar image
0

Answer by Owen-Reynolds · Mar 22, 2012 at 02:00 AM

Atan always gives a "forward" result -- if you're going backwards it gives you exactly 180 degrees flipped as the answer. In other words, as you turn it will tell you 87, 88, 89,90,-89, -88,... . That's not Unity -- it's math.

Most people use Atan2 to solve that -- instead of the slope, you give it y and x (differenceYX and widthRaycast) and it takes care of division by zero and backwards, to give correct 0-360 answers.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image AlucardJay · Mar 22, 2012 at 02:06 AM 0
Share

thanks for the info, good to know :)

however I did test this, and while Atan2 is returning nice angles, I still have the problem which kind of confirms $$anonymous$$ryptos comment about achieving a Gimbal Lock.

This makes all my degrees vars redundant, I have to find out how to use delta to calculate a rotation (not much success with that search yet).

Here is my updated script from your reply : http://www.alucardj.net16.net/unityquestions/ScriptHoverBoard3a.js

 // calculate Z angle
 differenceYZ = vectorBoardBack.y - vectorBoardFront.y;
 angleBoardZtan = differenceYZ / widthRaycastZ;
 //angleBoardRotX = $$anonymous$$athf.Rad2Deg*$$anonymous$$athf.Atan(angleBoardZtan);
 angleBoardRotX = $$anonymous$$athf.Rad2Deg*$$anonymous$$athf.Atan2(widthRaycastZ, differenceYZ);
 
 // -- rotate board to align to terrain (Z angle is on the X-axis, and vice verca)
 transform.rotation = Quaternion.Euler (-angleBoardRotX + 90, 0, 0);

 

And the publish with the same effect error : http://www.alucardj.net16.net/unityquestions/hoverboard%201-1c.html

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

8 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Align plane to normal but keep Y-axis intact 1 Answer

Quaternions- how to leave out Y rotations... 1 Answer

Get raycast hit objects terrainData 0 Answers

Making a particle effect parallel to the slope of a terrain 1 Answer

multiplying gyro output 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges