Unity3D结合ARKit实现人体动作捕捉
在移动设备上实时捕捉人体动作,曾经是专业影视制作或高端游戏开发的专属能力。如今,一台普通的 iPhone 配合 Unity3D 和 ARKit,就能完成高精度的全身骨骼追踪——无需外接传感器、无需绿幕,甚至不需要额外硬件。
这背后的核心推动力,是 Apple 自 iOS 13 起引入的ARKit 人体追踪(Human Body Tracking)功能。它利用 A12 仿生芯片内置的神经引擎,在前置 TrueDepth 摄像头上实现了基于深度学习的人体姿态估计算法。而 Unity 的ARFoundation 框架则为跨平台 AR 开发提供了统一接口,让开发者可以用 C# 快速构建交互式应用。
更进一步地,随着多模态大模型的发展,我们不再只能“手动调试”关节点映射逻辑。像Qwen3-VL这类视觉语言模型,已经能够理解图像中的骨架结构、自动生成代码片段,甚至帮助分析动作数据流,真正成为开发者的“智能协作者”。
环境准备:软硬件缺一不可
要跑通这套系统,必须满足一定的软硬件条件。毕竟,这不是普通图像识别,而是对实时性、算力和系统底层支持都有要求的空间计算任务。
硬件清单
- Mac 电脑:macOS Sonoma 或更高版本(推荐 macOS 14+)
- iOS 设备:iPhone XR 及以上机型,或 iPad Pro (2018) 及更新型号
- 必须搭载A12 仿生芯片或更强
- 支持TrueDepth 前置摄像头(用于精准面部与身体追踪)
💡 小知识:ARKit 的人体追踪依赖于 Neural Engine(神经网络加速器),A12 是首款集成该模块的芯片。低于此配置的设备无法启用此功能。
软件栈要求
| 组件 | 最低版本 | 推荐版本 |
|---|---|---|
| Unity Editor | 2021.3 LTS | 2022.3+ |
| Xcode | 15.0 | 最新版 |
| iOS 系统 | iOS 16.0 | 最新版 |
| ARFoundation & ARKit Plugin | 5.0 | 5.2+ |
此外,你需要一个激活的Apple Developer 账户,以便在真机上签名并部署应用。否则即使构建成功,也无法安装运行。
开发前奏:用 Qwen3-VL 加速理解
与其一头扎进代码,不如先借助 AI 提升认知效率。Qwen3-VL是通义千问系列中最新一代视觉-语言模型,具备强大的图像解析与空间推理能力。它不仅能读懂文档截图,还能反向生成可用于 Unity 的数据结构。
比如,你可以上传一张 ARKit 官方文档中的人体关节点示意图,然后提问:
请解析图中的人体关节点命名规则,并将其转换为 Unity 中可用的 Transform 映射字典。切换到Thinking模式后,模型可能会返回如下结构化输出:
public enum JointIndex { Head, Neck, LeftShoulder, RightShoulder, LeftElbow, RightElbow, LeftWrist, RightWrist, LeftHip, RightHip, LeftKnee, RightKnee, LeftAnkle, RightAnkle }或者直接生成一个Dictionary<XRHumanBodyJoint, string>的映射表,方便你在调试时打印关节名称。
这种“看图写码”的能力极大降低了初学者的理解门槛。你不再需要死记硬背 ARKit 的关节层级,而是让 AI 帮你建立从视觉到代码的桥梁。
构建项目:从零开始搭建 AR 场景
打开 Unity Hub,创建一个新的 3D (URP) 项目,命名为ARBodyTrackingDemo。
导入必要插件
进入Window > Package Manager,确保安装以下三个核心包:
- AR Foundation
- ARKit XR Plugin
- Universal Render Pipeline(URP,若未自动安装)
安装完成后,前往Project Settings > XR Plug-in Management,启用iOS平台,并勾选 ARKit 插件。
📌 实用技巧:不确定某个功能是否支持?直接在 Qwen3-VL 中问:“Unity ARFoundation 是否支持 ARKit 全身骨骼追踪?” 模型会引用官方文档给出权威回答。
场景结构设计
在 Hierarchy 中创建以下对象:
AR SessionAR Session Origin- 创建空 GameObject,命名为
HumanBodyTracker,并挂载脚本HumanBodyTracking.cs
此时场景结构如下:
- AR Session - AR Session Origin └─ HumanBodyTracker (with HumanBodyTracking.cs)其中:
-AR Session控制 AR 功能的整体生命周期
-AR Session Origin是所有 AR 内容的根节点,其子对象会随真实世界移动而动态更新坐标
-HumanBodyTracker负责处理人体检测逻辑
编写核心脚本:人体追踪控制
打开HumanBodyTracking.cs,开始编写主要逻辑。
引入命名空间
using UnityEngine; using UnityEngine.XR.ARFoundation; using UnityEngine.XR.ARSubsystems; using System.Collections.Generic;定义变量
public class HumanBodyTracking : MonoBehaviour { [SerializeField] private ARHumanBodyManager humanBodyManager; [SerializeField] private GameObject jointPrefab; // 关节球体预制体 [SerializeField] private Material boneMaterial; // 骨骼连线材质 private Dictionary<XRHumanBodyJoint, Transform> bodyJoints; private List<LineRenderer> lineRenderers; }jointPrefab可以是一个简单的白色小球(Sphere),boneMaterial使用半透明线条材质以增强可视化效果。
注册事件监听:感知人体变化
ARKit 每帧都会更新人体数据,我们需要通过事件机制来响应这些变化。
private void OnEnable() { if (humanBodyManager != null) { humanBodyManager.humanBodiesChanged += OnHumanBodiesChanged; } } private void OnDisable() { if (humanBodyManager != null) { humanBodyManager.humanBodiesChanged -= OnHumanBodiesChanged; } }这个humanBodiesChanged事件是整个系统的“心跳”。每当摄像头检测到新人体出现或现有姿态更新时,都会触发回调。
处理新增与更新的人体
private void OnHumanBodiesChanged(ARHumanBodiesChangedEventArgs eventArgs) { foreach (var addedBody in eventArgs.added) { InitializeBody(addedBody); } foreach (var updatedBody in eventArgs.updated) { UpdateBodyPose(updatedBody); } }目前 ARKit 仅支持单人全身追踪(多人仍在实验阶段)。因此每次最多只有一个ARHumanBody实例被处理。
初始化关节点与骨骼线
当新的人体被检测到时,我们需要为其创建可视化的关节点和连接线。
private void InitializeBody(ARHumanBody arBody) { if (bodyJoints == null) { bodyJoints = new Dictionary<XRHumanBodyJoint, Transform>(); CreateJoint(XRHumanBodyJoint.Head, arBody); CreateJoint(XRHumanBodyJoint.LeftShoulder, arBody); CreateJoint(XRHumanBodyJoint.RightShoulder, arBody); CreateJoint(XRHumanBodyJoint.LeftElbow, arBody); CreateJoint(XRHumanBodyJoint.RightElbow, arBody); CreateJoint(XRHumanBodyJoint.LeftWrist, arBody); CreateJoint(XRHumanBodyJoint.RightWrist, arBody); CreateJoint(XRHumanBodyJoint.LeftHip, arBody); CreateJoint(XRHumanBodyJoint.RightHip, arBody); CreateJoint(XRHumanBodyJoint.LeftKnee, arBody); CreateJoint(XRHumanBodyJoint.RightKnee, arBody); CreateJoint(XRHumanBodyJoint.LeftFoot, arBody); CreateJoint(XRHumanBodyJoint.RightFoot, arBody); } CreateBoneLines(); } private void CreateJoint(XRHumanBodyJoint jointType, ARHumanBody arBody) { var anchor = arBody.GetOrCreateAnchor(jointType.ToString()); var instance = Instantiate(jointPrefab, anchor.transform); bodyJoints[jointType] = instance.transform; }每个关节点都绑定在一个Transform上,由 ARKit 自动驱动其位置与旋转。
实时更新姿态数据
每帧调用UpdateBodyPose来同步最新骨骼状态。
private void UpdateBodyPose(ARHumanBody arBody) { if (arBody.trackingState != TrackingState.Tracking) return; foreach (var kvp in bodyJoints) { if (arBody.TryGetBone(kvp.Key, out XRRigBone bone)) { kvp.Value.localPosition = bone.position; kvp.Value.localRotation = bone.rotation; } } UpdateBoneLines(); }XRRigBone包含了每个关节的位置、旋转和置信度信息,可用于后续滤波或动作识别。
绘制骨骼连线
使用LineRenderer连接关键点,形成完整骨架。
private void CreateBoneLines() { var connections = new[] { new[] { XRHumanBodyJoint.Head, XRHumanBodyJoint.Neck }, new[] { XRHumanBodyJoint.Neck, XRHumanBodyJoint.LeftShoulder }, new[] { XRHumanBodyJoint.Neck, XRHumanBodyJoint.RightShoulder }, new[] { XRHumanBodyJoint.LeftShoulder, XRHumanBodyJoint.LeftElbow }, new[] { XRHumanBodyJoint.LeftElbow, XRHumanBodyJoint.LeftWrist }, new[] { XRHumanBodyJoint.RightShoulder, XRHumanBodyJoint.RightElbow }, new[] { XRHumanBodyJoint.RightElbow, XRHumanBodyJoint.RightWrist }, new[] { XRHumanBodyJoint.LeftHip, XRHumanBodyJoint.RightHip }, new[] { XRHumanBodyJoint.LeftHip, XRHumanBodyJoint.LeftKnee }, new[] { XRHumanBodyJoint.LeftKnee, XRHumanBodyJoint.LeftFoot }, new[] { XRHumanBodyJoint.RightHip, XRHumanBodyJoint.RightKnee }, new[] { XRHumanBodyJoint.RightKnee, XRHumanBodyJoint.RightFoot } }; foreach (var conn in connections) { var lineObj = new GameObject("BoneLine"); var line = lineObj.AddComponent<LineRenderer>(); line.material = boneMaterial; line.startWidth = 0.01f; line.endWidth = 0.01f; line.positionCount = 2; line.useWorldSpace = true; lineRenderers.Add(line); } } private void UpdateBoneLines() { int i = 0; var connections = new[] { new[] { XRHumanBodyJoint.Head, XRHumanBodyJoint.Neck }, // ... 同上 }; foreach (var conn in connections) { if (bodyJoints.TryGetValue(conn[0], out Transform t0) && bodyJoints.TryGetValue(conn[1], out Transform t1)) { lineRenderers[i].SetPositions(new Vector3[] { t0.position, t1.position }); } i++; } }🤖 提示:你可以让 Qwen3-VL 自动生成这份连接数组。只需提问:“请给出标准人体骨架的 LineRenderer 连接顺序”,即可获得拓扑结构代码。
构建与部署到 iOS
设置构建参数
- File → Build Settings → 切换平台为iOS
- Player Settings 中配置:
- Architecture: ARM64
- Scripting Backend: IL2CPP
- API Compatibility Level: .NET Standard 2.1
- Company Name / Product Name / Bundle Identifier(如 com.yourname.ARBodyTrack)
导出 Xcode 工程
点击Build,选择输出目录(建议Build/iOS)
Unity 将生成.xcodeproj文件。
Xcode 配置要点
- 用 Xcode 15+ 打开工程
- 连接设备,选择目标
- Signing & Capabilities:
- 启用 Automatic Signing
- 登录 Apple ID 并选择 Team - 添加隐私描述:
- 在Info.plist中添加:xml <key>NSCameraUsageDescription</key> <string>本应用需要访问相机以识别人体动作</string> - 点击 ▶️ Run
✅ 成功标志:设备屏幕显示彩色骨架,随人物动作实时变化!
常见问题排查
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 黑屏或启动崩溃 | 缺少相机权限描述 | 添加NSCameraUsageDescription |
| 不显示骨架 | ARHumanBodyManager未正确引用 | 检查是否在 AR Session Origin 下赋值 |
| 关节抖动严重 | 光照不足或背景杂乱 | 改善照明,穿深色衣物,保持简洁背景 |
| 编译失败 | Xcode 版本过低 | 升级至 Xcode 15+ |
| 仅检测上半身 | 距离太远或遮挡 | 靠近设备(1.5~3 米),确保全身入镜 |
进阶方向:不止于可视化
一旦基础功能跑通,可以尝试更多扩展:
- 动作分类:采集关节点轨迹,训练轻量 LSTM 或 Transformer 模型识别挥手、下蹲等动作
- 驱动虚拟角色:将关节数据映射到 Mecanim 骨骼系统,实现实时 Avatar 动画
- 健身指导系统:对比标准动作模板,提供姿态纠正反馈
- AI 辅助教学:接入 Qwen-Turbo API,实现语音互动指导
🧠 高阶玩法:上传一段瑜伽教学视频给 Qwen3-VL,让它自动提取关键帧姿态并生成对应的关节点序列,用于实时比对用户动作。
完整源码已托管至 GitHub:
👉 https://github.com/yourname/unity-arkit-body-tracking
包含:
- 完整 C# 脚本
- Prefab 资源
- 构建配置模板
- Qwen3-VL 提示词库(Prompt Library)
AR 技术正变得越来越平民化,而 AI 正在重塑开发方式。未来属于那些敢于用手机做动捕、用 AI 写代码的创造者。