1

It seems like this question has already been discussed many times. But I couldn't find the solution for my case. All the discussions are either about camera rotation according to mouse movement or object control via mouse. But I need to control the mouse pointer with joystick (or keyboard). It looks like a really simple question, but I'm confused. Currently, I'm trying to hide hardware cursor and recreat my own, controlling it with Input.GetAxis("Horizontal") or Input.GetAxis("Mouse X") but the cursor just disappears and Event System reports no movement. However, if I use Input.mousePosition.x my custom cursor is well created and controlled with mouse. Unfortunately, I need to control it only with Joystick. In addition, it doesn't work with Project Settings>>Input (or maybe I'm change something wrong there) Thanks in advance.

public class cursor : MonoBehaviour
{
    public Texture2D cursorImage;

    private int cursorWidth = 32;
    private int cursorHeight = 32;
    public float horizontalSpeed = 2.0F;
    public float verticalSpeed = 2.0F;

    void Start()
    {
        Cursor.visible = false;
    }

    void OnGUI()
    {
        float h = horizontalSpeed * Input.GetAxis("Horizontal") * Time.deltaTime;
        float v = verticalSpeed * Input.GetAxis("Vertical") * Time.deltaTime;
        GUI.DrawTexture(new Rect(h, Screen.height - v, cursorWidth, cursorHeight), cursorImage);
    }
}
ivanshv
  • 47
  • 1
  • 2
  • 7
  • What about having a canvas overlay with an image on it ? You can use the RectTransform to make it move – Jichael Jul 23 '19 at 11:52
  • @Jichael Thanks for your suggestion. That's indeed a solution, and I was thinking about that. But the entire app functionality is about mouse position (display coordinates), and I really would prefer not to rewrite everything and obtain this canvas world position and translate it to display coordinates. The project is ready, I only need to implement joystick movement. – ivanshv Jul 23 '19 at 11:59
  • you know that `Input.GetMouseButtonDown(0);` does absolutely nothing here, right? it returns a bool you never store or use... If you really want to implement your own cursor with possibility of using UI and `IPointerEnterHandler`, `IPointerClickHandler` etc you would have to implement your own [`PointerInputModule`](https://docs.unity3d.com/ScriptReference/EventSystems.PointerInputModule.html) – derHugo Jul 23 '19 at 12:14
  • @derHugo I know, these lines are useless here, just leftovers. Sorry, I'll remove them – ivanshv Jul 23 '19 at 12:22

1 Answers1

2

You are using

float h = horizontalSpeed * Input.GetAxis("Horizontal") * Time.deltaTime;
float v = verticalSpeed * Input.GetAxis("Vertical") * Time.deltaTime;
GUI.DrawTexture(new Rect(h, Screen.height - v, cursorWidth, cursorHeight), cursorImage);

h and v will always have very tiny values since multiplied by Time.deltaTime and Input.GetAxis afaik returns usually values between 0 and 1.

These values don't represent an actual cursor position but rather are the change of the position relative to the last frame.

Your cursor will be stuck somewhere in the top-left corner.


Instead you should store the current position and add your values as change to it like

private Vector2 cursorPosition;

private void Start()
{
    Cursor.visible = false;

    // optional place it in the center on start
    cursorPosition = new Vector2(Screen.width/2f, Screen.height/2f);
}

private void OnGUI()
{
    // these are not actual positions but the change between last frame and now
    float h = horizontalSpeed * Input.GetAxis("Horizontal") * Time.deltaTime;
    float v = verticalSpeed * Input.GetAxis("Vertical") * Time.deltaTime;

    // add the changes to the actual cursor position
    cursorPosition.x += h;
    cursorPosition.y += v;

    GUI.DrawTexture(new Rect(cursorPosition.x, Screen.height - cursorPosition.y, cursorWidth, cursorHeight), cursorImage);
}

Also note that horizontalSpeed and verticalSpeed are in Pixels / Seconds and you probably want some values bigger then 2 ;)

I used 200 and the Up, Down, Left & Right keys.

enter image description here

derHugo
  • 83,094
  • 9
  • 75
  • 115
  • That's fantastic, @derHugo ! As always very informative and helpful. Thank you very much! – ivanshv Jul 23 '19 at 12:52
  • I apologize for bothering you again, but I have another problem. Everything works perfect and I get what I need, but there is an issue and maybe you could help me again. I have a multi-display setup and the cursor doesn't go to the second display. Do you know what can cause this issue? Thanks. – ivanshv Jul 23 '19 at 18:19
  • Hm honestly I have zero experience with mutlidisplays in Unity .. my only guess would be that maybe the `OnGUI` does not support multiple displays .. you could try to instead use a normal [`Image`](https://unity3d.com/de/learn/tutorials/topics/user-interface-ui/ui-image) component from the Unity [UI system](https://docs.unity3d.com/Manual/UISystem.html) instead. There also once was an issue with [UI and multiple displays](https://forum.unity.com/threads/ui-and-multiple-displays.385525/) so the UI was enterily limited to the main display .. maybe that's still true for `OnGUI`... – derHugo Jul 23 '19 at 19:19
  • Thanks. Will try to find something out. Anyway, I always have a solution to simply build a borderless window and drag it to all the displays. Thanks again. – ivanshv Jul 23 '19 at 19:55