Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 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 /
  • Help Room /
avatar image
0
Question by unity_QPt4yqS82mflYg · Apr 03, 2020 at 04:30 PM · camera3dcamera-movementplayer movement

Third person Camera rotation problem

Howdy I'm working on a third person game. I have a problem with the camera when I rotate it on the Y axis. This changes its position X when it reaches a certain rotation. I want to keep the X position that I have when I rotate the camera but I do not succeed .. Here is a video with what happens: https://drive.google.com/open?id=1fY0AivmvUDfHzVuNfs35YxP16T_9RcmF

Below is the code:

cameraController.cs

 public class CameraController : MonoBehaviour
  {
  
      public Transform target; //Player
      public Transform pivot; //Pivot for rotating camera
      public Vector3 offset;
      public bool useOffsetValues;
      public float rotateSpeed;
      public float maxViewAngle;
      public float minViewAngle;
      public bool invertY;
  
      void Start()
      {
        if (!useOffsetValues)
        {
          offset = target.position - transform.position;
        }
        pivot.transform.position = target.transform.position;
        //pivot.transform.parent = target.transform;
        pivot.transform.parent = null;
  
        Cursor.lockState = CursorLockMode.Locked; //Hides Mouse's Cursor
      }
  
      void LateUpdate()
      {
        pivot.transform.position = target.transform.position;
        //Rotating Player by Mouse X Axis
        float horizontal = Input.GetAxis("Mouse X") * rotateSpeed;
        pivot.Rotate(0, horizontal, 0);
  
        //Rotating Player's Pivot by Mouse Y Axis
        float vertical = Input.GetAxis("Mouse Y") * rotateSpeed;
        //pivot.Rotate(-vertical, 0, 0);
        if (invertY)
        {
          pivot.Rotate(vertical, 0, 0);
        } else
        {
          pivot.Rotate(-vertical, 0, 0);
        }
  
        //Limit up/down Camera rotation
        if (pivot.rotation.eulerAngles.x > maxViewAngle && pivot.rotation.eulerAngles.x < 180f)
        {
          pivot.rotation = Quaternion.Euler(maxViewAngle, pivot.rotation.eulerAngles.y, 0);
        }
        if (pivot.rotation.eulerAngles.x > 180f && pivot.rotation.eulerAngles.x < 360f + minViewAngle)
        {
          pivot.rotation = Quaternion.Euler(360f + minViewAngle, pivot.rotation.eulerAngles.y, 0);
        }
  
        //Rotate Camera by Mouse X Axis
        float desiredYAngle = pivot.eulerAngles.y;
        float desiredXAngle = pivot.eulerAngles.x;
        Quaternion rotation = Quaternion.Euler(desiredXAngle, desiredYAngle, 0);
        transform.position = target.position - (rotation * offset);
  
        //Camera follow Player
        if (transform.position.y < target.position.y)
        {
          transform.position = new Vector3(transform.position.x, target.position.y -.5f, transform.position.z);
        }
        transform.LookAt(target);
      }
  }

playerController.cs

 public class PlayerController : MonoBehaviour
 {
 
     public float moveSpeed;
     public float jumpForce;
     public CharacterController controller;
     public float gravityScale;
     public Animator anim;
     public Transform pivot;
     public float rotateSpeed;
     public GameObject playerModel;
 
     private Vector3 moveDirection;
 
     void Start()
     {
       controller = GetComponent<CharacterController>();
     }
 
     void Update()
     {
       float yStore = moveDirection.y;
       moveDirection = (transform.forward * Input.GetAxis("Vertical")) + (transform.right * Input.GetAxis("Horizontal"));
       moveDirection = moveDirection.normalized * moveSpeed;
       moveDirection.y = yStore;
 
       if (controller.isGrounded)
       {
         moveDirection.y = 0f;
         if (Input.GetButtonDown("Jump"))
         {
           moveDirection.y = jumpForce;
         }
       }
 
       //Applying gravity
       moveDirection.y = moveDirection.y + (Physics.gravity.y * gravityScale * Time.deltaTime);
       controller.Move(moveDirection * Time.deltaTime);
 
       if (Input.GetAxisRaw("Horizontal") != 0 || Input.GetAxisRaw("Vertical") != 0)
       {
         transform.rotation = Quaternion.Euler(0f, pivot.rotation.eulerAngles.y, 0);
         Quaternion newRotation = Quaternion.LookRotation(new Vector3(moveDirection.x, 0f, moveDirection.z));
         playerModel.transform.rotation = Quaternion.Slerp(playerModel.transform.rotation, newRotation, rotateSpeed * Time.deltaTime);
       }
 
       anim.SetBool("isGrounded", controller.isGrounded);
       anim.SetFloat("Speed", (Mathf.Abs(Input.GetAxis("Vertical")) + Mathf.Abs(Input.GetAxis("Horizontal"))));
     }
 }
 


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

