I recently figured out something that I found was not documented very well or otherwise to be found on AnswerHub or here, on the forums. But I’ve seen plenty of people struggle with it, so I’m going to give you my approach on the matter.
What we’re going to do is build a simple system in which you have your custom cursor, independent of the OS’s cursors, that changes into another cursor when you mouse-over certain actors (for example, interactables like a chest).
So let’s get started!
Here are our cursor images that we’re going to use for this game. The orange cursor is the default, the Awesome cursor is what we’ll use when we mouse-over a square tile actor.
Let’s import the images into the editor. Right-click, Sprite Actions > Apply Paper2D Texture Settings. Call the orange cursor orangeCursor and the Awesome cursor awesomeCursor.
Right-click in the content browser and click Blueprint Class;
Search for ‘User Widget’ under All Classes;
Create a Widget of class User Widget;
Let’s name it mouseWidget;
Open mouseWidget for editing.
On the Designer panel, we’ll delete the Canvas panel and under Common, drag an Image onto the [mouseWidget] in the Hierarchy. To the top-right of the Canvas Panel, where it says “Fill Screen”, click and select the option “Desired on Screen” to display the image in its true proportions. Our cursor images are 32x32 pixels, so in the Details panel, expand the Brush option and set the Image size to 32 in both X and Y dimensions. We’ll choose our orangeCursor as the brush image. But note that this will not actually determine the appearance of your cursor! It is just a placeholder so that we can see which of the widgets is our cursorWidget for if we want to add this cursor to some other encapsulating Widget system in the future for some reason. To the right of ‘Brush’, click ‘bind’ and create a new binding. This is what our Widget looks like on the Canvas panel (right-click: open in new tab to see the full image):
Creating a new binding opens the Graph view. Create a new variable and call it ‘cursorImg’. Make sure it’s of the Texture2D type. Set your orangeCursor image as its default image. Back on the Designer panel, click the bind button again and select your cursorImg variable as the binding.
Now let’s set the widget up to follow the mouse position wherever it goes. Set up the following blueprint nodes in the Graph view of the mouseWidget:
That’s all for our widget.
Create a new PlayerController blueprint. We’ll call it Mouse_PC. Click to open its Initial Values and scroll down until you see Mouse Interface. We need to make sure Enable Mouseover Events is enabled:
We don’t need the OS default cursor, so we’ve disabled it here, too.
(The enable click events is not strictly necessary for the scope of this tutorial, but may be useful in case you also want to add click interactions later.)
Next, in its Event Graph, set up the following blueprint nodes:
We create a Widget of class mouseWidget and set its cursorImg variable to our orangeCursor texture. Then we promote the resulting reference to a variable for future use. We call it mouseReference. Then, add the Widget to the Viewport.
We are done with our Player Controller.
Finally, we’ll set up an actor that we will hover our mouse over. This actor will tell the Player Controller that it has been moused over and that the cursor should change. Create a square texture sprite (just make it a white square; doesn’t matter). In its Viewport, add a PaperSprite component and make it the square texture sprite that you just created.
Now, in its Event Graph, add the following nodes:
At the begin of play, create a reference to the Mouse_PC Player Controller. We’ll need it later. We create this reference so we don’t need to keep casting to the Mouse_PC whenever we want to tell it to change its cursor.
The next bit is easy. From our Mouse_PC reference, we grab the reference to the mouseWidget we made earlier. And then, ‘as the mouseWidget’, we change the cursorImg to either awesomeCursor or orangeCursor depending on whether we moused over the actor or leave its bounds.
Finally, create a custom GameMode and set up for the Player Controller to be the default Player Controller for this level.
In the World Settings, set this new Game Mode to be the Game Mode Override.
Drag your actor into the level and test!
You can add as many mouse cursors as you like. Just keep grabbing the reference to your Player Controller, which grabs a reference to the mouseWidget and change the cursorImg as you please!
This tutorial can also be extended to 3D space. It doesn’t necessarily only work on sprites. I just found it simpler to explain this with sprites.