Per-state cursors in Unity (hover, click, drag)

Swap the cursor on UI hover with EventSystem hooks for proper drag-and-drop game UI. · 9 min read

What you'll build

Swap the cursor on UI hover with EventSystem hooks for proper drag-and-drop game UI.

Steps

  1. Implement IPointerEnterHandler on the UI element
  2. On enter, call Cursor.SetCursor(hoverTexture, ...)
  3. On exit, restore default
  4. On drag, swap to grabbing texture in OnBeginDrag / OnEndDrag

Why this works

Custom cursors are the smallest, most-viewed piece of UI on a desktop. The technique above applies the smallest possible change that achieves the goal — no extra dependencies, no custom event loop, no accessibility regression. If you change exactly what these steps describe and nothing else, the cursor swap is invisible to assistive tech, undisturbed by browser or OS updates, and free of the memory leaks common to JS-driven cursor implementations.

Common mistakes

  • Skipping the hotspot. The hotspot is the pixel inside your cursor image that actually counts as the click point. Defaulting to (0, 0) is wrong for almost every cursor type. Tune it, then test on a 1-pixel target.
  • Skipping the fallback. Custom cursor URLs without a fallback keyword are silently ignored by some browsers. Always end the rule with pointer, auto, crosshair, or whatever system cursor matches the role.
  • Antialiasing the pixel grid. If you ship a 16x16 PNG and the browser scales it, you lose the pixel art. Ship a 32x32 (2x) variant, or use SVG with shape-rendering="crispEdges".
  • Animating idle cursors. Even a great animation makes the cursor feel restless. Reserve animation for busy, working, and progress states.

Testing checklist

  • Hover over a white background (Stack Overflow), a black background (a code editor), and a chaotic background (a YouTube grid). The cursor must be visible on all three.
  • Verify the hotspot lands where the cursor "feels like" it points by hovering over a tiny target.
  • If the cursor is animated, watch it for 30 seconds without context. If it gets distracting, slow it down or remove animation.
  • Test in at least two browsers and on a HiDPI display. Cursor handling differs more across browsers than most CSS properties.

Game-engine recipes

For copy-paste recipes per engine, see the game dev hub. Each entry includes the minimal code, the official docs link, and a known-good Godot/Unity/Unreal version.

Pick a pack to try this with

If you want a cursor pack to use as the source for this tutorial, browse the collections page or jump straight to a free CC0 set on the community assets page. Both pages link to packs you can download right now.