Search code examples
c#unity-game-engine2dtopdown

Unity2D Movement - velocity not working correctly


I have been working at this for a while and do not know why it doesnt work. I want the rigidbody2D object to add velocity when the mouse button is released and however long the mouse is held down determines the power of the velocity.

It works correctly for the first few pushes but when I begin doing it multiple times it seems like it remembers the velocity from before (even though I reset it to 0). Can anyone help? Code and Example below

Code:


public class PlayerControl : MonoBehaviour
{
    public UnityEngine.UI.Slider powerBar;

    private Rigidbody2D rb;
    private float holdDownStartTime;
    private float force;
    private bool moving = false;

    private Vector2 mousePosition;
    private Vector2 targetPosition;
    private Vector3 growthSize = new Vector3(0.1f,0.1f,0);
    

    private void Start()
    {
        powerBar.gameObject.SetActive(false);
        RectTransform rectTransform = powerBar.GetComponent<RectTransform>();
        rb = GetComponent<Rigidbody2D>();
    }

    void Update()
    { 
        if (Input.GetMouseButtonDown(0))
        {
            //reset RigidBody
            rb.velocity = Vector3.zero;
            rb.angularVelocity = 0;
            rb.position = transform.position;
            rb.isKinematic = true;
            //rb.rotation = transform.rotation;

            moving = false;
            holdDownStartTime = Time.time;
            powerBar.gameObject.SetActive(true);

        }

        if (Input.GetMouseButton(0))
        {
            if (!moving)
            {
                powerBar.value = Time.time - holdDownStartTime;
            }
        }

        if (Input.GetMouseButtonUp(0))
        {

            powerBar.gameObject.SetActive(false);
            float holdDownTime = Time.time - holdDownStartTime;
            force = CalculateHoldDownForce(holdDownTime);
            Move(force);
        }

        mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        RotateTowards(mousePosition);
    }

    private void OnTriggerEnter2D(Collider2D collision)
    {
        if(collision.tag == "Food")
        {
            Eat();
        }
    }

    private void Eat()
    {
        this.transform.localScale += growthSize;
    }

    private void Move(float force)
    { 
        targetPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        rb.velocity = new Vector2(targetPosition.x * force/100, targetPosition.y * force/100);

       
    }

    private void RotateTowards(Vector2 target)
    {
        Vector2 direction = (target - (Vector2)transform.position).normalized;
        var angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
        var offset = 90f;
        transform.rotation = Quaternion.Euler(Vector3.forward * (angle + offset));
    }

    private float CalculateHoldDownForce(float holdTime)
    {
        holdTime *= 3;
        float maxForceHoldTime = 2f;
        float holdTimeNormalized = Mathf.Clamp01(holdTime / maxForceHoldTime);
        float force = holdTimeNormalized * 100f;
        return force; 
    }

Video Example: https://www.loom.com/share/965cc423e13e4c19a9295f59c5fa896a?sid=8d6e30b2-7f99-4204-a3da-5a720067f292


Solution

  • The problem is calculation in the Move() function.

    private void Move(float force)
    { 
        targetPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        rb.velocity = new Vector2(targetPosition.x * force/100, targetPosition.y * force/100);
    }
    

    In this code you give targetPosition vector as velocity input. As you can see in the video, object goes through your mouse position according to center. You should edit this function like that:

    private void Move(float force)
    { 
        targetPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        var targetDirection = targetPosition - rb.transform.position;
    
        rb.velocity = new Vector2(targetDirection.x * force/100, targetDirection.y * force/100);
    }