当前位置: 首页 > news >正文

Rokid UXR 的手势追踪虚拟中更真实的手实战开发【含 工程源码 和 最终完成APK】

一、项目介绍

本文将带你基于Rokid UXR SDK 3.0.3 + 团结引擎

开发一个沉浸式的 AR 空间Demo——虚拟中更真实的手

在这个Demo中:

  • 小人会自动寻路找金币

  • 玩家移动整个手掌,即可挡住虚拟小人物体;

这是一个非常适合初学者上手的Rokid AR 实战案例

二、环境准备

  • 设备:Rokid AR Studio眼镜

  • SDK:Rokid UXR SDK 3.0.3

  • 引擎:团结引擎 1.6.5

注:全文必须在官方SDKRokid UXR SDK 3.0.3 已完成接入指南后,也就是完成如下章节后才可开始学习(custom.rokid.com/prod/rokid_web/c88be4bcde4c42c0b8b53409e1fa1701/pc/cn/8ad2e74dbd7c4f5bb21a964dbdd5512d.html?documentId=965ccb56e0284976ab0c701346f5833e

三、核心功能拆解

步骤 1:创建场景基础

1.1 创建并打开场景
  • Assets/Scenes/BoneFollowHand创建好BoneFollowHand这个空场景

  • 拖入RKCameraRig[RKInput],配置如下

1.2 创建地面
  1. 在 Hierarchy 中右键 → 3D Object → Cube

  2. 命名为 "Plane",位置配置如下(因为此处需要考虑手掌和实际大小,故设置为长宽30cm的平面,高1cm)

*Unity中1u=实际1米

  1. Plane.mat材质拖到 Ground 上

这里创建个材质给个颜色即可

步骤 2:设置手追

2.1 创建手部追踪管理器
  1. 在 Hierarchy 中创建空物体:GameObject → Create Empty

  2. 命名为 "HandBoneFollower26"

  3. 添加HandBoneFollower26.cs脚本

如下为脚本

using Rokid.UXR.Interaction; using Rokid.UXR.Module; using System.Collections.Generic; using UnityEngine; public class HandBoneFollower26 : MonoBehaviour { [Header("默认跟随预制体(Prefab 或 Scene 物体均可)")] public GameObject bonePrefab; [Header("目标手选择")] public HandType handType = HandType.RightHand; [Header("偏移设置")] public Vector3 offset = Vector3.zero; public Vector3 rotationOffsetEuler = Vector3.zero; [System.Serializable] public class CustomBoneObject { public SkeletonIndexFlag flag; public GameObject customPrefab; // 既支持Prefab,也支持Scene物体 } public List<CustomBoneObject> customBones = new List<CustomBoneObject>(); private Dictionary<SkeletonIndexFlag, GameObject> boneFollowers = new Dictionary<SkeletonIndexFlag, GameObject>(); private Dictionary<SkeletonIndexFlag, GameObject> customPrefabMap = new Dictionary<SkeletonIndexFlag, GameObject>(); void Awake() { foreach (var cb in customBones) { if (!customPrefabMap.ContainsKey(cb.flag)) customPrefabMap.Add(cb.flag, cb.customPrefab); } } void Start() { foreach (SkeletonIndexFlag flag in System.Enum.GetValues(typeof(SkeletonIndexFlag))) { GameObject targetPrefab = customPrefabMap.ContainsKey(flag) ? customPrefabMap[flag] : bonePrefab; GameObject obj; // 支持 Scene 物体(不实例化,直接使用原物体) if (targetPrefab.scene.IsValid()) { obj = targetPrefab; // 直接使用场景物体 Debug.Log($"[Follower] 使用场景物体作为骨骼节点: {flag}"); } else { obj = Instantiate(targetPrefab, transform); Debug.Log($"[Follower] 实例化 Prefab 用作骨骼节点: {flag}"); } obj.name = "Follower_" + flag; obj.SetActive(false); boneFollowers.Add(flag, obj); } } void Update() { if (GesEventInput.Instance == null) return; foreach (var pair in boneFollowers) { var flag = pair.Key; var obj = pair.Value; Pose pose = GesEventInput.Instance.GetSkeletonPose(flag, handType); bool detected = pose.position != Vector3.zero; obj.SetActive(detected); if (!detected) continue; Vector3 worldPos = pose.position + pose.rotation * offset; Quaternion worldRot = pose.rotation * Quaternion.Euler(rotationOffsetEuler); obj.transform.SetPositionAndRotation(worldPos, worldRot); } } }
2.2 配置 HandBoneFollower26 脚本

基础设置:

  • Bone Prefab: 拖入Default(默认骨骼显示物体)

此处由于是自定义手骨,需考虑正常手骨大小,因此修改缩放,下图1是默认手骨,但是掌心骨头是平面型较大,因此需要做个扁方块作为Palm掌心骨,配置如下图

  • Hand Type: 选择RightHandLeftHand

这里由于骨头模型默认是不带偏移和朝向的,因此为了贴合手掌,将脚本设置改为y轴和z轴旋转90度,这样可以不需要管预制体的旋转或偏移

为了完成只显示手骨,不显示原始手模,需按照官方sdk中如下部分内容复制好

custom.rokid.com/prod/rokid_web/c88be4bcde4c42c0b8b53409e1fa1701/pc/cn/8ad2e74dbd7c4f5bb21a964dbdd5512d.html?documentId=8869a42f3935436e90bead5e2c79fb73

本次要调整的是右手,这里直接把对应渲染器渲染图层设为UI层,即可隐藏渲染,这里放到UI层取决于摄影机设置

步骤 3:创建金币收集游戏

3.1 创建玩家对象
  1. 在 Hierarchy 中创建 Capsule:3D Object → Capsule

  2. 命名为 "Player"

  3. 设置 大小和旋转,因为也要考虑大小,因此这里的大小只有几cm

  1. 为了好看添加材质Player.mat

3.2 添加玩家眼睛
  1. 创建 Sphere:3D Object → Cube

  2. 命名为 "PlayerEye"

  3. 设为 Player 的子物体

  4. 设置 Transform:

  1. 添加材质PlayerEye.mat

3.3 配置玩家碰撞器
  1. 选中 Player 对象

  2. 确保有 Capsule Collider 组件

  3. 添加 Rigidbody 组件:

    • 这里只需要把位置锁,锁上x和z轴旋转即可,这样就不会东倒西歪了,同时还有重力

3.4 添加金币收集脚本
  1. 选中 Player 对象

  2. 添加AutoCoinCollector.cs脚本

using System.Collections.Generic; using UnityEngine; public class AutoCoinCollector : MonoBehaviour { public enum GameState { Start, Playing, End } [Header("UI")] public GameObject startUI; public GameObject endUI; [Header("金币父物体")] public List<Transform> coinParents = new List<Transform>(); [Header("金币Prefab")] public GameObject coinPrefab; [Header("当前金币")] public List<Transform> coins = new List<Transform>(); [Header("移动")] public float moveSpeed = 3f; public float rotateSpeed = 360f; public float arriveDistance = 0.1f; [Header("Debug")] public bool showDebug = true; private Transform currentTarget; private GameState state = GameState.Start; private List<Vector3> coinPositions = new List<Vector3>(); private List<Quaternion> coinRotations = new List<Quaternion>(); void Start() { RecordCoinData(); ShowStartUI(); } void Update() { if (state != GameState.Playing) return; if (currentTarget == null) { FindRandomCoin(); return; } MoveToTarget(); } // ===== UI 控制 ===== void ShowStartUI() { startUI.SetActive(true); endUI.SetActive(false); } void ShowEndUI() { startUI.SetActive(false); endUI.SetActive(true); } // ===== 按钮事件 ===== public void StartGame() { if (showDebug) Debug.Log("开始游戏"); startUI.SetActive(false); endUI.SetActive(false); state = GameState.Playing; FindRandomCoin(); } public void RestartGame() { if (showDebug) Debug.Log("重新开始"); RegenerateCoins(); startUI.SetActive(false); endUI.SetActive(false); state = GameState.Playing; FindRandomCoin(); } // ===== 金币数据 ===== void RecordCoinData() { coins.Clear(); coinPositions.Clear(); coinRotations.Clear(); foreach (Transform parent in coinParents) { foreach (Transform child in parent) { coins.Add(child); coinPositions.Add(child.position); coinRotations.Add(child.rotation); } } } void RegenerateCoins() { coins.Clear(); for (int i = 0; i < coinPositions.Count; i++) { GameObject coin = Instantiate( coinPrefab, coinPositions[i], coinRotations[i] ); coins.Add(coin.transform); } } // ===== AI 移动 ===== void MoveToTarget() { Vector3 dir = currentTarget.position - transform.position; dir.y = 0; float distance = dir.magnitude; if (distance <= arriveDistance) return; Vector3 moveDir = dir.normalized; Quaternion targetRot = Quaternion.LookRotation(moveDir); transform.rotation = Quaternion.RotateTowards( transform.rotation, targetRot, rotateSpeed * Time.deltaTime ); transform.position += transform.forward * moveSpeed * Time.deltaTime; } void FindRandomCoin() { if (coins.Count == 0) { GameOver(); return; } int index = Random.Range(0, coins.Count); currentTarget = coins[index]; if (showDebug) Debug.Log("目标金币: " + currentTarget.name); } void GameOver() { if (showDebug) Debug.Log("所有金币已吃完"); state = GameState.End; ShowEndUI(); } // ===== 吃金币 ===== private void OnTriggerEnter(Collider other) { if (coins.Contains(other.transform)) { if (showDebug) Debug.Log("吃掉金币: " + other.name); coins.Remove(other.transform); Destroy(other.gameObject); currentTarget = null; } } // ===== 绘制路线 ===== void OnDrawGizmos() { if (currentTarget == null) return; Gizmos.color = Color.red; Gizmos.DrawLine(transform.position, currentTarget.position); } }

步骤 4:创建金币系统

4.1 创建金币父物体
  1. 创建空物体:GameObject → Create Empty命名为 "CoinObject"

4.2 创建金币
  1. 创建一个圆柱,给压扁就是金币模型

将金币调整大小和位置,适配整体大小,并制作成预制体,如下只需要注意旋转和缩放即可,位置在场景自由摆放

4.3 配置金币

每个金币需要:进行配置,主要是勾选触发器,同时为了美观,增加一个自转脚本,创建个金色的材质Coin.mat,拖入即可

using UnityEngine; public class CoinRotate : MonoBehaviour { [Header("旋转速度 (度/秒)")] public float rotateSpeed = 180f; [Header("旋转轴")] public Vector3 rotateAxis = Vector3.up; [Header("Debug")] public bool showDebug = false; void Update() { transform.Rotate(rotateAxis * rotateSpeed * Time.deltaTime); if (showDebug) { Debug.Log($"[CoinRotate] {gameObject.name} 正在旋转 速度:{rotateSpeed}"); } } }

步骤 5:创建 UI 界面

5.1 创建 Canvas

使用官方预制体,拖入两个,一个命名为开始,一个命名为重新开始,在Canvas下各自新建一个按钮,命名为开始和重新开始即可

步骤 6:配置 AutoCoinCollector 脚本

选中 Player 对象,将脚本直接拖入进去,在 Inspector 中配置:

6.1 UI 设置
  • Start UI: 拖入 StartUI 整个物体

  • End UI: 拖入 RestartUI 整个物体

6.2 金币父物体
  • 拖入场景中的CoinObject物体

6.3 金币 Prefab
  • Coin Prefab: 拖入文件中的预制体Coin.prefab

6.4 移动参数

这里为了匹配小人,需考虑速度和靠近距离

  • Move Speed: 0.03(移动速度)

  • Rotate Speed: 360(旋转速度)

  • Arrive Distance: 0.001(到达距离)

6.5 调试
  • Show Debug: 勾选,会显示小人下一个吃哪个金币

步骤 7:连接 UI 按钮事件

7.1 开始按钮
  1. 选中 StartUI 下的 Button

  2. 在 Inspector 中找到 Button 组件

  3. 在 OnClick() 事件中:

    • 点击 +

    • 拖入 Player 对象

    • 选择函数:AutoCoinCollector.StartGame()

7.2 重新开始按钮
  1. 选中 EndUI 下的 Button

  2. 在 OnClick() 事件中:

    • 点击 +

    • 拖入 Player 对象

    • 选择函数:AutoCoinCollector.RestartGame()

完整脚本部分

只用到3个脚本,分别为AutoCoinCollectorCoinRotateHandBoneFollower26

用到4个材质,分别为CoinPlanePlayerPlayerEye

共3个预制体PalmDefaultCoin

四、打包与安装

当我们在编辑器里调试完成后,最后一步就是打包并安装到 Rokid AR Studio 眼镜上进行真机体验

五 、结束语

到这里,我们已经完成了一个基于 Rokid UXR SDK 3.0.3 + 团结引擎的手追Demo。

这个项目虽然简单,但涵盖了 Rokid AR 开发的核心要点:

  • 如何使用 UXR 获取骨架关节数据并驱动场景对象;

  • 如何结合团结引擎完成动态物体生成与材质管理;

  • 如何构建一个完整的「开始 → 进行 → 结束」游戏流程。

希望通过这篇实战,你可以对手势追踪有个更好的了解

最终完成安装包

001.apk

工程源码

RokidHandDemoo.zip

http://www.jsqmd.com/news/453830/

相关文章:

  • 开发者的临时文件自动化工具:提升效率与系统整洁度的关键方案
  • 别只当它是管家,RT-Thread 会自己生长
  • 权威解读:企业合作政策如何让非科班生通过国内AI认证实现“弯道超车”?
  • 2026年房山及燕山地区装修套餐全解析:五大优质服务商深度推荐 - 品牌2026
  • openclaw gateway status报错且gate无法正常运行解决办法
  • 无数绘画测试!Nano Banana 2 vs GPT Image 1.5,谁才是最厉害的模型
  • LeetCode-35.搜索插入位置
  • 基于javaweb的作业智能推荐系统的设计与实现
  • 2026超纯水机厂家推荐:进口与国产品牌实力对比 - 品牌推荐大师
  • 光学神经网络:进展与挑战(Optical Neural Networks: Progress and Challenges)
  • 如何本地部署大模型(以PaddleOCR-VL-1.5为例)
  • 2026年房山环保家装公司怎么选?五家实力装企深度解析 - 品牌2026
  • Gemini 3.1 Flash Image Preview (Nano Banana 2) 深度技术评测与极速接入指南
  • 2026最新25万级SUV智驾领先双能源车型推荐!权威榜单发布 - 十大品牌榜
  • ESP-IDF Chip revision问题解决方案
  • 2026年 信捷电气厂家推荐排行榜:江苏/安徽/上海/苏州/常州/合肥/芜湖/南京/镇江/南通/徐州/无锡,专业自动化解决方案与技术创新实力深度解析 - 品牌企业推荐师(官方)
  • 留学申请服务费用多少,考虑性价比,澳洲、马来西亚有啥好选择 - mypinpai
  • ARM Cortex-R52 内核详解(三)——异常处理机制
  • 【hello-agent】Plan-and-Solve
  • 2026 电池放电仪、电池内阻仪厂家:技术与口碑的双重认证 - 深度智识库
  • 计算机毕业设计源码:基于Python的智能推荐电商平台 Django Vue3 Scrapy爬虫 协同过滤推荐算法 大模型 购物 多模态 deepseek agent(建议收藏)✅
  • 2026最新25万级SUV/25万级SUV智驾/25万级SUV轿跑/25万级SUV双能源车型推荐:智驾领跑,实力重塑出行标杆 - 十大品牌榜
  • 2026年广州响应式网站建设,谁才是真正的口碑之选?
  • 2026年全国ITSS咨询服务机构费用盘点,上海擎标价格合理 - mypinpai
  • 2026最新25万级SUV轿跑品牌推荐!权威榜单出炉,科技与性能兼具 - 十大品牌榜
  • 2026年沧州耐用打包机定做厂家推荐,这些值得关注!打捆机/全自动打捆机/打包机/半自动打捆机,打包机制造厂怎么选择 - 品牌推荐师
  • Suno Lyrics Generation API
  • 2026年房山新房装修公司怎么选?5家本土深耕与标准化整装品牌推荐 - 品牌2026
  • Product Hunt 每日热榜 | 2026-03-08
  • 测试分类xxxxx