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
1
Question by Kwikalot · May 14, 2013 at 10:32 AM · rotationaxisfloat

Problem with rotating two axes independently, simultaneously

Hi everyone,

I've got a problem with matching two rotations. Let's start from the beginning - as seen on the first picture, I have a ball with wings. I want them to move up and down (by rotating them) while in the same time rotate them a little (just like on the second picture). So basically, when wings go up, they rotate a little in one direction, and when they go down, they rotate in the second direction.

The point of rotation for the wings is set in a 3D program right in the point of contact with the ball (so I don't have to set it manually in the script).

I thought that the best way to do what I want was to make an empty object which would be a parent for the wings. Then I could rotate the parent in one axis (for me that is local X axis) and the children-wings in second (that would be the local Z axis) - as shown on the third picture.

alt text

The whole movement can be seen on the fourth picture.

alt text

So now it's time to state my problem. When running the rotations separately (just one at a time) either the X rotation or the Z rotation is working fine. The problem occurs when I try to combine them and start them simultaneously. The first two or three cycles are working ok (the wings have their maximum on the X axes exactly when they reach maximum on the Z axis), but then everything starts to fall apart - rotation on the X axis doesn't match the rotation on the Z axis anymore.

Here's my code for the whole "animation":

 using UnityEngine;
 using System.Collections;
 using System;
 
 public class WingsAnimation : MonoBehaviour 
 {
     public GameObject leftWing;
     public GameObject rightWing;
     public GameObject parent;
     
     public float rotationTime; // time in which the object will rotate
     
     private float rotationAngleZ;
     private float rotationAngleX;
     private bool upOrDown = false;
     private bool twist = false;
     private float angles; // angles for the Z axis
     private float angles2; // angles for the X axis
 
     // Use this for initialization
     void Start () 
     {
         rotationAngleZ = 33.0f; // max rotation on the Z axis
         rotationAngleX = 20.0f;    // max rotation on the X axis    
     }
     
     // Update is called once per frame
     void Update () 
     {        
         angles = 2 * rotationAngleZ / rotationTime * Time.deltaTime;
         angles2 = 2 * rotationAngleX / rotationTime * Time.deltaTime;
         
         UpAndDown();
         SelfRotate ();    
     }
     
     void UpAndDown () // Z axis movement
     {        
         if (leftWing.transform.localRotation.z * 100 >= rotationAngleZ)
         {
             upOrDown = false;
         }
         
         if (leftWing.transform.localRotation.z * 100 <= -rotationAngleZ)
         {
             upOrDown = true;
         }
         
         if (upOrDown)
         {
             leftWing.transform.Rotate(0, 0, angles, Space.Self);
             rightWing.transform.Rotate(0, 0, -angles, Space.Self);
         }
         else
         {
             leftWing.transform.Rotate(0, 0, -angles, Space.Self);
             rightWing.transform.Rotate(0, 0, angles, Space.Self);
         }
     }
     
     void SelfRotate () // X axis movement
     {        
         if (parent.transform.localRotation.x * 100 >= rotationAngleX)
         {
             twist = false;
         }
         
         if (parent.transform.localRotation.x * 100 <= -rotationAngleX)
         {
             twist = true;
         }
         
         if (twist)
         {
             parent.transform.Rotate(angles2, 0, 0, Space.Self);
         }
         else
         {
             parent.transform.Rotate(-angles2, 0, 0, Space.Self);
         }
     }
 }

If I set rotationTime to 1, the problem occurs after a couple of minutes, but when it's less then 1, it happens a lot faster.

My guess is that this has to be a problem with floating-point numbers, but I'm not sure. I've tried to debug angles and angles2 to see, if they are changing over time, but they stay constant (or I should say that they change but the difference is so small, that it shouldn't have any effect - or not this big anyway - on the movement).

I've made a small test in which I tried to move two cubes in one direction with different displacement and velocity, but with the same time, while moving their parent slowly in the opposite direction. The test was supposed to show, if the two cubes would reach designated point in the same time or if there would be some delay for one of them. I thought that this situation would be similiar to my problem, but in the test everything was working fine.

While "playing" with the positions of the object, I never had such problem. But with rotation it's somehow different. I don't know if I am making a mistake in my understanding or is there a bug in my code, so any help and explanation would be much appreciated :)

1.jpg (84.3 kB)
2.jpg (107.8 kB)
Comment
Add comment · Show 6
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 Graham-Dunnett ♦♦ · May 14, 2013 at 10:32 AM 1
Share

Sounds like a perfect thing to do with the animation editor, so you can keyframe the wings and get exactly the behaviour you want.

avatar image Kwikalot · May 14, 2013 at 10:47 AM 0
Share

If everything fails I will probably do it with the animation editor - but for now I would like to try to code it :)