2 Replies

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

Answer by streeetwalker · Apr 03, 2020 at 08:50 PM

@unity_QPt4yqS82mflYg, I don't see where the problem is, but the code seems a bit complicated. For one, the pivot rotation is calculated and clamped on the x and y axes, and the Eulers are extracted from that to create to create the final rotation. Maybe I'm missing it, but not just apply the pivot rotation directly and skip that step?

Have you put a debugging statement in the see what the Euler values of x and y when it happens? You might be hitting some kind floating point rounding problem if the values are very small, and you are extracting them from a Quaternion and then applying them to another Quaternion - I don't know.

Another thing that probably does not anything to do with it, but I think the code should calculate the offset of the camera in every frame.

Here is a script I wrote from scratch about a month ago that seems to work perfectly. You can limit both axes rotation, lock both, or let them rotate free. The only thing it does not do yet is "chase" the player - the offset distance to the camera does not change, so the camera remains locked to the player. In the Update loop, you'll need to delete all the mouse down statements, and just leave the 2 input statements.

 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 public class CameraFollow : MonoBehaviour {
 
     [Header( "Target" )]
     public Transform target;
     [Header( "Camera will be placed behind target", order = 1 )]
     [Header( "At distance and Min Pitch Degrees", order = 2 )]
     [Header(" ", order = 2 )]
     public float distance = 3.5f;
     
     [Header( "Camera Rotation Speeds" )]
     public float y_sensitivity = 1f;
     public float x_sensitivity = 1f;
 
     [Header( "Rotation Clamps In Degrees -180 to 180", order = 1 )]
     [Header( "Max < Min Free Rotation, Min = Max Lock Rotation", order = 2 )]
 
 
     public float maxPitchDegrees = 70f;
     public float minPitchDegrees = 20f;
     public float maxYawDegrees = 90f;
     public float minYawDegrees = -90f;
 
     [Header( "Rotation Clamp Overrides" )]
     public bool pitchRotLocked = false;
     public bool yawRotLocked = false;
     public bool pitchRotFree = false;
     public bool yawRotFree = false;
 
     // Other private variables
     private Vector3 offset;
     private float pitch, yaw;
     private Quaternion oldTargetRotation;
     private bool dragging = false;
     private Transform my; // shortcut to this camera transform
     private Transform tg; // shortcut to the target
 
     void Start() {
 
         my = transform; // make short cuts
         tg = target;
 
         // set my position using distance and minPitchDegrees
         float z = Mathf.Sin( minPitchDegrees ) * distance;
         float y = Mathf.Cos( minPitchDegrees ) * distance;
         my.position = new Vector3( tg.position.x,
             tg.position.y + y, tg.position.z - z );
         my.LookAt( tg.transform, Vector3.up ); // start out focusing on object
 
         // record these for use later
         offset = my.position - tg.position;
         oldTargetRotation = tg.transform.rotation;
 
     }
 
     // Update
     void Update() {
         // Get axis of X & Y using mouse to use when we
         // orbit the mouse around the object
         // here we are making the user left click and drag
         // if you want rotation without dragging, delete all the mousedown code
         //
         if( Input.GetMouseButtonDown( 0 ) ) {
             dragging = true;
         }
 
         if( Input.GetMouseButtonUp( 0 ) ) {
             dragging = false;
         }
 
         pitch = 0;
         yaw = 0;
         if( Input.GetMouseButton( 0 ) && dragging ) {
             if( !pitchRotLocked ) pitch = Input.GetAxis( "Mouse Y" ) * y_sensitivity;
             if( !yawRotLocked ) yaw = Input.GetAxis( "Mouse X" ) * x_sensitivity;
         }
     }
 
     private void FixedUpdate() {
 
         // For each input axis:
         // 1 if have input axis motion
         // 2    if we do not have free rotation we need to clamp rotation:
         // 3        get preview angle for rotateAround for each axis:
         // 3.a            subtract any target rotation then
         // 3.b            add to rotateAround angle
         // 4        get preview angle in min/max degrees
         // 5        clamp preview angle to min/max if input in direction of limit
         // 6        if rotation allowed, rotate around
         // 7    else free rotate around
         //
         if( Mathf.Abs( pitch ) > 0 ) { // 1
             if( !pitchRotFree ) {  // 2
                 Vector3 prevAngle = ( ( my.rotation * Quaternion.Inverse( tg.rotation ) ) *
                     Quaternion.AngleAxis( pitch, -my.right ) ).eulerAngles; // 3.a & 3.b
                 float xDeg = RotToDeg( prevAngle.x ); // 4
                 if( xDeg < minPitchDegrees && pitch > 0 ) pitch = 0; // 5
                 else if( xDeg > maxPitchDegrees && pitch < 0 ) pitch = 0; // 5
                 if( Mathf.Abs( pitch ) > 0 ) my.RotateAround( tg.position, -my.right, pitch ); // 6
             } else my.RotateAround( tg.position, -my.right, pitch ); // 7
         }
 
         if( Mathf.Abs( yaw ) > 0 ) { // 1
             if( !yawRotFree ) { // 2
                 Vector3 prevAngle = ( ( my.rotation * Quaternion.Inverse( tg.rotation ) ) *
                     Quaternion.AngleAxis( yaw, Vector3.up ) ).eulerAngles; // 3.a & 3.b
                 float yDeg = RotToDeg( prevAngle.y ); // 4
                 if( yDeg < minYawDegrees && yaw < 0 ) yaw = 0; // 5
                 else if( yDeg > maxYawDegrees && yaw > 0 ) yaw = 0; // 5
                 if( Mathf.Abs( yaw ) > 0 ) my.RotateAround( tg.position, Vector3.up, yaw ); // 6
             } else my.RotateAround( tg.position, -my.right, pitch ); // 7
         }
 
         // update my offset vector of any rotateAround based on target position
         offset = my.position - tg.position;
 
         // update my offset vector if we have rotated my target in its movement script
         // 1 if the current target rotation != to last frame's target rotation:
         // 2    subtract the current target rotation from old rotation to get the difference
         // 3    add the difference to my current offset vector
         // 4    add the difference to my current rotation
         // 5    reset old target rotation for next frame
         //
         if( Quaternion.Dot( tg.rotation, oldTargetRotation ) <= 1f - 0.000001f ) { // 1
             Quaternion deltaRot = tg.rotation * Quaternion.Inverse( oldTargetRotation ); // 2
             offset = deltaRot * offset; // 3
             my.rotation = deltaRot * my.rotation; // 4
             oldTargetRotation = tg.rotation; // update for next time around
         }
         // finally, apply all the offset changes to my position
         my.position = tg.position + offset;
     }
 
     private float RotToDeg( float rot ) {
         float deg = 0;
         if( rot > 180f ) {
             deg = rot - 360f;
         } else {
             deg = rot;
         }
         return deg;
     }
 
     private void OnValidate() {
         if( maxPitchDegrees > 180 ) {
             maxPitchDegrees = 180;
         } else if( maxPitchDegrees < -180 ) {
             maxPitchDegrees = -180;
         }
         if( minPitchDegrees >= maxPitchDegrees ) {
             minPitchDegrees = maxPitchDegrees;
             pitchRotLocked = true;
         } else if( minPitchDegrees < -180 ) {
             minPitchDegrees = -180;
             pitchRotLocked = false;
         }
 
         if( maxYawDegrees > 180 ) {
             maxYawDegrees = 180;
         } else if( maxYawDegrees < -180 ) {
             maxYawDegrees = -180;
         }
         if( minYawDegrees >= maxYawDegrees ) {
             minYawDegrees = maxYawDegrees;
             yawRotLocked = true;
         } else if( minYawDegrees < -180 ) {
             minYawDegrees = -180;
             yawRotLocked = false;
         }
     }
 }
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
avatar image
0

