0
\$\begingroup\$

i'm making a game in which the player character, a 2d rigidbody, is controlled by the user's mouse dragging them. i originally made it so that the player character's position was made the same as the mouse's whenever the mouse was clicking, but this allows for the player to drag the character through walls. i decided the best way to get past this is to apply force to the character until it reaches the mouse's position so as to get the player there as fast as possible without going through walls. when the character reaches the mouse's position, i tried to set its velocity in both axes to 0. however, i seem to be stuck as the movement is largely inaccurate. here's my code:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player : MonoBehaviour
{
    public Rigidbody2D rb2D;
    public bool isBeingHeld;
    public float force = 1;
    Vector3 mousePos;

    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {
        mousePos = Input.mousePosition;
        mousePos = Camera.main.ScreenToWorldPoint(mousePos);

        if (isBeingHeld == true)
        {
            if (mousePos.x == this.transform.position.x)
            {
                rb2D.velocity = new Vector2(0, rb2D.velocity.y);
            }
            if (mousePos.y == this.transform.position.y)
            {
                rb2D.velocity = new Vector2(rb2D.velocity.x, 0);
            }
            if (mousePos.x > this.transform.position.x)
            {
                rb2D.AddForce(new Vector2(force, 0));
            }
            if (mousePos.x < this.transform.position.x)
            { 
                rb2D.AddForce(new Vector2(-force, 0));
            }
            if (mousePos.y > this.transform.position.y)
            {
                rb2D.AddForce(new Vector2(0, force));
            }
            if (mousePos.y < this.transform.position.y)
            {
                rb2D.AddForce(new Vector2(0, -force));
            }
        }

        if (Input.GetMouseButtonUp(0))
        {
            isBeingHeld = false;
        }
    }

    private void OnMouseOver()
    {
        if (Input.GetMouseButtonDown(0))
        {
            mousePos = Input.mousePosition;
            mousePos = Camera.main.ScreenToWorldPoint(mousePos);
            isBeingHeld = true;
        }
    }
}

thank you!

\$\endgroup\$
4
  • \$\begingroup\$ you should use lerp or movetowards and use Time.deltaTime. So that he movement is smooth. One thing I also do is I take the axis values ( input ) on Update but do the moving on FixedUpdate using Time.fixedDeltaTime \$\endgroup\$ – Jonathan Alfaro Jan 9 '20 at 7:21
  • \$\begingroup\$ @Darkonekt if you're working in FixedUpdate, then Time.deltaTime automatically returns the fixed delta, you don't need to ask for the fixed delta specifically. \$\endgroup\$ – DMGregory Jan 9 '20 at 12:11
  • \$\begingroup\$ you can simply dsiable rigidBody or make it kinematic when user pressed on object \$\endgroup\$ – virtouso Jan 9 '20 at 14:47
  • \$\begingroup\$ @DMGregory I know it does... But then your code would depend on an internal implementation detail which could change any time with a future release of Unity. Also in my opinion it violates encapsulation because it requires the developer to "know internal things" about the property. Because this property behaves differently depending on where you are calling it. But I do agree with you that Time.deltaTime returns Time.fixedDeltaTime when called within the FixedUpdate method \$\endgroup\$ – Jonathan Alfaro Jan 9 '20 at 15:02

Browse other questions tagged or ask your own question.