Hardware Cursor Support

Well, I’ve passed 100 hours of evaluating Unity3D Pro. Many headaches like no included A*Pathfinding and an inability to make Terrain rotations. I’ve got over those hurdles.

Now I’m trying to implement a custom hardware cursor. I’m working on an RTS game, where the state of the cursor is used to communicate quite a lot of visual clues to the player. Using a software cursor is NOT ACCEPTABLE, any lag with the cursor will kill the gaming experience, as documented elsewhere on this forum.

So far my exhaustive searches have lead to:
http://forum.unity3d.com/threads/70163-Hardware-Cursor-Plugin/page2?highlight=custom+cursor

and I’ve finally come up with the following script based on the three Windows-only solutions I can find through Google. When I run the game (within the Editor), the custom mouse pointer appears, but then vanishes when the 3D scene appears, resetting to the default windows cursor. I read somewhere that the solution only worked on .exe builds, so I ran a build and the cursor doesn’t show at all in that. (Windows 7 64-bit).

Is there anyone that has a solution they wouldn’t mind sharing?

using UnityEngine;
using System;
using System.Collections;
using System.Runtime.InteropServices;

public class CursorManager : MonoBehaviour
{
	[DllImport("user32.dll", CharSet=CharSet.Auto, ExactSpelling=true)]
	public static extern IntPtr SetCursor(IntPtr hCursor);
	
	[DllImport("user32.dll")]
	public static extern IntPtr LoadCursor(IntPtr hInstance, int lpCursorName);
	
	[DllImport("user32.dll")]
	public static extern IntPtr LoadImage(IntPtr hInstance, string lpImageName, uint uType, int cxDesired, int cyDesired, uint fuLoad);

	//fuLoad
	public const uint LR_CREATEDIBSECTION     =0x00002000;
	public const uint LR_DEFAULTCOLOR     =0x00000000;
	public const uint LR_DEFAULTSIZE     =0x00000040;
	public const uint LR_LOADFROMFILE     =0x00000010;
	public const uint LR_LOADMAP3DCOLORS     =0x00001000;
	public const uint LR_LOADTRANSPARENT     =0x00000020;
	public const uint LR_MONOCHROME     =0x00000001;
	public const uint LR_SHARED     =0x00008000;
	public const uint LR_VGACOLOR     =0x00000080;
	
	public void ChangeCursorToArrow()
	{
		SetCursor(LoadCursor(IntPtr.Zero, 32512));
	}
	
	public void ChangeCursorToCustom(string filePath)
	{
		SetCursor(LoadImage(IntPtr.Zero, filePath, 2, 0, 0, LR_LOADFROMFILE | LR_DEFAULTSIZE));
	}
	
	public void Init() 
	{
		string cursorPath = Application.dataPath+"/Resources/Cursors/normal.cur";
		ChangeCursorToCustom(cursorPath);
	}
}

Well, looks like it’s the Unity GUI system that is resetting the cursor.

Anyhows, I’ve managed to get lubo3d’s solution working for now, as I have no C++ experience.

Please Unity Team, sort this out in the main API ASAP so it also works when playing in the Editor. I nearly threw in the towel during my eval because of this.

When searching for a way to load another standard cursor already included n the OS, I ended up with this:

      public enum WindowsCursor
        {
            StandardArrowAndSmallHourglass = 32650,
            StandardArrow = 32512,
            Crosshair = 32515,
            Hand = 32649,
            ArrowAndQuestionMark = 32651,
            IBeam = 32513,
            //Icon = 32641, // Obsolete for applications marked version 4.0 or later.
            SlashedCircle = 32648,
            //Size = 32640,  // Obsolete for applications marked version 4.0 or later. Use FourPointedArrowPointingNorthSouthEastAndWest
            FourPointedArrowPointingNorthSouthEastAndWest = 32646,
            DoublePointedArrowPointingNortheastAndSouthwest = 32643,
            DoublePointedArrowPointingNorthAndSouth = 32645,
            DoublePointedArrowPointingNorthwestAndSoutheast = 32642,
            DoublePointedArrowPointingWestAndEast = 32644,
            VerticalArrow = 32516,
            Hourglass = 32514
        }
   
        private static void ChangeCursor(WindowsCursor cursor){
            SetCursor(LoadCursor(IntPtr.Zero , (int)cursor));
        }
   
        [DllImport("user32.dll", EntryPoint = "SetCursor")]
        public static extern IntPtr SetCursor(IntPtr hCursor);
   
        [DllImport("user32.dll", EntryPoint = "LoadCursor")]
        public static extern IntPtr LoadCursor(IntPtr hInstance, int lpCursorName);