5

I have written the following methods to rotate an arbitrary point around another arbitrary point by an angle over a duration. The point in question now moves erratically, but ends up around where I believe is the desired destination. I need to get it to move smoothly to the angle.

Please note that the points are independent of a game object.

From the diagram below, I am trying to move one point of a bezier curve (drawn with a LineRenderer) around another point by an angle over a given period of time. None of these points coincide with the position of the game object which contains the bezier curve. 


enter image description here

IEnumerator runMovement()  {

    yield return new WaitForSeconds(2.0f);
    Vector2 pivot = points[3];

    StartCoroutine(RotateControlPointWithDuration(pivot, 2.0f, 90.0f));

}

   IEnumerator RotateControlPointWithDuration(Vector2 pivot, float duration, float angle)
{
    float currentTime = 0.0f;
    float ourTimeDelta = 0;
    Vector2 startPos = points[0];

    ourTimeDelta = Time.deltaTime;
    float angleDelta = angle / duration; //how many degress to rotate in one second

    while (currentTime < duration)
    {
        currentTime += Time.deltaTime;
        ourTimeDelta = Time.deltaTime;

        points[0] = new Vector2(Mathf.Cos(angleDelta * ourTimeDelta) * (startPos.x - pivot.x) - Mathf.Sin(angleDelta * ourTimeDelta) * (startPos.y - pivot.y) + pivot.x,
                                                        Mathf.Sin(angleDelta * ourTimeDelta) * (startPos.x - pivot.x) + Mathf.Cos(angleDelta * ourTimeDelta) * (startPos.y - pivot.y) + pivot.y);

        yield return null;
    }
}
TenOutOfTen
  • 467
  • 6
  • 14
  • I suggest you add animated gif or link to a video that shows your current problem. Also, it would be better to add another video that shows what exactly you are trying to do – Programmer Jun 29 '18 at 05:31
  • 1
    Also, listen to everything @Programmer says :) – Fattie Jun 29 '18 at 12:06
  • @Fattie I'm working on an update would be ready soon – TenOutOfTen Jun 29 '18 at 12:07
  • @Programmer I just updated the question – TenOutOfTen Jun 29 '18 at 12:34
  • @Fattie I would really appreciate a reason why it **totally wrong** to use Quaternions. – TenOutOfTen Jun 29 '18 at 12:47
  • Quaternions simply have no connection, in any way, at all, to what you're thinking about and dealing with. They are not even vaguely related. – Fattie Jun 29 '18 at 13:30
  • 2
    @Fattie still having some erratic movement. I just updated the question. I honestly think this question has a number of dynamics that make it different from the link you provided. – TenOutOfTen Jun 29 '18 at 14:42
  • @Programmer I just updated the question again. – TenOutOfTen Jun 29 '18 at 14:43
  • your code should be more like .. fraction = (Time.time - startTime) / duration .. and move it to that new point each time – Fattie Jun 29 '18 at 15:31
  • @Fattie I edited the question. I'm trying to work with your suggestion on the fraction but not too sure how get it to work. Would appreciate some more info on this or possibly an answer :) – TenOutOfTen Jun 29 '18 at 16:24
  • i put in an answer with the usual pattern @TenOutOfTen . Note, there may be any number of other problems you're having. You say you're doing a "math calculation" abstracted from any GameObject in the scene, but, if you are seeing erratic behavior I guess it must be presented in some way as a physical elements; in which case there could be many problems. – Fattie Jun 29 '18 at 19:25

2 Answers2

1

The pattern you want is just

public IEnumerator HowToSmoothly()
    {
    // move "X" from value "A" to value "B"

    float duration = 2.5f;
    float delta = B - A;

    float startTime = Time.time;
    float finishTime = Time.time+duration;

    while(Time.time<finishTime)
        {

        float soFarTime = Time.time-startTime;
        float fractionThisFrame = soFarTime / duration;
        float valueThisFrame = A + delta * fractionThisFrame;

        X = valueThisFrame
        if (X > B) X = B;

        yield return 0;
        }

    X = B;
    yield break;
    }
Fattie
  • 27,874
  • 70
  • 431
  • 719
0

I can really help you with quartonians much, but I can offer some advice about movement over time. I hard lesson I had to learn was to avoid using Co-routines wherever possible. While they seem pretty slick, they are a bit confusing to get right and the was Unity uses them isn't exactly how you are supposed to use them in other areas of C#.

Wherever possible, I just use a unity class that updates each frame. Its much simpler to understand and to debug. The drawback in your case is that you need a new component for each point you are trying to rotate, but that shouldn't be a big deal.

public class PointRotator : MonoBehaviour

{

bool rotating = false;
float rate = 0;
float angle;

Vector3 point;
Vector3 pivot;

public void Rotate(Vector3 point, Vector3 pivot, float duration, float angle)
{
    this.point = point;
    this.pivot = pivot;
    this.rate = angle/duration;
    this.angle = angle;

    rotating = true;
}

public void Update()
{
    if (rotating)
    {
        // use quartonian.Lerp with Time.deltatime here

    //if(angle > quartonian angle){rotating = false)
    }
}

}

Try something like that and see if your problem goes away. Otherwise, you may have to research quartonians a little more, or just do the trigonometry manually since you are in a 2D plane.

pseudoabdul
  • 616
  • 3
  • 12
  • I am going to be timing the rotation of several points, they could end up in the hundreds, I can't tell as of now. Thats another reason I want to use coroutines. – TenOutOfTen Jun 28 '18 at 15:18
  • @TenOutOfTen, it's not possible to help you more unless you explain in a sentence or two what you're trying to do. Cheers – Fattie Jun 29 '18 at 12:16
  • Have you considered making the points game objects? It would really simplify the solution. – pseudoabdul Jun 29 '18 at 14:40