C.Deighton
C.Deighton

Reputation: 9

Unity rope swinging physics algorithm: Player stuck mid-swing

I have implemented the following tutorial in Unity (2D) attempting to create a rope swinging platformer: https://gamedevelopment.tutsplus.com/tutorials/swinging-physics-for-player-movement-as-seen-in-spider-man-2-and-energy-hook--gamedev-8782

void FixedUpdate() 
{
    Vector2 testPosition = playerRigidbody.position + playerRigidbody.velocity * Time.deltaTime;
    Hooked(testPosition);
}

private void Hooked(Vector2 testPosition)
    {
        Vector2 t = new Vector2(tetherPoint.position.x, tetherPoint.position.y);
        Debug.DrawLine(tetherPoint.position, playerRigidbody.position);
        float currentLength = (testPosition - t).magnitude;

        if (currentLength < tetherLength)
        {
           currentLength = (playerRigidbody.position - t).magnitude * Time.deltaTime;
        }
        else
            currentLength = tetherLength;

        if ((testPosition - t).magnitude > tetherLength)
        {
            Vector2 x = (testPosition - t).normalized;
            testPosition = new Vector2(x.x * currentLength, x.y * currentLength);

            playerRigidbody.velocity = (testPosition - playerRigidbody.position) * Time.deltaTime;
            playerRigidbody.position = testPosition;
        }
    }

It seems to function correctly on the downward swing but when the player begins to travel upwards they become stuck floating in the air and don't drop to the middle of the arc. The swing also does not propel them very high on the other side even when dropped from height.

EDIT (Further clarification): Interestingly When the player is dropped from the other side of the tetherPoint it stops in the same spot, this time only half-way down. It's as if the player is being pulled toward a single position even when manually moved in the editor while playing no matter the direction.

EDIT: User John cleared up my concerns about deltaTime.

I've tried examining the change in variables during play but I just can't figure out why it's not working correctly. I think the issue lies somewhere in my interpretation of the original psudeo-code to C#.

Another question on the same tutorial has been asked previously but unfortunately that users implementation was very different than mine: Game rope swing physics acting weird

EDIT: Since posting I've updated the code to use AddForce and MovePosition instead but it's still the same.

playerRigidbody.AddForce((testPosition - playerRigidbody.position) * Time.deltaTime);
playerRigidbody.MovePosition(testPosition);

Upvotes: 0

Views: 540

Answers (1)

John
John

Reputation: 728

It looks like you're using Time.deltaTime from a method that is called from FixedUpdate. What you want to use instead is Time.fixedDeltaTime.

FixedUpdate is called at a set interval (eg. 50fps) for physics updates, but regular Update is called at a different varying frequency (up to hundreds of times a second if you've got a fast computer/simple game).

Time.deltaTime is used for the Update method, and so the value of it can be different each time Update is called, as the time between Update calls varies.

However, because FixedUpdate is called at the same interval each time, Time.fixedDeltaTime is constant and (normally) much larger than Time.deltaTime. Your code doesn't work well with Time.deltaTime, as it doesn't represent the actual difference in time between each FixedUpdate call, but Time.fixedDeltaTime should work.

As a side note, you're correct that you should be multiplying by the time delta rather than dividing. the time delta should be multiplied when calculating positions (eg. for the Vector2 testPosition assignment and the currentLength calculation), but for calculating the velocity you should be dividing the time delta (because velocity = distance/time).

Upvotes: 0

Related Questions