avatar image raimon.massanet · May 14, 2013 at 11:11 AM 0
Share

By using Space.Self, you are rotating around axes that have moved because of previous rotations. Could that be the case? First of all, I would try using Space.World, because you always want to rotate around fixed axes.

avatar image Kwikalot · May 14, 2013 at 11:33 AM 0
Share

I'm using Space.Self, because the whole GameObject can move or rotate and I need wings to always rotate with it no matter where that GameObject is or what rotation does it have :)

avatar image raimon.massanet · May 14, 2013 at 12:49 PM 0
Share

I understand, but notice that once you have rotated your object around its X axis, its Z axis is no longer facing "forward", and therefore, rotating around Z axis will not rotate it upwards. $$anonymous$$aybe it is expected behavior, I'm just pointing it out because this has bothered be sometimes :-) By the way, this is also true when directly editing transform.eulerAngles.

Show more comments

3 Replies

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

Answer by TheDarkVoid · May 14, 2013 at 10:40 AM

You shouldn't be modifiying a Quaternion directly like that. you need to do this with the Transform.eulerAngles Do it like this:

 private Vector3 rotationAngles; //store you desired rotation here
 
 void Update()
 {
 transform.eulerAngles = rotationAngles;
 }

instead of modffifying the rotation directly just moddify the rotationAngles vector and then set it at the end of the update. Also testing the current rotation should also be done with eulerAngles.

Comment
Add comment · Show 4 · 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 Kwikalot · May 14, 2013 at 11:39 AM 0
Share

Ok, I'm trying to use Transform.eulerAngles ins$$anonymous$$d of Transform.Rotate(), but I'm having an issue - it seems that eulerAngles are changing the rotation in world space, but I need them in local space (or am I misunderstanding something with this?)

avatar image Kwikalot · May 14, 2013 at 04:17 PM 0
Share

Ok, so the solution with Transform.eulerAngles partially helped :)

I had to resign from the idea of two functions - one for parent and the other one for children (it didn't work properly that way). Now I have only one function which rotates wings around the X and Z axes with no parent.

But all in all, solution with eulerAngles has a couple of disadvantages - first and most important for me is "lack" of local space. Second is problem in catching right moment of the rotation when speed of rotation is high - but this is mainly problem with float numbers and missing some of the steps (interesting thing is that transform.Rotate() doesn't have this problem - or I didn't see it).

For this moment the solution works so I'm happy :) I'll also try to make this with animation editor as Graham Dunnett suggested and see, which will look better :)

Anyway thank you for all the help and suggestions :)

avatar image TheDarkVoid · May 14, 2013 at 08:56 PM 1
Share

to get local rotation do transform.localRotation.eulerAngles works the same way as before but on local space

avatar image Kwikalot · May 15, 2013 at 06:03 AM 0
Share

I didn't know that - thanks :)

avatar image
1

Answer by raimon.massanet · May 15, 2013 at 07:16 AM

In your case, I think that what was causing the desynchronization had nothing to do with the rotation method used.

I think the problem is that you don't check whether the angles are going to go past the fixed limits before applying the rotation. This can cause your wings to actually sweep a larger angle than expected (at "random" depending on the last deltaTime before reaching the end of the sweep).