Answer by unity_QPt4yqS82mflYg · Apr 03, 2020 at 10:06 PM

@streeetwalker Thanks for your answer, but I think the problem is from here..

 if (pivot.rotation.eulerAngles.x > maxViewAngle && pivot.rotation.eulerAngles.x < 180f)
         {
           pivot.rotation = Quaternion.Euler(maxViewAngle, pivot.rotation.eulerAngles.y, 0);
         }
         if (pivot.rotation.eulerAngles.x > 180f && pivot.rotation.eulerAngles.x < 360f + minViewAngle)
         {
           pivot.rotation = Quaternion.Euler(360f + minViewAngle, pivot.rotation.eulerAngles.y, 0);
         }

Or here

 //Rotate Camera by Mouse X Axis
       float desiredYAngle = pivot.eulerAngles.y;
       float desiredXAngle = pivot.eulerAngles.x;
       Quaternion rotation = Quaternion.Euler(desiredXAngle, desiredYAngle, 0);
       transform.position = target.position - (rotation * offset);

I can't figure out.. 2 days of searching and modifying and nothing.. I also tried as you said to take offset for each frame, but then the camera starts to spin very fast and does not keep the values.

I followed this tutorial for the camera. https://www.youtube.com/watch?v=VH5kS1Pjdyk&list=PLiyfvmtjWC_V_H-VMGGAZi7n5E0gyhc37∈dex=10&t=0s

