Moving 3d rigidbody with mouse and new input system...!

Hey folks, having a moment of stupidity here. Basically trying to drag a 3d object around, as seen in this tutorial. The main differences are that I’m using the new Input System, I’m putting the code on the camera and I’m trying to push the object around using Rigidbody.Moveposition.

I’m also looking to make the movement camera-relative and zero out the y movement (as you can see in the commented out code), but for the moment I’d settle with just getting the object moving about (like dragging an icon around on a desktop).

I’m pretty sure this is a simple fix, but I’m wicked tired and heading to bed. If there’s anybody out there who can see where I’m going wrong, I’d appreciate it…!

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

public class SimpleDrag : MonoBehaviour
{
    #region Private Fields
    private Camera cam;
    private Transform tf;
    private Rigidbody payloadRb;

    public bool dragging = false;

    private Controls inputActions;
    public Vector2 mousePosition;
    private Vector3 mousePosOffset;
    #endregion

    #region Public Fields
    public float cursorCastDist = 100.0f;
    public Color cursorCastCol;
    public LayerMask cursorMask;
    public float dragScalar = 8.0f;
    public Vector3 movementLimits;
    public Vector3 mouseWorldPos;
    #endregion

    private void Awake()
    {
        inputActions = new Controls();
               
        cam = GetComponent<Camera>();
        tf = GetComponent<Transform>();
    }

    private void OnEnable()
    {
        inputActions.Enable();
        inputActions.ActionMap.MouseButton0.started += StartDrag;
        inputActions.ActionMap.MouseButton0.canceled += StopDrag;
        inputActions.ActionMap.MousePosition.performed += Movement => mousePosition = Movement.ReadValue<Vector2>();
    }

    void Start()
    {
        payloadRb = GameObject.Find("Payload").GetComponent<Rigidbody>();
    }

    void Update()
    {
        if (dragging) Drag();
    }

    private void OnDisable()
    {
        inputActions.ActionMap.MouseButton0.started -= StartDrag;
        inputActions.ActionMap.MouseButton0.canceled -= StopDrag;
        inputActions.ActionMap.MousePosition.performed -= Movement => mousePosition = Movement.ReadValue<Vector2>();
        inputActions.Disable();
    }

    private void StartDrag(InputAction.CallbackContext context)
    {
        Ray cursorRay = cam.ScreenPointToRay(Mouse.current.position.ReadValue());
        RaycastHit cursorHit;
        if (Physics.Raycast(cursorRay, out cursorHit, cursorCastDist, cursorMask))
        {
            Debug.DrawLine(cursorRay.origin, cursorHit.point, cursorCastCol);

            if (cursorHit.transform.name == "Payload")
            {
                mousePosOffset = cursorHit.transform.position - cam.ScreenToWorldPoint(mousePosition);
                dragging = true;
                // Cursor.visible = false;
            }
        }
    }

    private void StopDrag(InputAction.CallbackContext context)
    {
        dragging = false;
        // Cursor.visible = true;
    }

    private void Drag()
    {
        float localXSigned = Mathf.Sign(StraightenedNormalisedDirection(tf.right).x);
        float localZSigned = Mathf.Sign(StraightenedNormalisedDirection(tf.forward).z);

        //Vector2 clampPos = mousePosition;
        //clampPos.x = Mathf.Clamp(clampPos.x, 2.0f, 430.0f);
        //clampPos.y = Mathf.Clamp(clampPos.y, 2.0f, 766.0f);

        mouseWorldPos = cam.ScreenToWorldPoint(mousePosition) + mousePosOffset;

        // Vector2 currentMousePos = mousePosition - mousePosOffset;

        // Vector3 mouseDelta = mouseWorldPos; // new Vector3(localXSigned * mousePosition.x, 0.0f, localZSigned * mousePosition.y);
        // Vector3 newPos = payloadRb.position + mouseDelta * dragScalar * Time.deltaTime;
        //newPos.x = Mathf.Clamp(newPos.x, -movementLimits.x, movementLimits.x);
        //newPos.y = Mathf.Clamp(newPos.y, -movementLimits.y, movementLimits.y);
        //newPos.z = Mathf.Clamp(newPos.z, -movementLimits.z, movementLimits.z);

        payloadRb.MovePosition(mouseWorldPos); // (newPos);
    }

    private Vector3 StraightenedNormalisedDirection(Vector3 dir)
    {
        dir.y = 0;
        return dir.normalized;
    }

    private void OnDrawGizmosSelected()
    {
        Gizmos.color = Color.cyan;
        Gizmos.DrawWireCube(Vector3.zero, movementLimits * 2);
    }
}

Without getting into the specifics, the easiest will be:

  • rewrite your input system to capture input to local variables

  • process the contents of those local variables to operate the game.

When you break stuff apart like this and something is misbehaving, you have a great halfway cleave-it-apart point to figure out if it is getting the input wrong, or you are processing the input wrong.

And then you can replace the first part with other ways of input, such as old or new or Kinect or whatever.

And then since all the game logic is in the second part, none of that needs to change.

Hey @Kurt-Dekker ! Well, I’m already doing that - I’m registering the InputAction in OnEnable and OnDisable and sending the mouse input to a local variable - namely mousePosition (see the code above).

