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 canis · May 09, 2015 at 09:35 AM · camerarotationvector3

Calculate Quaternion upward ? to keep the rotation of camera

alt what happen

May be its the old problems, but I still deeply troubled by this for few days long.

I working on the project to control the camera follow the target(player), those objects without any hierarchy relationship. which mean independent objects in the scene.

let's make it short, Imagine a spaceship to move around and camera following it. {Pic01}

when the camera on-top/at-bottom of that spaceship {pic02} camera will start fliping, it is because the upwards reference is based on world's upwards {in this case Vector3.up}, at that point Quaternion cannot calculate the upward of camera, both x & z axis are zero. I call this zero-point, correct me because I didn't know the name of this point.

therefore after camera get pass zero-point the camera will rotate 180 degree, but this is not the result that we want, we want it keep the camera's head point to the ground{Vector3.down}

so here is the question, can we calculate the upward ?? in my program I already have following values

  • Polar, Elevation, Distance related to chasing target.

  • target forwards, target upwards

here is the video to show the real issue.

**Video here.** !!!!

**Video here.** !!!!

**Video here.** !!!!

upwardreference.png (15.4 kB)
Comment
Add comment · Show 4
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 Eno-Khaon · May 09, 2015 at 10:51 AM 0
Share

Ahhh, okay. Thank you for the video clarification.

Yep, that's Gimbal Lock. You're rotating until you're in front of your target point and looking backwards towards it, while expecting the camera to be tilted upside-down slightly. That's where the solution in my answer (albeit based around the wrong axis at present) is a potential quick-fix for it, but certainly not the best approach.

Sorry to say, though, I'm dead tired and can't really come up with any good suggestions right now, but I would suggest tinkering around with Quaternion.AngleAxis to work out that problem. Effective use of it will let you limit rotation per axis relative to your baseline (right behind the character?) as well as having no trouble with rotation of any kind.

avatar image Bunny83 · May 09, 2015 at 11:14 AM 0
Share

@canis: Show the code you use to rotate your camera. If you exclusively use quaternions this shouldn't happen. However i guess that you use LookAt or LookRotation which has "Vector3.up" as default up vector.

It's not really a gimbal lock as you usually can't recover that easily from that state. It's true that at the lowest point you loose one degree of freedom but you still rotate in the same direction. A gimbal lock takes away a different rotation axis than the one that causes the lock.

Do you use by chance one of the $$anonymous$$ouseLook script from Standard Assets?

avatar image canis · May 09, 2015 at 11:38 AM 0
Share

I'm using the Quaternion.LookRotation(), however I can't calculate the right upwards for the camera.

// sorry little mess here, I already try to use the name that can represent the meaning.

 // Position
             cache.CameraOrbitPosition = obj.Coordinates.ToCartesian() + ChaseTarget.position;
             cache.TargetOrbitPosition = (obj.ExtendLookAt.Enable) ? (obj.ExtendLookAt.LookAt.ToCartesian() + ChaseTarget.position) : ChaseTarget.position;
             cache.TargetZoomedPosition = cache.TargetOrbitPosition + cache.TargetOrbitPosition.Direction(cache.CameraOrbitPosition) * obj.Camera$$anonymous$$ethod.ZoomSectionRef;
             cache.CameraZoomedPosition = cache.CameraOrbitPosition - cache.CameraOrbitPosition.Direction(cache.TargetOrbitPosition) * obj.Camera$$anonymous$$ethod.ZoomSectionRef;
 
             // Rotation
             cache.CameraFacingDirection = (cache.TargetZoomedPosition - cache.CameraZoomedPosition).normalized;
             cache.TargetForwardReference = (obj.Camera$$anonymous$$ethod.ForwardReference == null) ? ChaseTarget : obj.Camera$$anonymous$$ethod.ForwardReference;
 
             // Question : Camera upward reference based on pitch angle?
             // after geting pass from zeropoint, reverse upward & downward 
             // using calculate upward to find out the local roll the whole orbit for camera rotate
             float orientationFix = $$anonymous$$athf.Abs(Vector3.Dot(cache.CameraFacingDirection, Vector3.up));
             cache.CameraUpwardReference = Vector3.Lerp(Vector3.up, cache.CameraFacingDirection, orientationFix);
             Debug.DrawRay(ControlRotation.transform.position, cache.CameraUpwardReference, Color.red);
             cache.CameraRotationReference = Quaternion.LookRotation(cache.CameraFacingDirection, cache.CameraUpwardReference);
avatar image Bunny83 · May 09, 2015 at 11:59 AM 0
Share

Well, that doesn't help much as you almost exclusively use your own variables and methods where we have no idea what they are doing exactly or what they return. You said you have polar and elevation values. Is the elevation clamped in any way? (between +-90?) in that case it's not possible because a pure polar angle and elevation angle doesn't contain any orientation around the look axis. You need another reference. Usually use use the old local right vector and use the cross product to calculate a new up vector.

