ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Unity动态更换鼠标光标:用Cursor.SetCursor与Texture2D实现多状态切换

Unity动态更换鼠标光标:用Cursor.SetCursor与Texture2D实现多状态切换 1. Unity 运行时鼠标光标切换从按钮悬停到拖拽等待的完整落地路径Unity 动态更换鼠标光标这件事说简单也简单一个Cursor.SetCursor就能改说坑也多尤其是贴图导入设置不对、热点坐标算错、CursorMode选错导致光标大小失控这几个问题几乎每个做交互的开发者都会踩一遍。这篇内容聚焦的就是运行时按交互状态动态切换鼠标光标鼠标移到按钮上变成手型、按下拖拽时变成抓取、进入等待区域变成转圈、离开后还原默认箭头。核心 API 就是Cursor.SetCursor(Texture2D, Vector2, CursorMode)配合Texture2D资源导入配置和CursorMode参数控制显示行为。它适合谁适合正在做 Unity UI 交互、2D 拖拽、工具类编辑器、游戏内可点击物件反馈的开发者。你不需要很深的图形学基础只要会用 MonoBehaviour 和基本的碰撞/UI 事件就能跟做。整篇会交付可直接复制的光标纹理导入配置、Cursor.SetCursor调用脚本、CursorMode参数对照表以及进入/离开按钮、拖拽、等待三种状态的验证步骤。我试过把这套逻辑封装成一个光标管理器后面接新状态只需要注册贴图和热点不用每次重写调用代码。先明确一个概念Unity 里的鼠标光标分两层。一层是操作系统光标由Cursor.SetCursor控制另一层是 UI 层面的视觉反馈比如你用 Image 跟着鼠标画一个假光标。本文讲的是前者也就是真正替换系统光标的那条路径。它的好处是零额外 DrawCall、不依赖 Canvas、全局生效代价是热点和尺寸受平台与CursorMode影响需要按规则配置贴图。下面按「问题场景 → 前置准备 → 可复制配置 → 验证请求 → 常见报错 → 后续动作」的顺序展开你可以从头跟到尾也可以直接跳到配置章节抄代码。2. 前置准备光标贴图导入设置与 TaoToken 接入环境在写脚本之前先把贴图资源准备好这一步决定了后面Cursor.SetCursor能不能正常显示。很多人脚本没问题但光标要么不显示、要么糊成一团根源都在导入设置。光标贴图的基本要求使用 PNG带透明通道尺寸建议 32x32 或 64x64。热点hotspot就是光标真正“点击”的那个像素点比如箭头光标的热点在左上角 (0,0)十字准星在中心。热点坐标是相对于贴图左上角计算的这点和 Unity 常见的左下角原点不同后面脚本里会再强调。导入设置的关键项设置项推荐值说明Texture TypeCursor必须选 Cursor否则Cursor.SetCursor行为异常Alpha Is Transparency勾选保证边缘透明正确Read/Write关闭光标不需要 CPU 读取省内存Max Size按需如 64/128ForceSoftware 模式下决定实际显示尺寸CompressionNone 或 High Quality避免光标边缘出现色块Wrap ModeClamp防止边缘采样溢出这里有个容易忽略的点CursorMode.ForceSoftware下光标显示大小不是按贴图原始分辨率而是按资源为 Cursor 类型时的 MaxSize 设置。也就是说你把 256x256 的图 MaxSize 设成 64运行时软件光标就是 64 这个量级。而CursorMode.Auto下 MaxSize 无效显示固定大小。这个差异直接决定了你该选哪种模式。如果你在做的是带 AI 能力的交互工具比如把光标状态和某个模型调用状态联动等待模型返回时显示转圈光标那还需要一个稳定的模型接入环境。我这边常用的是 TaoToken 做统一接入官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 地址是 https://taotoken.net/api 。它的作用是让你在 Unity 里通过标准 HTTP 请求调用模型不用自己维护多套鉴权。具体接入放在下一章先把光标本身跑通。准备清单至少三张光标贴图默认箭头、手型悬停、抓取拖拽可选等待转圈。每张图确认热点坐标记在纸上或注释里。一个空场景 一个 Button 一个可拖拽的 Sprite。3. 可复制配置Cursor.SetCursor 脚本与 CursorMode 参数对照这一章是核心直接给可复制的代码和配置。先看Cursor.SetCursor的签名和参数含义。public static void SetCursor(Texture2D texture, Vector2 hotspot, CursorMode cursorMode);三个参数Texture2D texture要切换成的光标贴图。传null会还原为系统默认光标这是最常用的“离开即还原”手段。Vector2 hotspot光标识别点相对贴图左上角。(0,0) 是左上(width, height) 是右下。注意这里用的是贴图在 Cursor 类型下的 MaxSize 尺寸不是原始分辨率。CursorMode cursorModeAuto或ForceSoftware。Auto下 MaxSize 无效、显示固定大小ForceSoftware下由 MaxSize 控制光标大小。CursorMode参数对照表模式MaxSize 是否生效显示大小适用场景CursorMode.Auto否平台固定大小普通悬停、点击反馈CursorMode.ForceSoftware是由 MaxSize 决定需要自定义光标尺寸、动画光标下面是一个可直接挂到空物体上的光标管理器脚本支持注册多个状态并按名字切换using System.Collections.Generic; using UnityEngine; public class CursorManager : MonoBehaviour { [System.Serializable] public class CursorState { public string stateName; public Texture2D texture; public Vector2 hotspot; public CursorMode mode CursorMode.Auto; } public ListCursorState states new ListCursorState(); private Dictionarystring, CursorState _map; void Awake() { _map new Dictionarystring, CursorState(); foreach (var s in states) { if (!_map.ContainsKey(s.stateName)) _map.Add(s.stateName, s); } } public void Apply(string stateName) { if (_map ! null _map.TryGetValue(stateName, out var s)) { Cursor.SetCursor(s.texture, s.hotspot, s.mode); } else { Cursor.SetCursor(null, Vector2.zero, CursorMode.Auto); } } public void ResetToDefault() { Cursor.SetCursor(null, Vector2.zero, CursorMode.Auto); } }在 Inspector 里配置 states 列表比如stateName: default texture: cursor_arrow hotspot: (0,0) mode: Auto stateName: hover texture: cursor_hand hotspot: (16,0) mode: Auto stateName: drag texture: cursor_grab hotspot: (16,16) mode: ForceSoftware stateName: wait texture: cursor_wait hotspot: (16,16) mode: ForceSoftware如果你要把光标状态和模型调用状态联动比如等待模型返回时切到 wait 光标可以在请求前后调用Apply(wait)和ResetToDefault()。TaoToken 的接入配置可以放在一个独立的请求脚本里用标准 JSON 传参{ model: claude-sonnet-4-20250514, max_tokens: 1024, messages: [ { role: user, content: 你好返回一句问候 } ] }请求地址用 https://taotoken.net/api 鉴权头带上你的 Key。这样光标切换和模型调用就是两条独立但可联动的线互不干扰。4. 验证请求进入/离开按钮、拖拽、等待三种状态的实测步骤配置写完必须验证。这一章给三种状态的实测步骤每一步都有预期结果方便你对照排查。4.1 进入/离开按钮状态验证在场景里放一个 Button给它挂一个脚本实现IPointerEnterHandler和IPointerExitHandlerusing UnityEngine; using UnityEngine.EventSystems; public class HoverCursor : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler { public CursorManager cursorManager; public void OnPointerEnter(PointerEventData eventData) { cursorManager.Apply(hover); } public void OnPointerExit(PointerEventData eventData) { cursorManager.ResetToDefault(); } }验证步骤运行场景鼠标移入按钮预期光标变成手型。鼠标移出按钮预期光标还原为默认箭头。快速反复进出预期不闪烁、不残留错误光标。如果移入没变化先检查 Button 的 Raycast Target 是否勾选再检查 EventSystem 是否存在。4.2 拖拽状态验证给可拖拽物体挂脚本实现IDragHandler、IBeginDragHandler、IEndDragHandlerusing UnityEngine; using UnityEngine.EventSystems; public class DragCursor : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler { public CursorManager cursorManager; public void OnBeginDrag(PointerEventData eventData) { cursorManager.Apply(drag); } public void OnDrag(PointerEventData eventData) { // 拖拽逻辑比如跟随鼠标 transform.position eventData.position; } public void OnEndDrag(PointerEventData eventData) { cursorManager.ResetToDefault(); } }验证步骤按住物体开始拖动预期光标变成抓取样式。拖动过程中保持抓取样式不闪回默认。松开鼠标预期光标还原。注意如果拖拽时光标热点偏移说明 hotspot 设错了。抓取光标的热点通常在中心即 (width/2, height/2)。4.3 等待状态验证等待状态一般由业务逻辑触发比如发起模型请求。写一个简单的协程模拟using System.Collections; using UnityEngine; public class WaitCursorDemo : MonoBehaviour { public CursorManager cursorManager; public void StartWait() { StartCoroutine(WaitRoutine()); } private IEnumerator WaitRoutine() { cursorManager.Apply(wait); yield return new WaitForSeconds(2f); cursorManager.ResetToDefault(); } }验证步骤调用StartWait()预期光标立即变成等待样式。等待 2 秒后预期光标自动还原。如果等待光标尺寸不对检查该状态的 mode 是否为 ForceSoftware以及贴图 MaxSize 是否设成了期望值。三种状态都通过后说明Cursor.SetCursor、Texture2D、CursorMode的配合已经跑通。接下来看常见报错。5. 常见报错排查光标不显示、热点偏移、尺寸异常与请求 401这一章对照真实报错逐个排查。光标问题大多不是代码错而是资源或模式配置错。5.1 光标完全不显示现象调用SetCursor后光标消失或变成透明。 排查顺序贴图 Texture Type 是否为 Cursor。不是的话改成 Cursor 重新导入。贴图是否有透明通道且 Alpha 正确。用图片工具确认。hotspot 是否超出贴图范围。超出会导致不显示改成 (0,0) 试。是否传了 null。传 null 是还原默认不是隐藏。5.2 热点偏移点击位置不对现象光标视觉位置和实际点击点错位。 原因hotspot 坐标系是左上角原点很多人按左下角算。 修正箭头类热点用 (0,0)中心类用 (width/2, height/2)。注意 width/height 是 Cursor 类型下的 MaxSize 尺寸不是原图尺寸。5.3 光标尺寸异常ForceSoftware 下过大或过小现象切到 ForceSoftware 后光标突然变大或变小。 原因ForceSoftware 下显示尺寸由 MaxSize 决定。 修正把该贴图的 MaxSize 调成期望值比如 64。Auto 模式下 MaxSize 无效所以如果你不想被尺寸影响就用 Auto。5.4 模型请求返回 401如果你把光标状态和模型调用联动请求时可能遇到 401。这通常是鉴权头缺失或 Key 错误。 排查确认请求头带了正确的 Authorization。确认 Base URL 是 https://taotoken.net/api 不要多加路径。确认 Key 没有多余空格。如果报 local proxy failed检查本机网络环境是否拦截了请求换一个网络环境重试。如果报 reading choices 相关错误说明返回体结构和预期不符检查 model 字段是否拼写正确。5.5 OAuth 相关报错部分工具链用 OAuth 鉴权如果报 OAuth 错误检查 token 是否过期、回调地址是否配置正确。这类问题一般和光标逻辑无关属于接入层单独排查即可。5.6 光标切换后不还原现象离开按钮后光标还是手型。 原因OnPointerExit没触发或者被其他 UI 遮挡。 修正确认没有全屏透明 Image 挡住射线确认 EventSystem 正常。排查完这些基本能覆盖 90% 的光标问题。剩下的 10% 多半是平台差异比如某些平台对 ForceSoftware 支持有限这时退回 Auto 即可。6. 后续动作把光标状态接到模型对话、Coding Plan 与接入文档光标切换跑通后你可以把它接到更完整的交互链路里。比如做一个 AI 辅助工具鼠标悬停在“生成”按钮上变手型点击后切等待光标模型返回后还原并展示结果。这条链路里模型接入用 TaoToken 就够了。具体动作分三个方向第一验证模型是否可用。打开模型对话页面 https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentchatutm_campaignrewrite 发一条测试消息确认返回正常。这一步能帮你排除 Key 和网络问题再去写 Unity 请求脚本就心里有底。第二长期编码或 Agent 场景。如果你要做的不是单次请求而是持续性的编码辅助或 Agent 循环可以看 Coding Plan https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 它更适合高频调用和长会话。第三接入细节和 Key 管理。所有接入参数、鉴权方式、错误码说明都在接入文档 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite Key 在 API Keys 页面 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 管理。控制台入口是 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 。如果你用的是 Claude Code 这类工具Anthropic 兼容入口在 https://taotoken.net/claude-code-anthropic?utm_sourcetaotoken_aicg_blog_endutm_contentclaudecodeutm_campaignrewrite 配置时同样记住三件套Base URL 填 https://taotoken.net/api Key 填你自己的Model ID 按文档填。这三样缺一不可尤其是 Model ID 写错会直接报模型不存在。回到光标本身最后给一个实用技巧把 CursorManager 做成单例或 ScriptableObject 配置这样多个场景共享同一套光标状态不用每个场景重新拖引用。热点坐标建议在贴图旁边用注释写清楚比如// hotspot (16,16) 中心过两周再回来看也不会忘。光标切换本身不复杂复杂的是状态管理和资源规范把这两块理顺后面接多少种状态都不慌。
返回列表