Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

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

Discussion in 'Scripting' started by cannedcorgies, Jul 12, 2023.

  1. cannedcorgies

    cannedcorgies

    Joined:
    Jun 27, 2021
    Posts:
    3
    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()

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class VolumeDial : MonoBehaviour
    6. {
    7.  
    8.     // sound object to manipulate
    9.     public GameObject soundbox;
    10.     public AudioSource song;
    11.  
    12.     // volume will change by difference in degrees between curr and prev angles
    13.     public float angle_offset;
    14.     public float angle_curr;
    15.     public float angle_diff;        // (curr - offset)
    16.  
    17.  
    18.     // Start is called before the first frame update
    19.     void Start()
    20.     {
    21.        
    22.         song = soundbox.GetComponent<AudioSource>();
    23.  
    24.         // starting offset
    25.         var radians = Mathf.Atan2(transform.forward.y, -transform.forward.z);
    26.         angle_offset = 180 + radians * Mathf.Rad2Deg;
    27.  
    28.     }
    29.    
    30.  
    31.     // Update is called once per frame
    32.     void Update()
    33.     {
    34.        
    35.         // get current angle
    36.         var radians = Mathf.Atan2(transform.forward.y, -transform.forward.z);
    37.         angle_curr = 180 + radians * Mathf.Rad2Deg;
    38.  
    39.         // get difference in degrees between curr and prev angles
    40.         angle_diff = angle_curr - angle_offset;
    41.  
    42.         // manipulate volume (don't worry about this one)
    43.         song.volume -= angle_diff/1000;
    44.  
    45.         // set offset up for next frame
    46.         angle_offset = angle_curr;
    47.  
    48.     }
    49. }
    50.  
     
  2. DapperMonke

    DapperMonke

    Joined:
    Apr 19, 2022
    Posts:
    5
    It's slightly hard to tell but i believe its simply that you should be doing
    Code (CSharp):
    1. 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.
     
  3. cannedcorgies

    cannedcorgies

    Joined:
    Jun 27, 2021
    Posts:
    3
    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.
     
  4. zulo3d

    zulo3d

    Joined:
    Feb 18, 2023
    Posts:
    510
    Why is it necessary to get the difference?. Can't you just use the angle directly?

    volume=transform.eulerAngles.z/360.0f;
     
  5. cannedcorgies

    cannedcorgies

    Joined:
    Jun 27, 2021
    Posts:
    3
    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.
     
  6. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    5,769
    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.
     
  7. zulo3d

    zulo3d

    Joined:
    Feb 18, 2023
    Posts:
    510
    Code (CSharp):
    1. float previousAngle;
    2.     void Update()
    3.     {
    4.         float angle=transform.eulerAngles.z;
    5.         float diff=Mathf.DeltaAngle(previousAngle,angle);
    6.         previousAngle=angle;
    7.         volume+=diff;
    8.     }