3

I am rotating a point in relation to another pivot point using the following code:

Vector3 RotatePointAroundPivot(Vector3 point, Vector3 pivot, Vector3 angles) {

    Vector3 dir = point - pivot; // get point direction relative to pivot
    dir = Quaternion.Euler(angles) * dir; // rotate it
    point = dir + pivot; // calculate rotated point
    return point;
}

How can I rotate the point over a specific duration, say 5 seconds using a coroutine?

Programmer
  • 121,791
  • 22
  • 236
  • 328
OnlyCodeMatters
  • 683
  • 1
  • 5
  • 15
  • 1
    See the rotate function from [this](https://stackoverflow.com/questions/37586407/rotate-gameobject-over-time/37588536#37588536) post. Does that help? – Programmer Dec 13 '17 at 05:12
  • 1
    @Programmer from the linked post the rotation is done on a game object with a transform. That makes things a lot simpler. What I am trying to do is a bit different - rotating a point based on another. – OnlyCodeMatters Dec 13 '17 at 06:14
  • It's almost the-same. All you have to do is to add this code in your question inside that function then replace the lerp with `point` variable. Something like this: `Vector3.Lerp(currentRot, point, counter / duration);` – Programmer Dec 13 '17 at 06:18
  • @Programmer what exactly does the line `gameObjectToMove.transform.eulerAngles = Vector3.Lerp(currentRot, newRot, counter / duration);` become? – OnlyCodeMatters Dec 13 '17 at 08:01
  • I see you are still stuck with this. Edit your question with which object/point you are rotating around and which object you are rotating. Just add a complete code to your question and I will put an answer. – Programmer Dec 13 '17 at 08:07
  • @Programmer just edited the question – OnlyCodeMatters Dec 13 '17 at 09:16

1 Answers1

4

Modified the code from my other answer to get this effect. You can read that to understand how lerp work.

What changed and why:

1.Got the beginRotation point from the RotatePointAroundPivot function by passing Vector3.zero to the angle parameter and the current Object position outside of the while loop. This needs to be done once as the result will be used in the while loop.

Vector3 beginRotPoint = RotatePointAroundPivot(objPoint.transform.position, pivot, Vector3.zero);

This is done because lerp needs a starting point. That starting point should never changed otherwise, it break the lerp function.

2.Generate new angle each frame in the while loop. This is done by lerping from Vector3.zero to the target angle:

float t = counter / duration;
Vector3 tempAngle = Vector3.Lerp(Vector3.zero, angles, t);

3.Find the final pivot angle rotation. This is done by passing the starting point from #1 to the first parameter, the pivot point to the second parameter and finally the current angle generated from #2 to the third parameter.

Vector3 tempPivot = RotatePointAroundPivot(beginRotPoint, pivot, tempAngle);

4.Finally, assign the result from #3 to objPoint.transform.position instead of objPoint.transform.eulerAngles because you are not only moving the object. You are also rotating it.

objPoint.transform.position = tempPivot;

Complete code:

Your RotatePointAroundPivot function:

Vector3 RotatePointAroundPivot(Vector3 point, Vector3 pivot, Vector3 angles)
{
    Vector3 dir = point - pivot; // get point direction relative to pivot
    dir = Quaternion.Euler(angles) * dir; // rotate it
    point = dir + pivot; // calculate rotated point

    return point;
}

Modified rotateObject function that I described what changed above:

bool rotating = false;

IEnumerator rotateObject(GameObject objPoint, Vector3 pivot, Vector3 angles, float duration)
{
    if (rotating)
    {
        yield break;
    }
    rotating = true;

    Vector3 beginRotPoint = RotatePointAroundPivot(objPoint.transform.position, pivot, Vector3.zero);

    float counter = 0;
    while (counter < duration)
    {
        counter += Time.deltaTime;

        float t = counter / duration;
        Vector3 tempAngle = Vector3.Lerp(Vector3.zero, angles, t);

        Vector3 tempPivot = RotatePointAroundPivot(beginRotPoint, pivot, tempAngle);
        objPoint.transform.position = tempPivot;
        Debug.Log("Running: " + t);
        yield return null;
    }
    rotating = false;
}

USAGE:

Will rotate object 180-deg around pivot point in 5 seconds:

//The GameObject with the pivot point to move
public GameObject pointToRotate;
//The Pivot point to move the GameObject around
public Transform pivotPoint;

//The angle to Move the pivot point
public Vector3 angle = new Vector3(0f, 180f, 0f);

//The duration for the rotation to occur
public float rotDuration = 5f;

void Start()
{
    StartCoroutine(rotateObject(pointToRotate, pivotPoint.position, angle, rotDuration));
}
Programmer
  • 121,791
  • 22
  • 236
  • 328
  • 1
    Wow, thanks a lot for the elaborate explanation. It really helps. – OnlyCodeMatters Dec 13 '17 at 14:31
  • I have been following this question. How would I run two `rotateObject` coroutines at the same time? I tried calling one directly after the other and only the first one was run, it seems. – SuperHyperMegaSomething Dec 13 '17 at 14:37
  • 1
    @SuperHyperMegaSomething Remove the `bool rotating = false;` code and any part of the code that uses it in the `rotateObject` function. This includes removing the `yield break;` code. I did that to make sure that you don't call the function twice while passing the-same object to it as that will result to multiple coroutine functions modifying one object at the-same time. – Programmer Dec 13 '17 at 14:49