HCI (UI User Interface / UX User eXperience)

Custom Cursors for a Pan and Scroll Camera using Cinemachine

You don’t have access to this lesson
Please register or sign in to access the course content.

You can access a windows example here.

You need to have completed the lesson on creating a Pan and Zoom camera before attempting this one and expecting it to work fully. You can use this to learn how to change cursors though.

The code below is what is used to change the cursor. It takes three arguments:

  • The new cursor
  • The point x,y of the new cursor image that will be used to interact with objects
  • and how the cursor should work.
Cursor.SetCursor(newCursor, clickPoint, cursorMode);

First design or select your cursors. Eight png files are shown below, these have been used in the example.

Import the new cursor images you want to use.

Change the type of the image to Sprite (2D and UI) in the Inspector.

Create a script for managing the Custom Cursors.

Attach this to the CameraManager.

Setup the variables by including steps 1-6 from the code below.

1 brings in cinemachine

2 links the Cinemachine input provider to determine the x and y position of the mouse.

3 set the percentage of the border for when to change the cursor. In this example 5%

4 is an array to store the cursor position.

5 is the default cusror mode for Unity

6 is the origin point for the cursor to us when the mouse is clicked.

/*
    This script relies on the Pan and Zoom Camera Control lesson having been completed.
    
RTS Style Pan and Zoom Camera using Cinemachine
*/ using System.Collections; using System.Collections.Generic; using UnityEngine; // 1. Cinemachine objects using Cinemachine; public class CustomCursorScreenEdge : MonoBehaviour { // 2. Cinemachine new input provider [SerializeField] private CinemachineInputProvider _inputProvider; // 3. Percentage of the screen border to change icon / cursor at [SerializeField] private float _scrollBorderPercent = 0.05f; /* 4. Array to store icons for the cursors 0 - Up 1 - Upper Right 2 - Right 3 - Lower Right 4 - Down 5 - Lower Left 6 - Left 7 - Upper Left */ public Texture2D[] cursorTextures; // 5. Default cursor mode for Unity public CursorMode cursorMode = CursorMode.Auto; /* 6. Origin point (where the mouse clicks) for the cursor Default is 0,0 */ public Vector2 hotSpot = Vector2.zero; }

Save and switch back to Unity.

Add an array size of 8 to the Cursor textures and then drag in the images.

Now we need to write the update function to detect which corner or edge of the screen (or centre) the mouse cursor is currently in. See the comments for 7 through to 20 in the code below for explanations.

Point 11 in the code is what is used to change the cursor.

/*
    This script relies on the Pan and Zoom Camera Control lesson having been completed.
    
RTS Style Pan and Zoom Camera using Cinemachine
*/ using System.Collections; using System.Collections.Generic; using UnityEngine; // 1. Cinemachine objects using Cinemachine; public class CustomCursorScreenEdge : MonoBehaviour { // 2. Cinemachine new input provider [SerializeField] private CinemachineInputProvider _inputProvider; // 3. Percentage of the screen border to change icon / cursor at [SerializeField] private float _scrollBorderPercent = 0.05f; /* 4. Array to store icons for the cursors 0 - Up 1 - Upper Right 2 - Right 3 - Lower Right 4 - Down 5 - Lower Left 6 - Left 7 - Upper Left */ public Texture2D[] cursorTextures; // 5. Default cursor mode for Unity public CursorMode cursorMode = CursorMode.Auto; /* 6. Origin point (where the mouse clicks) for the cursor Default is 0,0 */ public Vector2 hotSpot = Vector2.zero; // Update is called once per frame void Update() { // 7. x and y mouse position for the CineMachine input Provider float x = _inputProvider.GetAxisValue(0); float y = _inputProvider.GetAxisValue(1); /* 8. The next set of nested if statements handles which cursor to load. It needs to check if the cursor is at the top of the screen, bottom, left, or right. If the cursor is also at the top or the bottom it also needs to check if the cursor is in the left or right corner as well. */ // 9. If at the top of the screen if(y >= Screen.height * (1 - _scrollBorderPercent)) { // 10. Check if on the right as well if(x >= Screen.width * (1 - _scrollBorderPercent)) { // 11. If so change the cursor to top right Cursor.SetCursor(cursorTextures[1], Vector2.zero, cursorMode); } else // 12. Check if in top left as well if(x <= Screen.width * _scrollBorderPercent) { Cursor.SetCursor(cursorTextures[7], Vector2.zero, cursorMode); } else { // 13. Otherwise the cursor is at the top so display that cursor Cursor.SetCursor(cursorTextures[0], Vector2.zero, cursorMode); } } else // 14. Check if at the bottom of the screen if(y <= Screen.height * _scrollBorderPercent) { // 15. Check if also in the lower right if(x >= Screen.width * (1 - _scrollBorderPercent)) { Cursor.SetCursor(cursorTextures[3], Vector2.zero, cursorMode); } else // 16. Check if also in the lower left if(x <= Screen.width * _scrollBorderPercent) { Cursor.SetCursor(cursorTextures[5], Vector2.zero, cursorMode); } else { // 17. In the bottom only Cursor.SetCursor(cursorTextures[4], Vector2.zero, cursorMode); } } else /* 18. Check if on the right (we don't need to check the corners as we did this as well) */ if(x >= Screen.width * (1 - _scrollBorderPercent)) { Cursor.SetCursor(cursorTextures[2], Vector2.zero, cursorMode); } else // 19. Check if on the left if(x <= Screen.width * _scrollBorderPercent) { Cursor.SetCursor(cursorTextures[6], Vector2.zero, cursorMode); } else { /* 20. If none of these are true the cursor is not in the scroll area. So display the default cursor. */ Cursor.SetCursor(null, Vector2.zero, cursorMode); } } }