Rotate UI Image With Radial Dial

I am trying to rotate an Image by rotate a dial. I have tried rotating the image itself by touch but that caused more issues becuase I also have a resize script attached to it so it was all funky. Now my approach is to use a radial dial to rotate it a complete 360 on the Z axis while also rotating the dial to match. But for some reason nothing I use works. I’ve tried quaternian, transform.rotate, etc. I have also tried onmousedrag and IBeginDragHandler events and it only moves the dial .079th of the way. Wondering if anyone has had the same issue? Attached is my dial.

using System;
using UnityEngine;
using UnityEngine.EventSystems;

public class DragRotate : MonoBehaviour, IDragHandler, IBeginDragHandler, IEndDragHandler, IPointerDownHandler
{
    // This event echoes the new local angle to which we have been dragged
    public event Action<Quaternion> OnAngleChanged;

    Quaternion dragStartRotation;
    Quaternion dragStartInverseRotation;


    private void Awake()
    {
        // As an example: rotate the attached object
        OnAngleChanged += (rotation) => transform.localRotation = rotation;
    }


    // This detects the starting point of the drag more accurately than OnBeginDrag,
    // because OnBeginDrag won't fire until the mouse has moved from the point of mousedown
    public void OnPointerDown(PointerEventData eventData)
    {
        dragStartRotation = transform.localRotation;
        Vector3 worldPoint;
        if (DragWorldPoint(eventData, out worldPoint))
        {
            // We use Vector3.forward as the "up" vector because we assume we're working in a Canvas
            // and so mostly care about rotation around the Z axis
            dragStartInverseRotation = Quaternion.Inverse(Quaternion.LookRotation(worldPoint - transform.position, Vector3.forward));
        }
        else
        {
            Debug.LogWarning("Couldn't get drag start world point");
        }
    }

    public void OnBeginDrag(PointerEventData eventData)
    {
        // Do nothing (but this has to exist or OnDrag won't work)
    }
    public void OnEndDrag(PointerEventData eventData)
    {
        // Do nothing (but this has to exist or OnDrag won't work)
    }

    public void OnDrag(PointerEventData eventData)
    {
        Vector3 worldPoint;
        if (DragWorldPoint(eventData, out worldPoint))
        {
            Quaternion currentDragAngle = Quaternion.LookRotation(worldPoint - transform.position, Vector3.forward);
            if (OnAngleChanged != null)
            {
                OnAngleChanged(currentDragAngle * dragStartInverseRotation * dragStartRotation);
            }
        }
    }


    // Gets the point in worldspace corresponding to where the mouse is
    private bool DragWorldPoint(PointerEventData eventData, out Vector3 worldPoint)
    {
        return RectTransformUtility.ScreenPointToWorldPointInRectangle(
            GetComponent<RectTransform>(),
            eventData.position,
            eventData.pressEventCamera,
            out worldPoint);
    }
}
4 Likes

I will implement this in the morning. I made something similar to this but I didnt use OnPointerDown. That may have been my downfall.

I also didnt use OnDragEnd or OnBeginDrag. I wasnt aware those needed to be in without being used. The more I learn lol

Yeah, there seems to be an undocumented rule that you’re not allowed to implement IDragHandler without also implementing IBeginDragHandler and IEndDragHandler. I only figured that out experimentally. I think it’s very foolish–either they should be combined into a single interface with multiple functions, or you should be allowed to implement only the ones you need.

As a general debugging tip: if your code doesn’t appear to be doing anything at all, you should add Debug statements to make sure it is executing.

1 Like

Oh i used Debug and it was working, but like i said it was moving the object .079th of the way. I could see the Z rot firing in inspector but it wouldn’t go past the mark. Im assuming because it wasnt seeing a drag end. it was very weird to say the least. I’ve used the same rotation script kind of like the one you have but its always been in update function or another. This is the first time ive used a drag handler. Thanks for your help buddy. I will add the code now and see how that fires off for me lol

Ok, so the script worked wonders. The only issue now is to reset the x,y,z axis so fit the new rotation. Since i have a drag/move script attached it messes with direction. Up is left… etc…