Hello, I am making a car customizer where the player can navigate around the car (like in blender with middle mouse button), but I am running into a problem. I am using RotateAround(), like so:
camTransform.RotateAround(Vector3.zero, transform.up, Input.GetAxis(“Mouse X”) * 3);
camTransform.RotateAround(Vector3.zero, transform.forward, Input.GetAxis(“Mouse Y”) * 3);
camTransform.rotation = Quaternion.Euler(camTransform.eulerAngles.x, camTransform.eulerAngles.y, 0);
My problem is that the camera rotates differently depending on its location. For example, if you look at the car from the side and drag vertically, you rotate around the car’s z axis (like intended). BUT, if you are looking at the car dead on and drag vertically, you still rotate around the car’s z axis (not intended), and your camera just ends up doing a small circle midair. I thought that using transform. up and transform.forward would use the cameras local axes, and I wouldn’t have this problem. But I guess not. All help is appreciated.
Here is the entire script if that helps:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
public class CarBuilder : MonoBehaviour
{
public float LookSpeed = 3;
public float ScrollSpeed = 10;
public float MinFOV = 30;
public float MaxFOV = 120;
private Transform camTransform;
private Camera cam;
private int UILayer;
private bool Clicked;
private void Start()
{
UILayer = LayerMask.NameToLayer("UI");
cam = Camera.main;
camTransform = cam.transform;
camTransform.LookAt(Vector3.zero);
}
private void Update()
{
bool OverUI = IsPointerOverUIElement(GetEventSystemRaycastResults());
if (Input.GetMouseButtonDown(0) && !OverUI)
{
Clicked = true;
}
if (Input.GetMouseButton(0) && Clicked && !OverUI)
{
if (Cursor.lockState == CursorLockMode.None) Cursor.lockState = CursorLockMode.Locked;
camTransform.RotateAround(Vector3.zero, transform.up, Input.GetAxis("Mouse X") * LookSpeed);
camTransform.RotateAround(Vector3.zero, transform.forward, Input.GetAxis("Mouse Y") * LookSpeed);
camTransform.rotation = Quaternion.Euler(camTransform.eulerAngles.x, camTransform.eulerAngles.y, 0);
}
else
{
Clicked = false;
if (Cursor.lockState == CursorLockMode.Locked) Cursor.lockState = CursorLockMode.None;
}
if (Input.GetAxis("Mouse ScrollWheel") > 0f && cam.fieldOfView > MinFOV && !OverUI)
{
cam.fieldOfView -= Input.GetAxis("Mouse ScrollWheel") * ScrollSpeed;
}
else if (Input.GetAxis("Mouse ScrollWheel") < 0f && cam.fieldOfView < MaxFOV && !OverUI)
{
cam.fieldOfView -= Input.GetAxis("Mouse ScrollWheel") * ScrollSpeed;
}
}
private bool IsPointerOverUIElement(List<RaycastResult> eventSystemRaysastResults)
{
for (int index = 0; index < eventSystemRaysastResults.Count; index++)
{
RaycastResult curRaysastResult = eventSystemRaysastResults[index];
if (curRaysastResult.gameObject.layer == UILayer)
return true;
}
return false;
}
static List<RaycastResult> GetEventSystemRaycastResults()
{
PointerEventData eventData = new PointerEventData(EventSystem.current);
eventData.position = Input.mousePosition;
List<RaycastResult> raysastResults = new List<RaycastResult>();
EventSystem.current.RaycastAll(eventData, raysastResults);
return raysastResults;
}
}
For anyone who potentially had the same problem as me - I found a solution. I added a GameObject called PivotPoint where I wanted the camera to rotate around, (0, 0, 0) in my case, then I made the pivot point always face towards the camera on the y axis, like so: “PivotPoint.LookAt(new Vector3(camTransform.position.x, 0, camTransform.position.z), PivotPoint.up);” Then I simply made the RotateAround() lines rotate around the PivotPoint’s local axes, like this: “camTransform.RotateAround(Vector3.zero, PivotPoint.up, Input.GetAxis(“Mouse X”) * LookSpeed); camTransform.RotateAround(Vector3.zero, PivotPoint.right, Input.GetAxis(“Mouse Y”) * LookSpeed); camTransform.rotation = Quaternion.Euler(camTransform.eulerAngles.x, camTransform.eulerAngles.y, 0);”. Hope this helped