However using polar angle (around world y) and elevation (around local x but allowing +-180°) will cause strange behaviour when you're upside down as left-right rotation will be inverted.

If you want a totally free rotation you should use only quaternions so you're not bound to eulerangles representation. You would use Quaternion.AngleAxis to calculate a relative rotation around a certain rotation axis (local up / local right / local forward) and multiply the old rotation with the relative rotation to get the new one. How much you should rotate around an axis should be based on your input. Though with the information given we have no idea where and how your input is actually transferred into rotation.

ps: for orbit cams it's usually the easiest approach to parent the camera to an empty gameobject and place the empty gameobject at the targets position. Now you just rotate this empty gameobject and have the camera offset in local space to "-dist" on the z axis. If you don't want to use that approach you can also first calculate the new totation and then place the camera at the target position offset at "-forward*dist"

2 Replies

· Add your reply
  • Sort: 
avatar image
1

Answer by Eno-Khaon · May 09, 2015 at 10:32 AM

First off, I believe the key problem you're encountering is Gimbal Lock, an incidental result of Euler Angles to calculate rotation (i.e. 0-360 degrees).

Essentially, there are multiple ways of representing the same rotation. Rotating 180 degrees on the Y axis can also be achieved by rotating 180 degrees on both the X and Z axes. Unity doesn't know which is intended, since they both look the same to it and are fundamentally being calculated as Quaternion rotations first.

With that out of the way... If I follow your description correctly, you're using transform.LookAt to follow the character. One simple approach to this would be to make use of the overloaded function transform.LookAt(Target, WorldUp). You could use something like

 // C#
 float orientationFix = Mathf.Abs(Vector3.Dot(targetPosition - cameraPosition, Vector3.Up));
 Vector3 newUpVector = Vector3.Lerp(Vector3.up, Vector3.forward, orientationFix);
 cameraObj.transform.LookAt(playerObj, newUpVector);

as a simple remedy to the problem. The use of Vector3.forward could be retooled based on the needs for your game.

That said, there are much more elegant and effective solutions to this problem (using much more thorough implementations of Quaternion rotations), but this should provide a smooth transition between perspectives, where the view would lean in and out based on the camera's current position.

Edit: I apologize if my example doesn't fit your orientations as intended, but I had a tough time following exactly how this is all being handled.

Comment
Add comment · Show 2 · 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 canis · May 09, 2015 at 11:36 AM 0
Share

Thanks for your help, but may I ask, why you using

float orientationFix = $$anonymous$$athf.Abs(Vector3.Dot(FacingDirection, Vector3.up));

I not so sure Vector3.Dot 's usage in this code. and why use it as a percent reference to find out newUpVector ?? seems like it's one more step closer to the right answer..

avatar image canis · May 09, 2015 at 01:50 PM 0
Share

@$$anonymous$$o $$anonymous$$haon sorry, my misstake, you idea seems solve a part of problem,

https://youtu.be/_e1g_Xq_R6g here is the result (red line = upward reference),

however, when the upward reference geting pass its zero-point, the issue still remain. but now the zero-point no longer at the world's up/down direction.

avatar image
0

Answer by Bunny83 · May 09, 2015 at 12:17 PM

This is a fully working space-orientation orbit cam. When you don't assign a target it acts like a freelook cam.

 using UnityEngine;
 using System.Collections;
 
 public class OrbitCam : MonoBehaviour
 {
     public Transform target;
     public float dist = 10f;
     void LateUpdate ()
     {
         var r = transform.rotation;
         if (Input.GetMouseButton(0))
         {
             r = Quaternion.AngleAxis(Input.GetAxis("Mouse X"), transform.up) * r;
             r = Quaternion.AngleAxis(-Input.GetAxis("Mouse Y"), transform.right) * r;
         }
         r = Quaternion.AngleAxis(Input.GetAxis("Horizontal"), transform.forward) * r;
         transform.rotation = r;
         if (target != null)
         {
             transform.position = target.position - transform.forward * dist;
         }
     }
 }


Since you rotate around local axes you can already end up with any orientation even when you only rotate around two axes. That's why i added the rotation around the forward axis as well. You might want to use a different input than Horizontal for that ^^. Very common keys are "e" and "q" (like in space engineers as far as i remember).

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

21 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 avatar image avatar image avatar image

Related Questions

nullifying targetObject after a Smooth LookAt Transition 2 Answers

Keep camera at certain distance from character when rotating 3 Answers

Get a child object to rotate a parent to the cameras direction -1 Answers

Player rotation = Camera Rotation 0 Answers

RTS Camera movement wrong after rotation 1 Answer


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