Since you have defined a fixed time for every sweep, but your sweeping angles might vary, there you have your desynchronization.

Comment
Add comment · Show 5 · 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 Kwikalot · May 15, 2013 at 08:48 AM 0
Share

I tried that, but it didn't help (desynchronization was showing later but it was still there). I didn't include that in the code in order to simplify my problem as much as possible :) But thanks anyway - this is something worth remembering.

avatar image raimon.massanet · May 15, 2013 at 09:59 AM 0
Share

But did you just "clamp" your angle or did you calculate the position it should move (in the opposite direction) in order to maintain sync?

If this does not work, I have no more ideas for the moment. And I don't see why modifying eurlesAngles should work and Rotate not.

avatar image Kwikalot · May 15, 2013 at 10:45 AM 0
Share

First I tried only to "clamp" it, later I added a fixed position for every rotation if the angle of either one of them was greater than the limit. Thanks to that, they all would start every sweep from proper positions. Of course sometimes you could see a little teleportation of the wings, but this was not the issue.

I guess that the desynchronization could be caused by the fact, that I had two separate functions for each rotation (they could have been calculated in a little different times). Now when it's in one function, everything is working fine.

I guess that if I've wrote previous code in a single function, the Rotate() would work ok.

avatar image raimon.massanet · May 15, 2013 at 02:41 PM 1
Share

I'm not sure I understand what you mean by "fixed position". What I meant by correcting the position is: Let's say your maximum angle is 45º, and you foresee that after applying your rotation you are going to end up in a 47º, then, since you are oscilating, the new position should be 43º (45º limit - 2º offset). There should be no "teleporting" in doing that. I believe you could do that in two different rotations, as intended.

avatar image Kwikalot · May 15, 2013 at 05:41 PM 0
Share

By "fixed position" I meant that for example I have my maximum angle 45º on the X axis and 30º on the Z axis. So when I'm rotating wings, whenever X axis or Z axis is greater then 45º or 30º, both axes are automatically set to match their maximum values. Then when they are all set and ready, another sweep begins.

It's not pretty, but in theory it should work properly.

As to what you wrote, I tried that and it works (even better than my original approach :) ).

But there are two things that make me wonder - first is that in eulerAngles approach I had to make one function, because when I had two functions, the axes on the mesh were working fine (visually on the scene view and in the Inspector), but mesh itself was rotating only in one axis. It sounds impossible but it happened - but I have no idea why.

Second thing is that there is still problem with small desynchronization at the beginning of the rotation (whichever approach), only when the time of the rotation is small (for example 0.1 sec.). But now after one broken sweep (which starts with the beginning of the scene) rotation returns to correct movement and from then it works fine. I found that this is connected to the Time.deltaTime. The first five sample logs for Time.deltaTime are: 0.02; 0.02; 0.308; 0.024; 0.016 - in the third log the value of Time.deltaTime is very high and this is the moment rotation is going crazy.

Of course when I use FixedUpdate() ins$$anonymous$$d of Update() or set the time of rotation to 1 sec. everything is ok. I'm just curious if that supposed to be like that - I know that Time.deltaTime has different values after each frame, but is it normal that one of the first values is so much higher than the others?

avatar image
0

Answer by IntergalacticSloth · Jul 03, 2017 at 03:56 PM

I'll leave this for others. I had a similar problem where the axes start to get all messed up over time.

I think I was suffering from "Un-commutativeness of Rotation in 3D Space". Explained at this link.

I shared the details of my solution on that link. And shared again as an answer to this question. (Just want to make sure y'all can find the information I could not.)

Comment
Add comment · 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

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

18 People are following this question.

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

Related Questions

90 Degree stopping rotation on y-axis issue 0 Answers

LookAt on one axis 2 Answers

Transform.Translate but ignore rotation on one axis 0 Answers

Orbit Collision Axis 0 Answers

joystick dpad axes snapping to 1 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