Home > front end >  Mouse.current.WarpCursorPosition only seems to be working correctly if moving left or up (not right
Mouse.current.WarpCursorPosition only seems to be working correctly if moving left or up (not right

Time:09-17

Here is a simple script to demonstrate the issue. This script should move the cursor to the left for 1 second and then back to the right for 1 second. However you'll see it just moves it to the left then stops. You can flip the order and try to move right first, but you'll notice that still won't work. I've also tested with moving up / down, moving up works as expected, moving down does not.

public class dumbtestscript : MonoBehaviour
{

    void Start()
    {
        Mouse.current.WarpCursorPosition(new Vector3(123, 123));

        StartCoroutine(MoveCursorLeftThenRightCoroutine());
    }

    IEnumerator MoveCursorLeftThenRightCoroutine()
    {
        float startTime = Time.time;
        while (Time.time < startTime   1)
        {
            Mouse.current.WarpCursorPosition(Input.mousePosition   

                (Time.deltaTime * new Vector3(-0.1f, 0)));

            yield return null;
        }

        while (Time.time < startTime   2)
        {
            Mouse.current.WarpCursorPosition(Input.mousePosition   

                (Time.deltaTime * new Vector3(0.1f, 0)));

            yield return null;
        }

    }
}

Am I misunderstanding something about how WarpCursorPosition is supposed to work?

Any advice appreciated. Thanks.

Edit: Upon further inspection it may have to do with the vector being passed to WarpCursorPosition. For example regardless of whether we use this to move left:

Mouse.current.WarpCursorPosition(Input.mousePosition   new Vector3(-0.1f, 0));

or this:

 Mouse.current.WarpCursorPosition(Input.mousePosition   new Vector3(-1f, 0));

it moves to the left at the same speed. So it seems anything between -0.1 and -1 is being rounded to -1. Conversely for going right everything between 0.1 and just under 1 is being rounded to 0 which would explain why it wasn't moving in the original.

So everything is getting round down to the nearest integer for some reason? Both Input.mousePosition and the Vector3 we are adding are both Vector3 and I thought could handle float numbers so not sure why things are being rounded down to ints, if thats whats happening?

CodePudding user response:

The issue

So everything is getting round down to the nearest integer for some reason?

Most probably Yes!

WarpCursorPosition makes your actual system cursor jump to the given pixel coordinates.

While inside Unity the pixel space is always provided as float for many things and mainly for making direct calculations with it, the actual system cursor uses pixels (like everything that is actually happening on the screen) which are always full int values!

So, yes, it will always (not round but rather) floor your given input to the next int (full pixel). Basically what happens if you simply use

var x = (int) (Input.mousePosition.x - 0.1f);

=> You will see that x will be exactly Input.mousePosition.x - 1 since if e.g. the current Input.mousePosition.x was 230 then you get (int) 229.9f which is 229.

In the other direction though you get e.g. 230 0.1f so (int) 230.1f again simply is 230.

=> Your steps would need to at least be one full pixel!


Solution

So instead of constantly read the current Input.mousePosition which underlies the afore mentioned pixel coordinates rather use and update a local vector that does not:

IEnumerator MoveCursorLeftThenRightCoroutine()
{
    // Store the current mousePosition as a Vector2
    // This uses floats and is not restricted to full pixel jumps
    var currentPosition = Input.mousePosition;

    for(var passedTime = 0f; passedTime < 1; passedTime  = Time.deltaTime)
    {
        // simply continously add to the float vector
        currentPosition  =  Vector2.left * speedInPixelsPerSecond * Time.deltaTime;
        // Using that float vector as input may in some frames cause no movement where the clamp results
        // still in the same pixel but it will catch up as soon as the vector was increased/reduced enough
        Mouse.current.WarpCursorPosition(currentPosition);               

        yield return nnull;
    }

    for(var passedTime = 0f; passedTime < 1; passedTime  = Time.deltaTime)
    {
        currentPosition  =  Vector2.right * speedInPixelsPerSecond * Time.deltaTime;
        Mouse.current.WarpCursorPosition(currentPosition);

        yield return null;
    }
}

In general for the new Input system I would rather use Mouse.current.position instead of Input.mousePosition.

CodePudding user response:

I don't have any experience using WarpCursorPosition but when I was experimenting to answer this thread, I felt it's not consistent & would like to advice not to use it.


Code

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

public class Q69189325 : MonoBehaviour
{
    private void Start()
    {
        Mouse.current.WarpCursorPosition(Input.mousePosition);
        StartCoroutine(MoveLogicCrt());
    }

    IEnumerator MoveLogicCrt()
    {
        yield return MoveCursorToDirectionCrt(Vector3.left, 150, 5);
        yield return null;
        yield return MoveCursorToDirectionCrt(Vector3.right, 350, 5);
    }

    private IEnumerator MoveCursorToDirectionCrt(Vector3 direction, float speed, float movementTime)
    {
        float startTime = Time.time;

        while(Time.time < startTime   movementTime)
        {
            Vector2 newMousePosition = Input.mousePosition   (Time.deltaTime * direction * speed);
            Mouse.current.WarpCursorPosition(newMousePosition);
            yield return null;
        }
    }
}

Note:

For some reason when I put the same speed to both left & right it doesn't move right which was weird.


Execution Overview

https://gfycat.com/eventhriftyannelida

Happy coding!

  • Related