Rotating dials with increments, one works and the others doesn't. Why?

I have 4 dials that rotate by increments when the players drag them. They all exactly have the same code, but I can't figure out why only one of the dial works as intended (dial 2). My code stops working as intended on other dials when I change the increment count to 4, the other dials rotate a quarter and then stops to move when I drag them.

Here's my class attached to the dial.

public class Rotate2d : MonoBehaviour
{
float previousRotation;
float currentRotation;

void Update()
{
RotateObject();
}

public static float DegreesCCWFromRight(Vector2 center, Vector2 pointer)
{
var direction = pointer - center;
}

//v2 rotate with incremental snapping
private void RotateObject()
{
Vector2 worldPoint = Camera.main.ScreenToWorldPoint(Input.mousePosition);
RaycastHit2D hit = Physics2D.Raycast(worldPoint, Vector3.forward);

if (Input.GetMouseButtonDown(0))
{
if (hit.collider && hit.collider.GetComponent<Rotate2d>())
{
previousRotation = DegreesCCWFromRight(transform.position, Camera.main.ScreenToWorldPoint(Input.mousePosition));
}
}

else if (Input.GetMouseButton(0))
{
if (hit.collider && hit.collider.GetComponent<Rotate2d>())
{
currentRotation = DegreesCCWFromRight(transform.position, Camera.main.ScreenToWorldPoint(Input.mousePosition));
previousRotation = currentRotation;

Vector2 mouseWorld = Camera.main.ScreenToWorldPoint(Input.mousePosition);
float angle = DegreesCCWFromRight(transform.position, mouseWorld);

const float incrementCount = 4;

angle = Mathf.Round(currentRotation * incrementCount / 360)
* 360 / incrementCount;

hit.collider.gameObject.transform.localEulerAngles = new Vector3(0, 0, angle);

}
}


Here's my Project Hierarchy

Here's each dials inspector

• I've noted two things but I don't know if they will be any help or not: DegreesCCWFromRight should not be static, I think. Using atan2 (multiplied by rad2deg) will give back an angle between (-180, 180), not (0, 360) (I'm not sure if you already knew this or not so I thought mentioning it is good) Jun 21 at 17:08
• @Arian_ki why should it not be static? What instance members do you believe it depends on? Jun 21 at 18:05
• @DMGregory I think it would make problems if you drag your mouse from one dial to another one, but as I said in my comment, I'm not sure Jun 21 at 21:09
• It seems removing hit.collider.gameObject and just using transform.localEulerAngles in the method works, however it rotates other dials upon the start of rotation. Jun 22 at 6:51
• @Arian_ki that is not what the static keyword means. If you're unclear on what this syntax does, you should consider writing a test to find out before offering potentially misleading advice. 2 days ago

The problem is that each Rotate2d has its own independent life cycle, which means that Update will be executed 4 times per frame. If the mouse points to any dial, the four scripts will trigger the corresponding logic.

fix: Determine whether the hit target is the dial itself.

public class Rotate2d : MonoBehaviour
{
float previousRotation;
float currentRotation;

void Update()
{
RotateObject();
}

public static float DegreesCCWFromRight(Vector2 center, Vector2 pointer)
{
var direction = pointer - center;
}

//v2 rotate with incremental snapping
private void RotateObject()
{
Vector2 worldPoint = Camera.main.ScreenToWorldPoint(Input.mousePosition);
RaycastHit2D hit = Physics2D.Raycast(worldPoint, Vector3.forward);

if (!hit.collider)
{
return;
}
var hitRotate2d = hit.collider.GetComponent<Rotate2d>();
if (hitRotate2d != this)
{
return;
}

if (Input.GetMouseButtonDown(0))
{
previousRotation = DegreesCCWFromRight(transform.position, Camera.main.ScreenToWorldPoint(Input.mousePosition));
}
else if (Input.GetMouseButton(0))
{
currentRotation = DegreesCCWFromRight(transform.position, Camera.main.ScreenToWorldPoint(Input.mousePosition));
previousRotation = currentRotation;

Vector2 mouseWorld = Camera.main.ScreenToWorldPoint(Input.mousePosition);
float angle = DegreesCCWFromRight(transform.position, mouseWorld);

const float incrementCount = 4;

angle = Mathf.Round(currentRotation * incrementCount / 360)
* 360 / incrementCount;

hit.collider.gameObject.transform.localEulerAngles = new Vector3(0, 0, angle);
}
}
}

• a simple If solved it! thanks for this! 2 days ago