The Y axis of the offset is set to -2. If I change it in 2 it doesn't do the same if I keep the camera on the ground level but if I try to raise it it makes it worse.

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 streeetwalker · Apr 04, 2020 at 04:30 AM 0
Share

@unity_QPt4yqS82mflYg, I just posted code I created. You can compare it with yours, or use it if you want.

If you modify an objects euler rotation directly in the inspector, watch the values of x and y as you rotate. At some point you should note the x flips over. That;s what I was saying, you need to slip a debugger in and see what the angles are when you rotate around and the problem happens.

        Quaternion rotation = Quaternion.Euler(desiredXAngle, desiredYAngle, 0);
        transform.position = target.position - (rotation * offset);
        Debug.Log( "Offset Rotation = " +  (rotation * offset) +  " > Pivot Angles = " + pivot.eulerAngles );
avatar image unity_QPt4yqS82mflYg · Apr 06, 2020 at 11:50 PM 0
Share

@streeetwalker Greetings ! Thanks for the reply. In the debug the position of the camera changes every time the position x of the pivot reaches 360, but still I have not found a way to solve it.

avatar image streeetwalker unity_QPt4yqS82mflYg · Apr 07, 2020 at 06:03 AM 0
Share

@unity_QPt4yqS82mflYg, OK, It's hard to tell from your code, but make sure you are not rotating y on the camera's Y axis, but ins$$anonymous$$d the use the world Vector3.up.

It can be confusing because changing the x rotation changes the height of the camera. It is easier to think in aeronautical terms: rotation on x is $$anonymous$$ch, and rotation on y is Yaw.

Importantly, the order of operations matters, if you pitch the camera, it's local y axis changes.

If you change the $$anonymous$$ch of the camera with respect to its local x transform, and then change its Yaw with respect to its local y, you are spinning around the tilted Y axis.

I may be wrong, but I have a hunch that is causing the problem, and why the effect is more pronounced the greater the $$anonymous$$ch is. You want to $$anonymous$$ch on local x, but Yaw (spin ) everything on world Y.

avatar image unity_QPt4yqS82mflYg streeetwalker · Apr 11, 2020 at 01:09 AM 0
Share

Sorry but i don't understand how to do what you say.. can you show me an example on my code ? 3 days and nothing..

Show more comments

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

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

Related Questions

How to have your player controls change while your camera rotates? 0 Answers

I build a own game but i have a cam problem 0 Answers

How to make camera follow player from point to point 2 Answers

Camera flickers while chasing the player 0 Answers

Mouvement issue with mouse input. 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