Skip to main content

Custom Cursors for a Pan and Scroll Camera using Cinemachine

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.
https://learnictnow.com/lesson/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.
https://learnictnow.com/lesson/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);
}
}
}