Search code examples
c#rotationunity-game-enginequaternions

Unity C# Limit Orbit RotateAround Position


So this is my code I've made so far, its for a camera orbiting around a point in space.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Lean.Touch;

public class CameraOrbit : TopClass
{
    [Tooltip("Ignore fingers with StartedOverGui?")]
    public bool ignoreGuiFingers = true;

    [Tooltip("Ignore fingers if the finger count doesn't match? (0 = any)")]
    public int requiredFingerCount = 1;

    [Tooltip("The sensitivity of the movement, use -1 to invert")]
    public float sensitivity = 0.25f;

    public Vector3 target = Vector3.zero;

    protected void LateUpdate()
    {
        // Get the fingers we want to use
        List<LeanFinger> fingers = LeanTouch.GetFingers(ignoreGuiFingers, requiredFingerCount);

        // Get the scaled delta of all the fingers
        Vector2 delta = LeanGesture.GetScaledDelta(fingers);

        transform.RotateAround(target, Vector3.up, delta.x * sensitivity);
        transform.RotateAround(target, Vector3.right, delta.y * sensitivity);

        transform.LookAt(target);
    }
}

This works great so far, however there are 2 things which are annoying and I'm at loss how to fix

  1. The biggest one is when the camera reaches the top things can get weird if the user keeps moving up. The camera starts to kind of turn around, the world kind of spins etc... I want the camera to kind of stop when it gets near the top or bottom.
  2. The camera's rotation can get weird, I want it to always be pointing up and never rotated to the right or left slightly or fully and especially upside down. Just always pointing up.

I've tried these links after lots of Google searching

But none of them worked right or I couldn't get them adapted to what I needed

Any help would be great, thanks in advance


Solution

  • So I found the answer so far, I think. I also had someone play test it and they liked it so I may have found the solution.

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using Lean.Touch;
    
    public class CameraOrbit : TopClass
    {
        [Tooltip("Ignore fingers with StartedOverGui?")]
        public bool ignoreGuiFingers = true;
    
        [Tooltip("Ignore fingers if the finger count doesn't match? (0 = any)")]
        public int requiredFingerCount = 0;
    
        [Tooltip("The sensitivity of the movement, use -1 to invert")]
        public float sensitivity = 0.25f;
    
        public float min = 45f;
        public float max = 315f;
    
        public Vector3 target = Vector3.zero; //this is the center of the scene, you can use any point here
    
        protected void LateUpdate()
        {
            // Get the fingers we want to use
            List<LeanFinger> fingers = LeanTouch.GetFingers(ignoreGuiFingers, requiredFingerCount);
    
            // Get the world delta of all the fingers
            Vector2 delta = LeanGesture.GetScaledDelta(fingers);
    
            transform.RotateAround(target, Vector3.up, delta.x * sensitivity);
            transform.RotateAround(target, Vector3.right, delta.y * sensitivity);
    
            Vector3 angles = transform.eulerAngles;
            angles.x = Mathf.Clamp(angles.x, min, max);
            angles.y = Mathf.Clamp(angles.y, min, max);
            angles.z = 0;
            transform.eulerAngles = angles;
    
            transform.LookAt(target);
        }
    }
    

    If I want the camera to always have the up point up, in my case, its keeping the z-axis at 0. The x and y axis just needed to be kept in check.

    If it helps anyone, the only thing I modified from above is

    ...
    public float min = 45f;
    public float max = 315f;
    ...
    Vector3 angles = transform.eulerAngles;
    angles.x = Mathf.Clamp(angles.x, min, max);
    angles.y = Mathf.Clamp(angles.y, min, max);
    angles.z = 0;
    transform.eulerAngles = angles;
    

    Thanks to @yes for pointing me in the right direction