Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice
  3. Dismiss Notice

Question Help rotating camera around point in world

Discussion in 'Scripting' started by UtterBob, May 15, 2024.

  1. UtterBob

    UtterBob

    Joined:
    Apr 11, 2024
    Posts:
    4
    Making an RTS-style camera and having some issues with rotation. The camera is at a fixed perspective angle (see screenshot) but can move, zoom and rotate (well, nearly rotate). I have the rotation working beautifully but only around the camera's local y axis. I want to rotate around the current focal point.

    Quick disclaimer: Both the simple rotation code and the newer rotateAround code are in here because I've been trying many different things. I usually just comment out whatever I'm not using for each test iteration.

    Inside FixedUpdate()
    Code (CSharp):
    1. if (isRotating)
    2.             {
    3.                 // Disable edge scrolling so mouse has infinite lateral potential & no confusing movement for dragging too far.
    4.                 allowEdgeScroll = false;
    5.  
    6.                 // Cast a ray from the camera's position along its forward direction
    7.                 RaycastHit hit;
    8.                 if (Physics.Raycast(cameraInstance.transform.position, cameraInstance.transform.forward, out hit, Mathf.Infinity, LayerMask.GetMask("Ground")))
    9.                 {
    10.                     // Use the hit point as the rotation point
    11.                     rotationAxis = hit.point;
    12.                 }
    13.                 else
    14.                 {
    15.                     // If no intersection with 'Ground' layer, use a default rotation point (e.g., origin)
    16.                     rotationAxis = Vector3.zero;
    17.                 }
    18.  
    19.                 // Calculate rotation delta based on mouse movement
    20.                 rotationMouseDelta = Mouse.current.delta.ReadValue();
    21.  
    22.                 // Apply rotation around the rotation point in world space
    23.                 Quaternion rotationDelta = Quaternion.AngleAxis(rotationMouseDelta.x * Time.fixedDeltaTime * rotationSpeed, Vector3.up);
    24.  
    25.                 // Apply rotation to the camera's local position
    26.                 rotationTarget = rotationDelta * rotationTarget;
    27.             }
    Inside LateUpdate()

    Code (CSharp):
    1.             // Apply rotation only if isRotating is true
    2.             if (isRotating)
    3.             {
    4.                 Debug.Log(rotationAxis);
    5.                 // Rotate around the rotation axis in world space
    6.                 transform.RotateAround(rotationAxis, Vector3.up, rotationMouseDelta.x * Time.deltaTime * rotationSpeed);
    7.  
    8.                 // Slerp the camera's rotation towards the rotation target
    9.                 //transform.rotation = Quaternion.Slerp(transform.rotation, rotationTarget, Time.deltaTime * rotationSmoothing);
    10.             }
    At the moment, I can either use rotatearound and get a very choppy rotation that also nudges the camera x, z, in the direction of rotation or; a beautifully smooth slerp. However, both rotate the camera around its local y, not the hit.point.

    I have done some debugging and can confirm the ray cast is working and setting the point correctly.

    Would love to know where I'm going wrong and/or if I've missed another way of doing this altogether?

    Many thanks!
     

    Attached Files:

    Last edited: May 16, 2024
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    39,382
    Camera stuff is pretty tricky... I hear all the Kool Kids are using Cinemachine from the Unity Package Manager.

    There's even a dedicated forum: https://forum.unity.com/forums/cinemachine.136/

    If you insist on making your own camera controller, do not fiddle with camera rotation.

    The simplest way to do it is to think in terms of two Vector3 points in space: where the camera is LOCATED and where the camera is LOOKING.

    Code (csharp):
    1. private Vector3 WhereMyCameraIsLocated;
    2. private Vector3 WhatMyCameraIsLookingAt;
    3.  
    4. void LateUpdate()
    5. {
    6.   cam.transform.position = WhereMyCameraIsLocated;
    7.   cam.transform.LookAt( WhatMyCameraIsLookingAt);
    8. }
    Then you just need to update the above two points based on your GameObjects, no need to fiddle with rotations. As long as you move those positions smoothly, the camera will be nice and smooth as well, both positionally and rotationally.
     
  3. UtterBob

    UtterBob

    Joined:
    Apr 11, 2024
    Posts:
    4
    I have come across Cinemachine. The purpose of this project is a learning experience, so I was keen to tackle it myself but I might have to just accept rotation is too much too soon and move on to other things.

    Hmmm, I was assuming that rotateAround was doing exactly that. The ray finds what I'm looking at, the current transform is where I am... I'll start testing that idea, thanks!

    Ps. Goldens best doggos.
     
  4. UtterBob

    UtterBob

    Joined:
    Apr 11, 2024
    Posts:
    4
    My mistake. I was only using the forward to experiment with and copied the wrong thing for the OP. I've updated it.

    But yeah... This code is what is causing the behaviour I described. Although, now that I think about it, both rotationAxis and camera forward were giving the same results!
     
  5. UtterBob

    UtterBob

    Joined:
    Apr 11, 2024
    Posts:
    4
    Well, for anyone else searching and stumbling across this. It was another code in LateUpdate that was causing the problem; I just had to return; out of LateUpdate to skip other movement code interfering, and this code worked as is.