Tuesday, October 25, 2022
HomeGame Developmentunity - How can I replace my kinematic object's rotation based mostly...

unity – How can I replace my kinematic object’s rotation based mostly on how a lot it has moved per body?


TLDR: A circle will rotate 360 levels each time it travels a distance equal to its circumference.

I stumbled upon the Coin Rotation Paradox, which helped me to higher perceive this downside.

A circle with radius r = 1 has a circumference 2 * Pi * 1 = 6.28. Rolling this circle round one other circle with radius r = 3 and circumference 2 * Pi * 3 = 18.84 causes the circle to finish 4 360 diploma rotations, which appears counter intuitive as a result of the circumference of the circle round which it’s rotating is just 3 times as giant. However the path of movement across the bigger circle can be a circle with radius r = 1 + 3, the space of each the unique circles’ radii added collectively. The preliminary circle will thus transfer a complete distance of 4 occasions its circumference, or 2 * Pi * (3 + 1) = 25.12. This path is proven beneath in blue:

enter image description here

Which means that a circle will rotate 360 levels each time it travels a distance equal to its circumference. Certainly, the cited Wikipedia article exhibits that rolling the unique circle over the straight line constituted of the unraveled circumference of the second circle with radius r = 3 causes that circle to solely rotate 3 times, as the entire distance traveled is simply 3 occasions its circumference.

So, to rotate a circle because it strikes across the sport:

  1. Discover the circumference of the circle
  2. Get the quantity moved this body
  3. Divide this quantity by the circumference to get the ratio of motion : circumference
  4. Add to or subtract from the circle’s z rotation this ratio multiplied by 360
utilizing UnityEngine;

[RequireComponent(typeof(CircleCollider2D))]
public class RotatingCircle : MonoBehaviour
{
    [SerializeField]
    personal float moveSpeed = 9f;
    [SerializeField]
    personal float acceleration = 25f;
    [SerializeField]
    personal float reverseTime = 3f;

    personal CircleCollider2D circleCollider;
    personal float circumference;

    personal float velocityX = 0;
    personal float directionX = 1;

    personal float timer = 0;

    personal void Awake()
    {
        circleCollider = GetComponent<CircleCollider2D>();
        circumference = 2 * Mathf.PI * (circleCollider.radius * remodel.localScale.x);
    }

    personal void Replace()
    {
        MoveAndRotate();
    }

    personal void MoveAndRotate()
    {
        if (timer >= reverseTime)
        {
            directionX *= -1;
            timer = 0;
        }

        // Transfer
        velocityX = Mathf.MoveTowards(velocityX, moveSpeed * directionX, acceleration * Time.deltaTime);
        remodel.Translate(Vector2.proper * velocityX * Time.deltaTime, Area.World);

        // Rotate
        float movementToCircumferenceRatio = Mathf.Abs(velocityX * Time.deltaTime) / circumference;
        float rotationAmount = 360 * movementToCircumferenceRatio;

        float targetRotationZ = remodel.eulerAngles.z - rotationAmount * Mathf.Signal(velocityX);
        Quaternion targetRotation = Quaternion.Euler(0, 0, targetRotationZ);
        remodel.rotation = targetRotation;

        timer += Time.deltaTime;
    }
}

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

- Advertisment -
Google search engine

Most Popular

Recent Comments