The issue remains, as it was last night, processing the input.

Ah well, hopefully things will seem clearer now I’m coming at it with a fresh mind.

In case this is of use to anyone, a working version (intended for use on two cameras facing each other at 180 degrees):

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

public class SimpleDrag : MonoBehaviour
{
    #region Private Fields
    private Camera cam;
    private Transform tf;
    private Rigidbody payloadRb;

    private bool dragging = false;

    private Controls inputActions;
    private Vector3 mousePosition;
    private Vector3 mouseWorldPos;
    private Vector3 mouseDelta;
    private Vector3 mousePosOffset;
    private Vector3 clickPosition;
    private Vector3 lerpedPos;
    #endregion

    #region Public Fields
    public float cursorCastDist = 100.0f;
    public Color cursorCastCol;
    public LayerMask cursorMask;
    public Vector3 movementLimits;
   
    public float mouseSmooth = 10.0f;
    public bool dragByDelta = true;
    public bool directionPolarity = true;
    #endregion

    private void Awake()
    {
        inputActions = new Controls();
               
        cam = GetComponent<Camera>();
        tf = GetComponent<Transform>();
    }

    private void OnEnable()
    {
        inputActions.Enable();
        inputActions.ActionMap.MouseButton0.started += StartDrag;
        inputActions.ActionMap.MouseButton0.canceled += StopDrag;
        inputActions.ActionMap.MousePosition.performed += Movement => mousePosition = Movement.ReadValue<Vector2>();
        inputActions.ActionMap.MouseDelta.performed += Delta => mouseDelta = Delta.ReadValue<Vector2>();
        inputActions.ActionMap.MouseDelta.canceled += Delta => mouseDelta = Vector2.zero;
    }

    void Start()
    {
        payloadRb = GameObject.Find("Payload").GetComponent<Rigidbody>();
    }

    void Update()
    {
        if (dragging) Drag();
    }

    private void OnDisable()
    {
        inputActions.ActionMap.MouseButton0.started -= StartDrag;
        inputActions.ActionMap.MouseButton0.canceled -= StopDrag;
        inputActions.ActionMap.MousePosition.performed -= Movement => mousePosition = Movement.ReadValue<Vector2>();
        inputActions.ActionMap.MouseDelta.performed -= Delta => mouseDelta = Delta.ReadValue<Vector2>();
        inputActions.ActionMap.MouseDelta.canceled -= Delta => mouseDelta = Vector2.zero;
        inputActions.Disable();
    }

    private void StartDrag(InputAction.CallbackContext context)
    {
        Ray cursorRay = cam.ScreenPointToRay(Mouse.current.position.ReadValue());
        RaycastHit cursorHit;
        if (Physics.Raycast(cursorRay, out cursorHit, cursorCastDist, cursorMask))
        {
            if (cursorHit.transform.name == "Payload")
            {
                clickPosition = cursorHit.point;

                mousePosOffset = cursorHit.transform.position - GetMouseWorldPos(mousePosition, clickPosition);

                dragging = true;
                Cursor.visible = false;
                Cursor.lockState = CursorLockMode.Confined;
            }
        }
    }

    private void Drag()
    {
        if (dragByDelta)
        {
            Vector3 targetpos = new Vector3(mouseDelta.x, 0.0f, mouseDelta.y);

            targetpos *= directionPolarity ? 1 : -1; // Invert mouse input depending on camera facing on Y axis

            targetpos = ClampWithinMovementLimits(payloadRb.position + targetpos);

            lerpedPos = Vector3.Lerp(lerpedPos, targetpos, mouseSmooth);

            payloadRb.MovePosition(lerpedPos);
        }
        else
        {
            mouseWorldPos = GetMouseWorldPos(mousePosition, clickPosition);

            Vector3 targetPos = mousePosOffset + ClampWithinMovementLimits(mouseWorldPos);

            targetPos.y = payloadRb.position.y;

            payloadRb.MovePosition(targetPos);
        }
    }

    private void StopDrag(InputAction.CallbackContext context)
    {
        dragging = false;
        Cursor.visible = true;
        Cursor.lockState = CursorLockMode.None;
    }

    private Vector3 ClampWithinMovementLimits(Vector3 _position)
    {
        for (int i = 0; i < 3; i++)
        {
            _position[i] = Mathf.Clamp(_position[i], -movementLimits[i], movementLimits[i]);
        }
        return _position;
    }

    private Vector3 GetMouseWorldPos(Vector3 _mouseInput, Vector3 _clickPosOnObject)
    {
        _mouseInput.z = cam.WorldToScreenPoint(_clickPosOnObject).z;
        return cam.ScreenToWorldPoint(_mouseInput);
    }

    private void OnDrawGizmosSelected()
    {
        Gizmos.color = Color.cyan;
        Gizmos.DrawWireCube(Vector3.zero, movementLimits * 2);
        Gizmos.color = Color.green;
        Gizmos.DrawCube(mouseWorldPos, Vector3.one * 0.25f);
        Gizmos.color = Color.white;
        Gizmos.DrawWireCube(clickPosition, Vector3.one * 0.25f);
    }
}
1 Like