简体   繁体   中英

How to reverse gravity immediately?

I'm making a 2D game. I have a Cube Object falling down from the top of the screen, and I have pipes which the cube should pass by reversing gravity.

Well my object is falling down from the top of the screen. I tap on the screen to reverse gravity but it's not going immediately up: it takes time to change the gravity orientation. When i tap the screen my object continues falling and then goes up. My movement is forming the shape of a U when I tap the screen. The same thing happens when it goes up: I tap it to go down and in that case my movement forms the shape of a .

What I want to achieve is that when I tap the screen my object's movement has instant response.

In addition, I want some sort of attenuation, damping, or smoothing.

I've tried these examples without success:

http://docs.unity3d.com/ScriptReference/Vector2.Lerp.html

http://docs.unity3d.com/Documentation/ScriptReference/Vector3.SmoothDamp.html

This is my code:

public class PlayerControls : MonoBehaviour
{
     public GameObject playerObject = null;
Rigidbody2D player;

public float moveSpeed;
public float up;

Vector2 targetVelocity;



void Start()
{
    player = playerObject.GetComponent<Rigidbody2D>();

    // Set the initial target velocity y component to the desired up velocity.
    targetVelocity.y = up;
}

void Update()
{
    for (int i = 0; i < Input.touchCount; i++)
    {
        Touch touch = Input.GetTouch(i);

        if (touch.phase == TouchPhase.Ended && touch.tapCount == 1)
        {
            // Flip the target velocity y component.
            targetVelocity.y = -targetVelocity.y;
        }
    }
}

void FixedUpdate()
{
    // Ensure if moveSpeed changes, the target velocity does too.
    targetVelocity.x = moveSpeed;

    // Change the player's velocity to be closer to the target.
    player.velocity = Vector2.Lerp(player.velocity, targetVelocity, 0.01f);
}

} This script is attached to the falling cube.

When affected by a constant force (in your code, gravity), an object will move in a parabola. You're observing a parabola: that U shape. To avoid the parabola and get instant response (a V shape), don't use forces. Replace the gravityScale code with something like:

Vector2 velocity = player.velocity;
velocity.y = -velocity.y;
player.velocity = velocity;

This inverts the velocity's y component, making the player move upwards.


You also mentioned you want to smooth this out. I suggest adding another variable: the target velocity.

To implement this, add Vector2 targetVelocity to your component. Then, during each FixedUpdate you can interpolate from the current velocity towards the target velocity to gradually change speed. Replace this line in your current code:

player.velocity = new Vector2(moveSpeed, player.velocity.y);

With this:

player.velocity = Vector2.Lerp(player.velocity, targetVelocity, 0.01f);

This will slowly change the velocity to be the same as the target velocity, smoothing out the movement. 0.01f is the place between the old velocity and the new velocity that the player's velocity is set to. Choose a larger number to interpolate more quickly, and a smaller number to change direction more slowly.

Then, instead of changing velocity when the screen is tapped, change targetVelocity . Make sure that the x component of targetVelocity is equal to moveSpeed , or the object won't move horizontally at all!


Combining these two changes, the Start and FixedUpdate methods should look similar to this:

void Start()
{
    player = playerObject.GetComponent<Rigidbody2D>();

    // Set the initial target velocity y component to the desired up velocity.
    targetVelocity.y = up;
}

void Update()
{
    for (int i = 0; i < Input.touchCount; i++)
    {
        Touch touch = Input.GetTouch(i);

        if (touch.phase == TouchPhase.Ended && touch.tapCount == 1)
        {
            // Flip the target velocity y component.
            targetVelocity.y = -targetVelocity.y;
        }
    }
}

void FixedUpdate()
{
    // Ensure if moveSpeed changes, the target velocity does too.
    targetVelocity.x = moveSpeed;

    // Change the player's velocity to be closer to the target.
    player.velocity = Vector2.Lerp(player.velocity, targetVelocity, 0.01f);
}

Note that you shouldn't use Input in FixedUpdate , because inputs are updated every frame and FixedUpdate may run multiple times per frame. This could cause the input to be read twice, especially if the frame rate gets slower and the fixed update is more likely to need to run multiple times per frame.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM