0
\$\begingroup\$

I have implemented curve movement for two sprites (moon and sun) to simulate daytime changing. Sprites should take turns one after each other and move over the sky.

enter image description here

But they just instantly appear at the finish point no matter how I tweak value supposedly responsible for the speed of lerping.

daytimeCounter += 1.0f * Time.deltaTime; 

Here is the full script.

[Tooltip("Object to parent sky elements.")]
[SerializeField]
private GameObject objectForParenting;

private float daytimeCounter; //counter to control moon and sun movement
private bool turnSwitch; //controls if it is moon movement or sun

/* Sun object field and parameters that control it's movement. */

[Header("Sun parameters.")]

[Tooltip("Sun object.")]
[SerializeField]
private GameObject sunObject;

[Tooltip("Sun prefab.")]
[SerializeField]
private GameObject sunPrefab;

[Tooltip("Start moving point for sun.")]
[SerializeField]
private Vector2 sunStartMovingPoint;

[Tooltip("Finish moving point for sun.")]
[SerializeField]
private Vector2 sunFinishMovingPoint;

[Tooltip("Multiplier for bezier curve height point.")]
[SerializeField]
private float bezierCurveMultiplierForSun; //multiplier to control height of bezier curve

private Vector2 heightBezierCurvePointForSun; //height point for bezier curve along which sun moves

[Tooltip("Slows sprite interpolation.")]
[SerializeField]
private float speedDividerForSun;


/* Moon object field and parameters that control it's movement. */

[Header("Moon parameters.")]

[Tooltip("Sun object.")]
[SerializeField]
private GameObject moonObject;

[Tooltip("Sun object.")]
[SerializeField]
private GameObject moonPrefab;

[Tooltip("Start moving point for moon.")]
[SerializeField]
private Vector2 moonStartMovingPoint;

[Tooltip("Finish moving point for moon.")]
[SerializeField]
private Vector2 moonFinishMovingPoint;

[Tooltip("Multiplier for bezier curve height point.")]
[SerializeField]
private float bezierCurveMultiplierForMoon; //multiplier to control height of bezier curve

private Vector2 heightBezierCurvePointForMoon; //height point for bezier curve along which moon moves

[Tooltip("Slows sprite interpolation.")]
[SerializeField]
private float speedDividerForMoon;


/* Clouds objects field and parameters that control it's movement. */

[Header("Clouds parameters.")]

[Tooltip("Array for cloud prefabs.")]
[SerializeField]
private GameObject[] cloudsArray;

// Use this for initialization
void Start() {

    daytimeCounter = 0f;

    //initializing bezier curve height point for sun
    InitializeBezierCurve(sunStartMovingPoint, ref heightBezierCurvePointForSun, sunFinishMovingPoint, bezierCurveMultiplierForSun);
    //initializing bezier curve height point for moon
    InitializeBezierCurve(moonStartMovingPoint, ref heightBezierCurvePointForMoon, moonFinishMovingPoint, bezierCurveMultiplierForMoon);
}

// Update is called once per frame
void Update() {
    MoveMoonAndSunAlongBezierCurve(ref sunObject, sunStartMovingPoint, heightBezierCurvePointForSun, sunFinishMovingPoint,
       ref moonObject, moonStartMovingPoint, heightBezierCurvePointForMoon, moonFinishMovingPoint);
}

//initialize bezier curve height point for moon and sun sprite movements
private void InitializeBezierCurve(Vector2 startPoint, ref Vector2 heightPoint, Vector2 finishPoint, float heightMultiplier)
{
    heightPoint = startPoint + (finishPoint - startPoint) / 2 + Vector2.up * heightMultiplier;
}

private void MoveMoonAndSunAlongBezierCurve(ref GameObject movableObject1, Vector2 startPoint1, Vector2 heightPoint1, Vector2 finishPoint1,
    ref GameObject movableObject2, Vector2 startPoint2, Vector2 heightPoint2, Vector2 finishPoint2)
{
    if (turnSwitch == false) //sun turn
    {
        while (daytimeCounter < 1.0f)
        {
            daytimeCounter += 1.0f * Time.deltaTime;

            Vector3 m1 = Vector2.Lerp(startPoint1, heightPoint1, daytimeCounter);
            Vector3 m2 = Vector2.Lerp(heightPoint1, finishPoint1, daytimeCounter);
            movableObject1.GetComponent<Transform>().localPosition = Vector2.Lerp(m1, m2, daytimeCounter);
        }
       // movableObject1.GetComponent<Transform>().localPosition = startPoint1;
    }
    else if (turnSwitch == true) //moon turn
    {
        while (daytimeCounter < 1.0f)
        {
            daytimeCounter += 1.0f * Time.deltaTime;

            Vector3 m1 = Vector2.Lerp(startPoint2, heightPoint2, daytimeCounter);
            Vector3 m2 = Vector2.Lerp(heightPoint1, finishPoint2, daytimeCounter);
            movableObject2.GetComponent<Transform>().localPosition = Vector2.Lerp(m1, m2, daytimeCounter);
        }
        //movableObject2.GetComponent<Transform>().localPosition = startPoint2;
    }

    daytimeCounter = 0f;
    turnSwitch = !turnSwitch;
}

