How do I reliably get the difference in rotation from frame to frame?

Hi, I’m fairly newish to Unity; very simply, I’m trying to get the change in rotation (in degrees) of an object from one frame to another.
For the purpose of the project, actual rotation of the object is handled by a separate script. The idea is a dial that changes the volume of an audio source depending on which way it rotates and by how much.

My most recent approach consisted of storing the previous rotation and calculating the difference between the current angle of rotation and the saved previous one; this difference in angle would then be applied to the volume change. The issue with this approach comes when the object crosses the 360 degree mark.

Consider the object is at an angle of 20 degrees. It then rotates clockwise 40 degrees. The difference should ideally be 40 degrees clockwise. However, because the new angle of rotation is 340, the difference would amount to 320 degrees COUNTER-clockwise instead of 40 degrees the correct way.

Is there a way to circumvent this “threshold” issue? Or is there a better approach to calculating ACCURATE difference in angle? I would prefer to keep to only changing volume in this script (no actual transformation), but if it’s helpful, the rotating script handles rotations via transform.Rotate()

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class VolumeDial : MonoBehaviour
{

    // sound object to manipulate
    public GameObject soundbox;
    public AudioSource song;

    // volume will change by difference in degrees between curr and prev angles
    public float angle_offset;
    public float angle_curr;
    public float angle_diff;        // (curr - offset)


    // Start is called before the first frame update
    void Start()
    {
       
        song = soundbox.GetComponent<AudioSource>();

        // starting offset
        var radians = Mathf.Atan2(transform.forward.y, -transform.forward.z);
        angle_offset = 180 + radians * Mathf.Rad2Deg;

    }
   

    // Update is called once per frame
    void Update()
    {
       
        // get current angle
        var radians = Mathf.Atan2(transform.forward.y, -transform.forward.z);
        angle_curr = 180 + radians * Mathf.Rad2Deg;

        // get difference in degrees between curr and prev angles
        angle_diff = angle_curr - angle_offset;

        // manipulate volume (don't worry about this one)
        song.volume -= angle_diff/1000;

        // set offset up for next frame
        angle_offset = angle_curr;

    }
}

It’s slightly hard to tell but i believe its simply that you should be doing

angle_curr = 180 - radians * Mathf.Rad2Deg;

If you take the 320 degrees you got from yours and take away 180 to just get the radians multiplied by Rad2Deg then you get 140 which you will find becomes 40 if you do 180 - 140 not 180 + 140 however i may be mistaken and the issue could be different.

thank you, but unfortunately, same issue upon trying; this line is my calculation to get the object’s current rotation from 0-360, which is to then be compared to the previous rotation, angle_offset.

Why is it necessary to get the difference?. Can’t you just use the angle directly?

volume=transform.eulerAngles.z/360.0f;

The difference is necessary as I will change the volume of the attached sound source by a quantity relative to the CHANGE in angle. I don’t want to tie the volume level to the rotation. I want the volume to, say, hypothetically, turn up by 5 if the knob turns clockwise 5 degrees. I want the volume to turn down 20 if the knob turns counter-clockwise 20.

For the sake of my project, tying volume to a proportion of the actual angle wouldn’t feel naturally or make sense.

You’re on the right approach here, but you want to work with quaternions. Probably just recording the quaternion rotation, both current and previous frame, then using Quaternion.Angle will give you a reliable angle in degrees.

1 Like
float previousAngle;
    void Update()
    {
        float angle=transform.eulerAngles.z;
        float diff=Mathf.DeltaAngle(previousAngle,angle);
        previousAngle=angle;
        volume+=diff;
    }