Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Unity 2022.2 is now available as the latest Tech release.
    Dismiss Notice
  3. We are making some changes to the DOTS forums.
    Dismiss Notice
  4. Have a look at our Games Focus blog post series which will show what Unity is doing for all game developers – now, next year, and in the future.
    Dismiss Notice

6DOF banking and pesky gimbal lock

Discussion in 'Scripting' started by Quietus2, Jan 10, 2011.

  1. Quietus2

    Quietus2

    Joined:
    Mar 28, 2008
    Posts:
    2,058
    I decided to toy around with creating a 6DOF camera controller similar to games such as Descent. Everything works fine, until I try to lerp in a small 15 degree banking angle into the rotation.

    Code (csharp):
    1. var rotationSpeed = 120;
    2. var bankingSpeed = 8;
    3.  
    4. private var mouseX = 0.0;
    5. private var mouseY = 0.0;
    6.  
    7. function Update () {
    8.  
    9. var bankingAngle = 0.0;
    10.  
    11. // Normalized mouse input
    12. mouseX = ((Input.mousePosition.x - Screen.width / 2.0) / (Screen.width / 2.0));
    13. mouseY = ((Input.mousePosition.y - Screen.height / 2.0) / (Screen.height / 2.0));
    14.  
    15. // Rotate camera
    16. transform.Rotate(-Vector3.right * (mouseY * rotationSpeed) * Time.deltaTime);
    17. transform.Rotate(Vector3.up * (mouseX * rotationSpeed) * Time.deltaTime);
    18.  
    19. // Calculate banking angle
    20. bankingAngle = Mathf.LerpAngle(transform.eulerAngles.z,  -mouseX * 15, Time.deltaTime * bankingSpeed );
    21. transform.eulerAngles.z = bankingAngle;
    22.  
    23. }
    24.  
    25. function OnGUI() {
    26.    
    27. GUI.Label (Rect (10, 10, 100, 30), mouseX.ToString() + " : " + mouseY.ToString());
    28. GUI.Label (Rect (10, 40, 100, 30), transform.eulerAngles.ToString());
    29.  
    30. }
    31.  
    The camera banks properly and is self righting when the mouse is brought back to the center of the screen. However when I turn the ship so it's looking directly up or down along the world Y axis, I lose all freedom on anything but the Y.

    Is this a classic case of gimbal lock, and if so how do I avoid it? Perform the Z rotation on a parent object? Somehow express the lerp using transform.rotate? Hints from searching the forums were a bit sparse.
     
  2. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    The avoid it, just don't mess around with eulerAngles and use quaternions instead, cause they are the only rotation representation taht does not suffer from gimbal lock.
    You can still use your euler angle thinking if you want but you must use the Quaternion.Euler() function and then just multiply the old rotation with the Quaternion you get from the X - Y - Z rotation you apply in a single step normally

    And yes that code is pretty surely generating gimbal lock casue your rotation around Vector3 right (sure you don't want to use transform.right there?) does not check to remain in the +- 89 range and once you hit 90 you are basically doomed ...
     
  3. Jesse Anders

    Jesse Anders

    Joined:
    Apr 5, 2008
    Posts:
    2,857
    This is incorrect. To present just one counterexample, matrices don't suffer from gimbal lock either; in fact, they have the exact same behavior with respect to gimbal lock as quaternions do.
     
  4. Quietus2

    Quietus2

    Joined:
    Mar 28, 2008
    Posts:
    2,058
    I've seen you say that numerous times in threads I've read, but you haven't ever offered an actual solution for gimbal lock.

    Code (csharp):
    1.  
    2.  
    3. var rotationSpeed = 120;
    4. var bankingSpeed = 8;
    5.  
    6. private var bankingAngle;
    7. private var mouseX = 0.0;
    8. private var mouseY = 0.0;
    9.  
    10. private var startingRotation : Quaternion;
    11. private var rotationAngleX : float;
    12. private var rotationAngleY : float;
    13. private var rotationAngleZ : float;
    14.  
    15. private var upsideDown = false;
    16.  
    17. function Start() {
    18.  
    19. startingRotation = transform.localRotation;
    20.  
    21. }
    22.  
    23. function Update () {
    24.  
    25. var rotationX : Quaternion;
    26. var rotationY : Quaternion;
    27. var rotationZ : Quaternion;
    28.  
    29. // Normalized mouse input
    30. mouseX = ((Input.mousePosition.x - Screen.width / 2.0) / (Screen.width / 2.0));
    31. mouseY = ((Input.mousePosition.y - Screen.height / 2.0) / (Screen.height / 2.0));
    32.  
    33. // Build rotations
    34.    
    35. rotationAngleX += (mouseX * rotationSpeed) * Time.deltaTime;
    36. rotationAngleX = ClampAngle (rotationAngleX, -360.0, 360.0);
    37.  
    38. rotationAngleY += (mouseY * rotationSpeed) * Time.deltaTime;
    39. rotationAngleY = ClampAngle (rotationAngleY, -360.0, 360.0);
    40.  
    41. rotationX = Quaternion.AngleAxis (rotationAngleX, Vector3.up);
    42. rotationY = Quaternion.AngleAxis (rotationAngleY, -Vector3.right);
    43.  
    44. // Calculate banking angle
    45. bankingAngle = Mathf.LerpAngle(transform.eulerAngles.z,  -mouseX * 15, Time.deltaTime * bankingSpeed );
    46. rotationZ = Quaternion.Euler(Vector3.forward * bankingAngle);
    47.  
    48. // Apply Rotation
    49. transform.rotation = startingRotation * rotationX * rotationY * rotationZ;
    50.  
    51. }
    52.  
    53. function OnGUI() {
    54.    
    55. GUI.Label (Rect (10, 10, 200, 30), mouseX.ToString() + " : " + mouseY.ToString());
    56. GUI.Label (Rect (10, 40, 100, 30), bankingAngle.ToString());
    57.  
    58. }
    59.  
    60. function ClampAngle (angle : float, min : float, max : float)
    61. {
    62.     if (angle < -360.0)
    63.         angle += 360.0;
    64.     if (angle > 360.0)
    65.         angle -= 360.0;
    66.     return Mathf.Clamp (angle, min, max);
    67. }
    68.  
    I switched around to using quaternions for all the rotations. Still having issues with looking directly along the world Y axis. The camera spins wildly, as if it's gimbal locked but the Z rotation I'm applying somehow breaks out of it.

    So I'm wondering if Jesse is correct, the docs and everything I read on the internet are wrong and quaternions can still gimbal lock. Or perhaps eulerangle.z in my lerp is causing the problem, giving wildly fluctuating values or some such looking along the world Y axis.

    Any ideas?
     
  5. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    Thats incorrect, matrices can't solve the gimbal lock problem.
    As eulers, they degrade to 2DOF in the pole directions

    The wikipedia article on gimbal lock explains it pretty nicely on whats going wrong
     
  6. Jesse Anders

    Jesse Anders

    Joined:
    Apr 5, 2008
    Posts:
    2,857
    I've explained how to implement gimbal-lock-free motion more times than I can count on various game development forums :) More on GDNet than here though, just 'cause I've been posting there longer. (I don't know for sure that I've explained it in detail here or on Unity Answers, but I'd be willing to bet that I have.)

    Anyway, in short, the way to avoid gimbal lock is not to build or combine rotations in ways that can lead to gimbal lock. What this means depends on the context, but usually it means modifying an orientation using incremental rotations rather than building an orientation 'from scratch' using a set of three Euler angles.

    You didn't specify what this is in response to; are you referring to my earlier post? If so, I can absolutely guarantee you that you're mistaken.

    I don't see anything in that article that states that matrices are more susceptible to gimbal lock than quaternions.

    Look, I've already been through this with other posters on the forum. It's a simple fact that matrices and quaternions behave the same way with respect to gimbal lock, and I can prove it if you'll give me the opportunity. Similarly, if your claim is that matrices are more susceptible to gimbal lock than quaternions, I invite you to submit proof of that.

    With that in mind, I'll issue the same challenge I did in the previous thread on this topic (the challenge was never met, by the way). That is, provide an example of an operation involving rotations that would lead to gimbal lock with matrices but not with quaternions. If your claim that matrices are more susceptible to gimbal lock than quaternions is correct, this should be easy to do.
     
  7. Jesse Anders

    Jesse Anders

    Joined:
    Apr 5, 2008
    Posts:
    2,857
    @Quietus: Actually, the problem you're seeing isn't gimbal lock, per se. It's just that modifying the global 'z' Euler angle (or the local one, for that matter) isn't going to produce the results that you expect.

    I haven't tried this myself, but here's what I'd suggest. Presumably, you want the roll/bank effect to be independent of the overall control of the vehicle. One way to achieve this would be to create two game objects, one the child of the other. The parent object would be controlled by a script much like your first one, but without the banking. The child object would then *only* bank, and would bank relative to the parent object. The banking angle would then be made proportional to the yaw velocity (or however you want to handle it).

    There may be other solutions, but that's the most straightforward way I can think of at the moment to get the behavior you're looking for.
     
  8. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    Was in respect to your posting.

    But I should have been more specific I guess.

    Matrices themself would not suffer from gimbal lock as matrices don't do anything other than vector space transformations.
    But in game engines, it heavily depends on what the engine does internally on if their usage results in gimbal lock or not, if the engine feeds rotation matrices from quaternions or euler angles.
    There is no requirement to build them from the quaternion and I've seen several engines really building them from euler angles, so I normally, without knowing the inner working indepth enough of the engine, consider them to be "euler based" ie gimbal lock bound too, this saves me the headache afterwards as I know that independent of the implementation, quaternions will never F*** up.

    Also quaternions, once you get the idea on them, are much easier to work with, to apply to stuff and when it comes to stuff like path following etc, they are out of competition above anything euler and matrix can do with similar simple code, math and performance.
    They only look frightening at the first or frightening if you are not a maths / physics / computer science student yet think its wise to look at their mathematical base. If you only think of them as what they represent at the end and visualize that, they are significantly easier, I would say for most applications even easier to think off than euler and definitely much more understable than matrices ;) So what I wanted to say is: there is no reason to not learn them, don't fear them, they are your friends :)
     
    Last edited: Jan 10, 2011
  9. Quietus2

    Quietus2

    Joined:
    Mar 28, 2008
    Posts:
    2,058
    That's basically what I'm doing now. Similar to some of the stock cameras, tracking rotation angles myself as an offset from a reference and ditching the Euler angle.

    Code (csharp):
    1. // Calculate banking angle
    2. bankingAngle = Mathf.LerpAngle(transform.eulerAngles.z,  -mouseX * 15, Time.deltaTime * bankingSpeed );
    3. rotationZ = Quaternion.Euler(Vector3.forward * bankingAngle);
    4.  
    Did some more testing and It was eulerAngles.z, which seemed to be fluctuating randomly when the camera is pointing along the Y axis for some reason. I seem to remember reading at some point that Quaternion.Slerp had similar problems, as the 'shortest path' calculations varied from frame to frame because of this.

    Code (csharp):
    1. // Calculate banking angle
    2. rotationAngleZ = Mathf.LerpAngle(rotationAngleZ,  -mouseX * 15, Time.deltaTime * bankingSpeed );
    3. rotationAngleZ = ClampAngle (rotationAngleZ, -360.0, 360.0);
    4. rotationZ = Quaternion.AngleAxis(rotationAngleZ, Vector3.forward);
    Replaced it with the above and it's working much better. No gimbal lock, no wild spinning cameras.
     
  10. Jesse Anders

    Jesse Anders

    Joined:
    Apr 5, 2008
    Posts:
    2,857
    Well, it sounds like we're not really in disagreement then :)

    That's really the essence of it right there, yes.

    Yes, it sounds as if (like many people) you simply 'associate' matrices with Euler angles more than you do quaternions, and therefore think of them as being more susceptible to gimbal lock than quaternions. Unfortunately, this way of looking at things has led to a lot of confusion online and elsewhere, as evidenced by the fact that many people firmly believe the matrices are inherently more susceptible to gimbal lock than quaternions (which is completely false).

    Agreed :)
     
  11. Jesse Anders

    Jesse Anders

    Joined:
    Apr 5, 2008
    Posts:
    2,857
    Yeah, that should work too. The only potential issue is that as you bank, yaw will be relative to the new, 'banked' orientation rather than the original 'unbanked' orientation. If that's acceptable, then that'll work; otherwise, the 'parenting' solution I described earlier might be more appropriate.

    (I've played Descent, but I can't remember off the top of my head exactly how the banking effect works in that game. I think though that it's more like what I described; that is, that the 'banking' effect doesn't affect the yaw axis.)
     
    Last edited: Jan 10, 2011
  12. Quietus2

    Quietus2

    Joined:
    Mar 28, 2008
    Posts:
    2,058
    Agreed, it's just intended to a be cosmetic effect to give an added impression of rotation. As the ship is really just a camera, I'll switch to the parented solution and see how it feels.

    I still have other problems to work on. Such as the rotations are based on world axis vectors and not the local transform axis. As a result when you are upside down controls are reversed, when you're sideways they're even more unintuitive. It looks like from the docs that InverseTransformDirection is what I need.

    I also think descent had an auto leveling system, but can't remember how that worked. Like you, it's been ages since I played it.
     
  13. Jesse Anders

    Jesse Anders

    Joined:
    Apr 5, 2008
    Posts:
    2,857
    Actually, I think you had the right idea with your original script. You shouldn't need to use InverseTransformDirection(); Transform.Rotate() already applies the rotation in local space, which is what you want. (And yeah, the control interface definitely shouldn't be affected by orientation; if you're 'upside-down' with respect to some reference or to your original orientation, the controls should continue to appear to function in the same way. In any case, your original approach of using Transform.Rotate() should give the right results.)

    Yeah, I think the autoleveling effect was independent of any cosmetic banking effect. Actually, the autoleveling effect is probably the more straightforward of the two to implement. Basically, you'd raycast down (relative to the ship) to see if there's a surface within some distance beneath the ship, and then apply an incremental, corrective rotation (for which you can use Quaternion.FromToRotation(), or whatever it's called) to gradually align the ship with the normal of the surface beneath it.
     
  14. Quietus2

    Quietus2

    Joined:
    Mar 28, 2008
    Posts:
    2,058
    Lol!

    I guess I could use the same modified banking code and plug that right into transform.rotate. It doesn't look as pretty as all the quaternion manipulation, but it's sure a hell of a lot less code. If I do and start getting gimbal lock and wild spinning again, I'll stab my eyes out Jesse!

    I'll have to watch some videos on youtube to get a feel for how it works. Iirc it was when there was no user input, for which I could probably just create a 5% or so mouse input dead zone, since I'm using normalized mouse coordinates and not a mouse-look type delta.
     
  15. Jesse Anders

    Jesse Anders

    Joined:
    Apr 5, 2008
    Posts:
    2,857
    Just in case I wasn't completely clear earlier, I'm not suggesting re-introducing the aspects of your original code that were causing the undesirable behavior (specifically the manual manipulation of the 'z' rotation angle). Rather, what I'm suggesting would be a combination of your original code (specifically the part that uses Transform.Rotate() to apply local pitch and yaw) and your later code (which creates the 'bank' effect using a relative rotation).

    If you really get stuck on this and find you can't get it working the way you want, post back and maybe I can post an example script showing what I mean.
     
  16. Quietus2

    Quietus2

    Joined:
    Mar 28, 2008
    Posts:
    2,058
    Oh I understood what you meant when discussing the parenting. I will certainly be doing that after I get past the current hurdles. It's just working a day getting the quaternions working the way I want (albiet in the wrong coordinate system) then going back to the 3 line solution I started with!

    I am sort of stuck though and could some rotation expertise. I could be that it's almost midnight and I'm exhausted, but I can't seem to figure out how to properly bank the craft in the same fashion at the quaternion version of the script.

    Code (csharp):
    1. // Calculate banking angle
    2. rotationAngleZ = Mathf.LerpAngle(rotationAngleZ,  -mouseX * 15, Time.deltaTime * bankingSpeed );
    3. rotationZVector = Vector3.forward * rotationAngleZ;
    4. transform.rotation *= Quaternion.Euler(rotationZVector);
    5.  
    That's the latest version I've tried (of a few dozen), it spins along the local Z but instead of setting an explicit angle like I think it should it spins about as if I were using using transform.rotate. It doesn't stop at either 15 or -15 rather just keeps spinning.

    There's probably a simple way I'm missing to bank the ship in a range sans euler angles, but after reading about quaternions all day I'm kind of fried. I'm back to square one, lol!

    I also attempted to convert the quaternion rotations to local space as well, but it didn't like that for some reason. It started spinning wildly whenever it approached any world axis. Maybe I just need sleep, or a glass of rum.

    http://dl.dropbox.com/u/18267143/DecentCamTest.unitypackage

    Here's a package with both scripts, with a camera in a reference box if you want to toy with it.
     
  17. Jesse Anders

    Jesse Anders

    Joined:
    Apr 5, 2008
    Posts:
    2,857
    Yes, that's the expected behavior given the code that you've written. This line:

    Applies an incremental, local rotation; in other words, the above code basically has the same effect as using Transform.Rotate() (with the last argument left at its default value). As such, the banking won't observe any sort of limit, but rather will be continuous (that is, the ship will continue to bank as long as it's also yawing).

    I hate to sound like a broken record, but I really think parenting is the solution. I downloaded your project, so if you really get stuck on this I could probably post a revised version of your script(s) showing what I mean.
     
  18. cerebrate

    cerebrate

    Joined:
    Jan 8, 2010
    Posts:
    261
    uh. I'm not quite sure why, but why don't you just use transform.Rotate()?
     
  19. Quietus2

    Quietus2

    Joined:
    Mar 28, 2008
    Posts:
    2,058
    Yes, but in the quaternion version the exact same same code has a limit and eases the banking when the mouse returns to center?

    I tried the parenting solution, feeding the calculated rotation with transform.parent.rotation. The banking works now but I've notice other issues.

    It doesn't 'feel' anything like the quaternion version, which has what I'm aiming for. Nor does it have the self righting of the original version. Simply rotating on a single axis, seems to screw with the other axis so that when you come back from a full rotation say along the x axis and stop, the ship is not centered.

    I think this all is because you never truly input only one axis with a mouse, in addition the quaternion version builds rotations relative to a reference object, while the transform.rotate version does not.

    If you have a solution that has the proper characteristics, I'd sure like to see it.

    I'm thinking now of using the quaternion script, with a different reference object depending on the camera's orientation. That's probably a dead end too, but I'm at a loss at this point. I thought a descent like controller would be a piece of cake, but it's turned out to be quite a headache.
     
  20. Jesse Anders

    Jesse Anders

    Joined:
    Apr 5, 2008
    Posts:
    2,857
    He was, originally. (I think the other stuff was just a tangent due to trying to get the 'bank' effect to work.)
     
  21. Jesse Anders

    Jesse Anders

    Joined:
    Apr 5, 2008
    Posts:
    2,857
    If you could post a new Unity package that has all the versions you've tried, and if you could also post a list of which elements of each you like and want to retain, I could probably take a look and try to put together a working version for you.
     
  22. Quietus2

    Quietus2

    Joined:
    Mar 28, 2008
    Posts:
    2,058
    bit.ly/hRAVOL

    The difference is easy to see.

    Activate either the original or the quaternion versions, then spin the shop hard about a few times. You'll notice you come back exactly to center, the ship essentially self rights due to the banking code.

    Then activate the two script parenting solution you suggested and do the same. Spin the ship hard about a few times, follow the seams on the box, etc. Notice the ship's orientation. It isn't quite right.

    So it looks like the banking code was masquerading as self-righting code as well.

    I'm thinking I should add the Q/E rotate around the pivot function before I proceed too much further.



    From watching some videos, It's somewhat difficult to tell how they're doing it. But I'm getting the impression that you and I were wrong, and the baking was not just cosmetic, that it's the essence of their auto leveling system. I don't see any aligning to surface normals in the video.
     
  23. Jesse Anders

    Jesse Anders

    Joined:
    Apr 5, 2008
    Posts:
    2,857
    Hm, wish I could fire up Descent and check it out :|

    Anyway, I'm not sure (yet) about us being wrong. For one thing, the 'autoleveling' in Descent was an option that you could turn on or off, but I think you *always* banked when you turned. If that's true, then that would suggest that the banking was independent of the autolevel feature.

    I'll take a look at the video and Unity project a little later though and see if I can offer any additional insight.
     
  24. Quietus2

    Quietus2

    Joined:
    Mar 28, 2008
    Posts:
    2,058
    Eric5h let me know there's an osx port of descent 2. http://www.descent2.de/ It's not descent 3, the controls are probably different from that video but it's a start to refresh our memories.

    That's a point. It's not a surface normal alignment though, and if you watch through the video the leveling appears to feel similar to the quaternion/original versions of the scripts.

    Appreciate your help. Hope you appreciate my appreciation.
     
  25. Jesse Anders

    Jesse Anders

    Joined:
    Apr 5, 2008
    Posts:
    2,857
    I've had a chance to look at the project, and the parenting implemented there isn't exactly what I had in mind. But, I'll try to put together an example that makes it more clear :)

    I ran around in Descent 2 a bit, and I have a suspicion that you may be mistaking the (cosmetic) 'banking' effect for autoleveling.

    I don't know if you've downloaded the Descent 2 demo, but a way you can check this is to make sure autoleveling is off in the options, and then go spin around (yaw) in place. You should bank as you yaw, and then 'unbank' (re-align with the current up vector) when you stop yawing. If this is what you're describing as autoleveling, then that's just the banking effect (which can be confirmed because it happens whether autoleveling is on or off).

    Furthermore, it's fairly clear (I think) that banking is purely cosmetic and doesn't actually modify your orientation. The evidence for this is that if you 'spin in place' (yaw) and then stop spinning, your local 'up' direction hasn't changed. If banking was actually changing your orientation, the yaw axis would be changing as well, which would cause your 'up' direction vector to change (which doesn't happen - even when you're banking, you're still yawing about the 'un-banked' up vector).

    Anyway, I'll try to put together an example showing what I mean.
     
  26. Jesse Anders

    Jesse Anders

    Joined:
    Apr 5, 2008
    Posts:
    2,857
    Ok, attached is a Unity package demonstrating Descent-style 6DOF control with (cosmetic) 'banking' behavior.

    To keep things simple I just used the default input setup, so the 'Horizontal' axis controls yaw and the 'Vertical' axis controls pitch. I didn't implement (player-controlled) rolling or linear motion, as that would've required changing the input setup or adding additional code to make the motion smooth, so the only controls are yaw and pitch. However, that's sufficient to demonstrate the idea.

    If you don't pitch and just yaw back and foth, you should see that banking behaves as expected. (The banking comes to a rest a little abruptly, but again, to fix that I would've had to change the input settings or add additional code to smooth out the motion.) Note that when you stop yawing, the ship 'rights itself'. I'm guessing this is what you were referring to as autoleveling, but autoleveling is actually something else. Note also that despite the banking, if you don't pitch, your 'up' direction vector doesn't change, just as in Descent. In other words, the banking is purely cosmetic (we may not disagree on that, but I'm just stating it for clarity).

    I hope this helps some :) And feel free to post back if you have any questions or need any more help with this.

    (Oop, one more thing. If you yaw one way and then immediately reverse directions and yaw the other way, the bank effect will 'pop' in a discontinuous way. Again, this is just a consequence of keeping the code simple for demonstration purposes and doesn't represent any shortcoming of the basic approach. If you were to do it 'right', you'd give the bank angle some damping/hysterisis in order to smooth it out.)
     

    Attached Files:

  27. Quietus2

    Quietus2

    Joined:
    Mar 28, 2008
    Posts:
    2,058
    Well Jesse, after a day of tangents and a foray deep into those ungodly quaternion things your parenting solution ended up being the ticket. At least dreamora got me to learn things I never wanted to touch with a 10 foot pole! Here's the final solution, which is remarkable similar to my original one.

    Code (csharp):
    1. var pitchYawSpeed = 120;
    2. var rotationSpeed = 120;
    3. var bankingSpeed = 8;
    4.  
    5. private var bankingAngle : float;
    6. private var mouseX : float;
    7. private var mouseY : float;
    8.  
    9. function Update () {
    10.  
    11. // Normalized mouse input
    12. mouseX = ((Input.mousePosition.x - Screen.width / 2.0) / (Screen.width / 2.0));
    13. mouseY = ((Input.mousePosition.y - Screen.height / 2.0) / (Screen.height / 2.0));
    14.  
    15. // Pitch/Yaw ship
    16. transform.Rotate(-Vector3.right * (mouseY * pitchYawSpeed) * Time.deltaTime);
    17. transform.Rotate(Vector3.up * (mouseX * pitchYawSpeed) * Time.deltaTime);
    18.  
    19. // Rotate ship
    20. transform.Rotate(Vector3.forward, Input.GetAxis("Rotate") * rotationSpeed * Time.deltaTime);
    21.  
    22. // Banking effect
    23. bankingAngle = Mathf.LerpAngle(bankingAngle,  -mouseX * 15, Time.deltaTime * bankingSpeed );
    24. Camera.main.transform.localEulerAngles.z = bankingAngle;
    25.  
    26. }
    Thanks for your help. I owe you a beer.
     
  28. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    ungodly hehe ;-)
    hey quaternions are the only practical usage of math that exceeds 4 dimensions, at least the only one I recall like that ;-)

    but glad you got something that seems to work fine for you, independent of what you use and how you got there :) And I'm sure all the godly and ungodly stuff has brought some knowledge and experience to you for the future :D
     
  29. Quietus2

    Quietus2

    Joined:
    Mar 28, 2008
    Posts:
    2,058
    Well tbh they aren't as bad as I had thought. Four Dimensions, ack! There ended up being pretty easy to work with once you got used to it, the helper functions went a long way towards that.

    The only thing I wasn't able to accomplish, was getting the rotations working properly in local space. I tried tracking my own rotations, ditching a reference object and setting them directly with Quanternion.Euler(), but it still seemed to rotate in world space and controls ended up reversing.

    But yeah dreamora, this is one wild goose chase I'm thankful for. Learned a great deal.

    Mostly, don't set Euler angles directly, as when Y=90 or Y=270 it will make the baby jesus cry.
     
    Last edited: Jan 12, 2011