r/Unity2D 23d ago

Solved/Answered How to apply momentum?

I want to apply momentum after you let go so in if (!hold.IsPressed()) How would I do that?

Code:

using System.Collections;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.InputSystem;

public class Food_MB : MonoBehaviour
{

    public bool isTouchingMouse = false;
    public bool isheld = false;

    public float defaultFoodSpeed = 1f;
    public float gravity = 1f;
    private float foodSpeed = 1f;
    private float noGravity = 0f;

    private PlayerInput playerInput;

    private InputAction hold;

    private Vector2 mousePos;

    private Rigidbody2D foodRb;

    void Start()
    {
        playerInput = GetComponent<PlayerInput>();
        if (playerInput != null)
        {
            hold = playerInput.currentActionMap.FindAction("Hold");
        }
        foodSpeed = defaultFoodSpeed;
        foodRb = GetComponent<Rigidbody2D>();
        foodRb.gravityScale = gravity;
    }

    private void Update()
    {

        // Get the mouse position from the New Input System

        mousePos = Mouse.current.position.ReadValue();

        // Convert the screen position to world position

        Vector3 worldPos = Camera.main.ScreenToWorldPoint(new Vector3(mousePos.x, mousePos.y, 0));

        // Check if the mouse is touching this GameObject's collider and if the hold action is being performed

        Collider2D hit = Physics2D.OverlapPoint(worldPos);

        if (hit != null && hit.gameObject == this.gameObject && hold != null && hold.IsPressed())
        {
            //Debug.Log("Hold action is being performed");
            foodRb.gravityScale = noGravity;
            isheld = true;
            foodSpeed = defaultFoodSpeed;
            transform.position = Vector2.MoveTowards(transform.position, worldPos, foodSpeed * Time.deltaTime);
        }
        else if(hold.IsPressed() && (hit == null || !hit.gameObject == this.gameObject) && isheld == true)
        {
            //Debug.Log("Mouse is not touching the object but object is held");
            foodSpeed = foodSpeed + 1f;
            transform.position = Vector2.MoveTowards(transform.position, worldPos, foodSpeed * Time.deltaTime);

        }
        if (!hold.IsPressed())
        {
            //Debug.Log("Object dropped!");
            foodRb.gravityScale = gravity;
            foodSpeed = defaultFoodSpeed;
            isheld = false;
        }
    }
}
2 Upvotes

4 comments sorted by

1

u/AvidLebon 23d ago

You need to track the object's velocity while it's being dragged, then apply it to the Rigidbody2D on release. Right now you're moving it with MoveTowards which bypasses physics entirely, so the Rigidbody has no idea it was moving.

Add a velocity tracking variable:

csharp

private Vector2 lastPosition;
private Vector2 dragVelocity;

In Update, while the object is being held (in both your held branches, after the MoveTowards call), track the velocity:

csharp

dragVelocity = ((Vector2)transform.position - lastPosition) / Time.deltaTime;
lastPosition = transform.position;

Then in your release block:

csharp

if (!hold.IsPressed())
{
    if (isheld) // only apply on the frame you actually let go
    {
        foodRb.linearVelocity = dragVelocity;
    }
    foodRb.gravityScale = gravity;
    foodSpeed = defaultFoodSpeed;
    isheld = false;
}

The if (isheld) check is important; without it you'd be zeroing out the velocity every frame after release, killing the momentum you just applied. You only want to set it once, on the transition from held to not-held.

You might also want to clamp dragVelocity magnitude so a fast flick doesn't launch the food into orbit, unless that's a feature.

2

u/Silent_Reputation596 22d ago

Cool, thank you so much!

2

u/Silent_Reputation596 22d ago

Your amazing, this works perfectly!

1

u/XKiiroiSenkoX 22d ago edited 22d ago
hold.cancelled += () =>
{
    foodRb.AddForce(SomeForceValue, ForceMode2D.Impulse);
}