Home > Blockchain >  How to measure Z rotation accurately with rapid changes
How to measure Z rotation accurately with rapid changes

Time:01-01

I am programming a game in unity and for one of the games enemies I wanted their sword to rotate in a 180 degree arc in front of them, I was able to make the sword rotate around the enemy but when I try to check if it has done the full arc it does not measure it properly since it is rotating at such high speeds.

    public GameObject pivotPoint;
    public SpriteRenderer renderer;


    // Start is called before the first frame update
    void Start()
    {
        StartCoroutine("rotate");
    }

    IEnumerator rotate()
    {
    renderer.enabled = true;
    yield return new WaitForSeconds(2);
    while(true)
    {
        transform.RotateAround(pivotPoint.transform.position, new Vector3(0, 0, 1), -1 * Time.deltaTime);
        if(transform.eulerAngles.z >= -47)
        {
            if(transform.eulerAngles.z > 132)
            {
                renderer.enabled = false;
                StopCoroutine("rotate");
            }
        }
        yield return null; 
    }
    yield return null;
    }

I have tried using fixed delta time which made it a lot worse and tried to play around with the checks just to hopefully find a sweet spot where it could consitently get the right number but none have worked so far.

CodePudding user response:

First, I'm not sure how this is a problem, because it looks like you're rotating 1 degree per second, so it should take 3 minutes (180 seconds) to rotate 180 degrees.

Regardless, assuming you're changing the speed to something faster, you're going to have trouble getting Euler angles out of the rotation because they may be limited to /- 90 degrees or similar.

I think you'd be better off accumulating the fractional angle and checking that. I don't understand your nested if statements, because the angle must be >= -47 if it's > 132, I I'll drop it and rewrite your code as follows:

float totalAngle = 0f;
while(true)
{
    float speed = -1f;
    float fractionalAngle = speed * Time.deltaTime; 
    transform.RotateAround(pivotPoint.transform.position, Vector3.up, fractionalAngle);
    totalAngle  = fractionalAngle;
    if(fractionalAngle < -180)
    {
        renderer.enabled = false;
        StopCoroutine("rotate");
    }
    yield return null; 
}

You were asking about 180 so I made it 180. Your code had -1 so I left the speed negative and went to -180. Change speed to get it faster.

CodePudding user response:

I wouldn't use eulerAngles here at all but rather track how much you have rotated and make sure you rotate exactly 180°.

// Adjust this via the Inspector 
public float anglePerSecond = 90f;

IEnumerator Start()
{
    renderer.enabled = true;
    yield return new WaitForSeconds(2);

    var rotated = 0f;

    while(rotated < 180f)
    {
        var step = Mathf.Min(anglePerSecond * Time.deltaTime, 180 - rotated);
        transform.RotateAround(pivotPoint.transform.position, Vector3.forward, -step);

        rotated  = step;
    
        yield return null; 
    }

    renderer.enabled = false;
}
  • Related