Related to: [Unity]: Moving 2D object along circular arc between two points

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

From daytimeCounter += 1.0f change 1.0f to any value you want the speed to be. Bigger values mean bigger speed. Do this in both cases in MoveMoonAndSunAlongBezierCurve.

Edit:

I found your problem. On Update you call the function MoveMoonAndSunAlongBezierCurve. However inside that function you are running the whole simulation inside a while. This means the simulation will execute in one frame, and when it returns, you will see the final result, which is the sun on the end of the curve. Instead, change while with an if:

while (daytimeCounter < 1.0f)
// Becomes
if (daytimeCounter < 1.0f)

Also, every time you increment daytimeCounter, you should check if it became more than 1.0f, in this case the animation ended, and it should either reset or handle code differently. Here's your function re-written so you can understand what I mean:

private void MoveMoonAndSunAlongBezierCurve(ref GameObject movableObject1, Vector2 startPoint1, Vector2 heightPoint1, Vector2 finishPoint1,
ref GameObject movableObject2, Vector2 startPoint2, Vector2 heightPoint2, Vector2 finishPoint2)
{
    if (turnSwitch == false)
    {
        // while turned into an if
        if (daytimeCounter < 1.0f)
        {
            daytimeCounter += 1.0f * Time.deltaTime;

            Vector3 m1 = Vector2.Lerp(startPoint1, heightPoint1, daytimeCounter);
            Vector3 m2 = Vector2.Lerp(heightPoint1, finishPoint1, daytimeCounter);
            movableObject1.GetComponent<Transform>().localPosition = Vector2.Lerp(m1, m2, daytimeCounter);

            // Animation just ended - handle what happens next
            if (daytimeCounter >= 1.0f) {
                daytimeCounter = 0f;
                turnSwitch = !turnSwitch;
            }
        }
    }
    else if (turnSwitch == true)
    {
        // Again, while turned into an if
        if (daytimeCounter < 1.0f)
        {
            daytimeCounter += 1.0f * Time.deltaTime;

            Vector3 m1 = Vector2.Lerp(startPoint2, heightPoint2, daytimeCounter);
            Vector3 m2 = Vector2.Lerp(heightPoint1, finishPoint2, daytimeCounter);
            movableObject2.GetComponent<Transform>().localPosition = Vector2.Lerp(m1, m2, daytimeCounter);

            // Animation just ended - handle what happens next
            if (daytimeCounter >= 1.0f) {
                daytimeCounter = 0f;
                turnSwitch = !turnSwitch;
            }
        }
   }

    // These are no longer needed
    //daytimeCounter = 0f;
    //turnSwitch = !turnSwitch;
}

I've only kept my comments so that you can see what changes I made. The idea is that this function is now called once per frame, it moves the animation to the next step (with daytimeCounter += 1.0f where 1.0f is the speed) and then draws the object in the new position. Once daytimeCounter becomes bigger or equal to 1.0f this means the animation reached its last point, so it should probably reset.

\$\endgroup\$
8
  • \$\begingroup\$ I have tried it before and now. It doesn't help. At least I cant see speed change with my eye. I have also tried to modify Time.deltatime with multipliers and dividers. It isn't changing even with crazy numbers. \$\endgroup\$ Apr 17, 2018 at 12:10
  • \$\begingroup\$ daytimeCounter += .01f * Time.deltaTime . Same result. Instantly appear at the end point. \$\endgroup\$ Apr 17, 2018 at 12:13
  • \$\begingroup\$ @NikitaDemidenko I found your problem and edited my answer \$\endgroup\$ Apr 17, 2018 at 12:18
  • \$\begingroup\$ Awesome. it's working now. Thanks. One more thing though. Vector.Lerp doesn't provide even speed along all the way. It speeds up at the end and beginning and slows in the middle. Could you advise any different method for even movement along all way? \$\endgroup\$ Apr 17, 2018 at 12:31
  • \$\begingroup\$ You can try Cubic Bezier Curves, which is the same technique, but with 4 points instead of 3. This allows you to have more control over the curve, and make a smoother result. You can also try Camull-Rom curve, but that may be a little harder to implement. \$\endgroup\$ Apr 17, 2018 at 12:34

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .