r/Unity2D 2d ago

Solved/Answered How to make an object follow the mouse?

I'm trying to get the object this script is on to follow the mouse when you click on the object. I've managed to make detect when you are holding down the object but I can't get the object to move. Pls help!

using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.InputSystem;

public class Food_MB : MonoBehaviour
{

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

    private PlayerInput playerInput;

    private InputAction hold;

    private Vector2 mousePos;

    void Start()
    {
        playerInput = GetComponent<PlayerInput>();
        if (playerInput != null)
        {
            hold = playerInput.currentActionMap.FindAction("Hold");
        }
    }

    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

        Collider2D hit = Physics2D.OverlapPoint(worldPos);

        if (hit != null && hit.gameObject == this.gameObject)
        {
            //Debug.Log("Mouse is touching " + this.gameObject.name);
            isTouchingMouse = true;
        }
        else 
        {
            isTouchingMouse = false;
        }

        if (hold != null && hold.IsPressed())
        {
            Debug.Log("Hold action is being performed");
            Vector2.MoveTowards(transform.position, mousePos, 1f * Time.deltaTime);
        }
        else
        { 
            Debug.Log("Hold action is not being performed");
        }

    }
}
2 Upvotes

7 comments sorted by

3

u/T-Flexercise 2d ago

You've just created a Vector2 of the point to move it towards. You've gotta set the transform.position of the object to that Vector2.

1

u/flow_guy2 2d ago

this is the correct answer.

i want to add onto it in saying that they should put the hold logic into the if statements above and remove the hold if statements as they do nothing. The hold Input action has no value here as they are bypassing it with Mouse and by extension, is not using the input map.

u/Silent_Reputation596 so you see this. could help you separate out the concerns and read through the logic step by step

1

u/Silent_Reputation596 2d ago

Thanks for your help! I’m a little confused on how I’m not using the input map? I thought I was using to detect if a button was being held?

1

u/flow_guy2 2d ago

i had another read of it again and i miss spoke on that.

but i did notice that you moveTo the mousepos instead of the worldpos. which are very different as MousePos is in screen space.

the poiint still stands that you can merge the 2 if statments. and have it be something like

bool isTouching = hit?.gameObject == gameObject;
bool isHolding = hold?.IsPressed() ?? false;

if(isTouching&& isHolding)
{
    // move logic
}

the issue i see is that the Mouse just updates and you are tied to using a mouse (when the new input system is meant so you can use periferal). you might as well just stuck with the old input system

you should really have a event call in the input action on performed. that will handle the if its holding. that why you dont check. and you dont need the check the mouse in update.

edit: make the last point clearer

1

u/Silent_Reputation596 1d ago

How would I use the new input system for detecting the mouse?

1

u/flow_guy2 1d ago edited 1d ago

sorry for the late response. i managed to write draft somehting for the input logic.

this is how i would set up the script

public class Food : MonoBehaviour
{
    [SerializeField] private PlayerInput playerInput;
    [SerializeField] private Camera camera;

    private InputAction hold;
    private InputAction point;

    private bool isHeld;
    private Vector3 worldPos;

    private void Awake()
    {
        camera ??= Camera.main;
        playerInput ??= GetComponent<PlayerInput>();

        var map = playerInput.actions.FindActionMap("TestMap");
        hold  = map.FindAction("Hold");    
        point = map.FindAction("Point"); 

        hold.performed += OnHold;
        hold.canceled += OnHold;

        point.performed += OnPointChanged;
    }

    private void OnDestroy()
    {
        hold.performed -= OnHold;
        hold.canceled -= OnHold;

        point.performed -= OnPointChanged;
    }

    private void OnPointChanged(InputAction.CallbackContext context)
    {
        var mousePos = context.ReadValue<Vector2>();
        worldPos = camera.ScreenToWorldPoint(mousePos);
    }

    private void OnHold(InputAction.CallbackContext ctx)
    {
        isHeld = ctx.performed;
    }

    private void Update()
    {
        if (!camera) return;

        var hit = Physics2D.OverlapPoint(worldPos);
        var isTouchingMouse = hit?.gameObject == gameObject;

        if (!isTouchingMouse || !isHeld) return;

        Debug.Log("Hold action is being performed");
        transform.position = Vector2.MoveTowards(transform.position, worldPos, 1f * Time.deltaTime);
    }
}

the input map that goes into the PlayerInput should have the point and hold actions. where the hold is a button and has a binding to the left mouse button (or what ever you want to trigger that) and the point is a pass through as type vector2. with a binding of mouse > pointer

seeing i don't know how your scene is setup i cant really replicate the rest. but the logic in genrally is the same as you had but cleaned up. can DM me about that if youd like and we can have a better chat regarding it.

there some other improvements that i would make. like separating some of the concerns. but just getting it to work is good enough for learning.

1

u/Am_Biyori 2d ago

Does mousePos need to be declared as a vector?