尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

Unity 2020.3.33集成Manomotion SDK:Android平台AR手势识别实战教程

Unity 2020.3.33集成Manomotion SDK:Android平台AR手势识别实战教程
📅 发布时间:2026/7/12 14:15:21

1. 项目概述与核心价值

最近在捣鼓一个AR小项目,想实现不依赖任何额外硬件,只用手机摄像头就能玩转手势交互。市面上方案不少,但要么收费不菲,要么配置复杂得让人头大。直到我发现了Manomotion SDK,一个宣称免费、支持Unity、能直接在Android和iOS上跑的手势识别方案。这听起来简直是为独立开发者和中小团队量身定做的。但说实话,第一次接触时,看着官方文档和零散的社区帖子,心里还是有点打鼓,尤其是在Unity 2020.3.33这个LTS版本和Android平台上的配置,总怕哪里一步没对就掉坑里。所以,我花了几天时间,把从零开始到成功在真机上跑通手势识别的完整流程彻底走了一遍,过程中踩的坑、总结的技巧,都在这篇保姆级教程里了。无论你是想快速做个AR手势demo验证想法,还是打算在成熟项目里集成低成本的手势功能,这篇基于Unity 2020.3.33和Android平台的实战记录,应该都能让你少走不少弯路。

Manomotion SDK的核心价值在于它把复杂的手势识别算法打包成了一个即插即用的Unity插件。你不需要从头研究计算机视觉和机器学习,只需要在Unity里导入插件、配置几个场景、写点简单的逻辑,就能实时获取到手掌、手指的3D位置、姿态以及预定义的手势(比如握拳、比耶、点赞)。这对于开发教育类AR应用、虚拟试戴、手势控制的游戏或者无障碍交互应用来说,是一个快速启动的利器。而且它支持单双手跟踪,精度和响应速度在主流手机上实测下来,对于很多非极致要求的场景已经足够用了。

2. 环境准备与SDK获取

2.1 基础环境清单

在开始导入SDK之前,确保你的开发环境是干净且匹配的,这能避免至少50%的莫名错误。以下是经过验证的稳定组合:

  • Unity编辑器:Unity 2020.3.33f1c2 (LTS)。这是关键,不同的小版本号(如2020.3.30和2020.3.33)在Android构建管线或包管理上可能有细微差别,强烈建议使用这个确切版本。你可以通过Unity Hub进行安装。
  • Android开发环境:
    • JDK:安装Oracle JDK 8 或 OpenJDK 8。Unity 2020.3版本对JDK 11及以上版本的支持有时会有问题。我使用的是OpenJDK 8 (AdoptOpenJDK)。
    • Android SDK & NDK:最简单的方式是在Unity编辑器的Preferences -> External Tools中,勾选Android部分下的JDK, SDK, NDK的“Install with Unity”选项,让Unity自动安装匹配的版本。这能保证最大兼容性。手动配置路径容易出错。
    • Gradle:Unity通常会内置一个Gradle版本用于构建。保持默认即可,除非你有特殊需求。
  • 测试设备:准备一部Android手机(建议Android 9.0及以上),并开启开发者选项和USB调试。这是后续真机测试的必需品。

注意:千万不要在环境没配好时就急着导入SDK。我曾经试过先导SDK再配Android环境,结果Unity项目设置里一堆红色错误,清理起来非常麻烦。正确的顺序是:装好Unity -> 配置好External Tools里的Android路径 -> 再处理SDK。

2.2 获取Manomotion SDK

Manomotion SDK目前主要通过其官方网站提供下载。你需要注册一个免费账户,登录后才能在开发者后台下载SDK包。通常下载下来的是一个.unitypackage文件,这是Unity的标准插件格式。这里有个小技巧:留意你下载的SDK版本号,最好去官方文档或下载页面看一眼它声明的兼容Unity版本。虽然Manomotion对2020.3.x系列支持较好,但确认一下能更安心。

2.3 创建与设置Unity项目

打开Unity Hub,创建一个新的3D项目。项目名称和位置按你喜欢来定。创建完成后,第一件事不是导入SDK,而是先设置项目的基本构架:

  1. 目标平台切换:在File -> Build Settings中,选择Android平台,然后点击Switch Platform。这个过程可能会花点时间,Unity需要重新导入一些资源以适应Android。
  2. Player Settings关键配置:切换到Android平台后,点击Player Settings,以下几个设置必须检查:
    • Other Settings 部分:
      • Minimum API Level:设置为Android 7.0 ‘Nougat’ (API level 24)或更高。Manomotion需要一些较新的系统API。
      • Target API Level:设置为与你测试手机系统相匹配的API级别,或直接选择Automatic。
      • Scripting Backend:选择IL2CPP。这是发布到移动平台(尤其是64位)的推荐且更稳定的后端。
      • Target Architectures:勾选ARM64。现在的手机基本都是64位系统,勾选这个能确保性能和应用商店的兼容性。
    • XR Settings 部分(如果存在):由于我们做的是基于摄像头的AR,并非必须依赖Unity的AR Foundation等XR插件,所以这部分通常保持默认即可。但如果你后续要结合ARCore使用,则需要在这里启用。

3. SDK导入与基础配置

3.1 导入Unity Package

环境准备就绪后,就可以导入SDK了。在Unity编辑器中,选择Assets -> Import Package -> Custom Package...,然后找到你下载的.unitypackage文件。导入时,会弹出一个窗口,显示包内所有文件。通常,全部勾选并导入即可。导入过程可能会提示一些关于API兼容性或命名空间的警告,只要不是错误(Error),可以先忽略。

导入完成后,你的Project窗口的Assets文件夹下,应该会出现一个名为ManoMotion或类似的文件夹。这就是SDK的核心所在。里面通常包含Scripts(核心脚本)、Prefabs(预制体)、Materials(材质)、Shaders(着色器)以及Documentation(文档)等子文件夹。

3.2 配置第一个手势识别场景

Manomotion SDK的设计思路是提供即用的预制件(Prefab)和管理器(Manager)。配置场景最快的方法如下:

  1. 清空示例场景:创建一个新的场景或使用默认场景,删除场景中自带的Main Camera和Directional Light(我们稍后会用SDK的预制体替代)。
  2. 拖入核心预制体:在ManoMotion/Prefabs文件夹下,找到名为ManoMotion或ManoManager的预制体,将其拖入场景(Hierarchy)中。这个预制体是手势识别系统的中枢。
  3. 检查自动生成的摄像机:拖入预制体后,你可能会发现场景里自动出现了一个新的摄像机(比如叫ManoCamera),或者原预制体下包含一个摄像机子物体。这个摄像机会被脚本用来渲染手机摄像头画面。
  4. 配置ManoManager脚本:选中场景中的ManoMotion预制体,在Inspector面板中,你会看到挂载的ManoManager脚本。这里有一些关键参数:
    • Camera:通常会自动关联上场景中那个专用的摄像机。如果没有,手动拖拽赋值。
    • Target Framerate:建议设置为60,以获得更流畅的手部跟踪体验。
    • 其他高级设置(如手势平滑度、检测置信度阈值):首次运行时可以先保持默认,后续根据效果微调。

3.3 添加可视化反馈(可选但推荐)

为了直观地看到手势识别结果,SDK通常提供一些可视化预制体:

  1. 手部网格/骨架:在ManoMotion/Prefabs/Visualization路径下,寻找类似Hand Mesh、Hand Skeleton或Wrist Information的预制体。将其拖入场景。
  2. 关联到管理器:通常你需要将这个可视化预制体拖拽到ManoManager脚本的某个公开字段上,例如Hand Visualization Prefab。这样,当SDK检测到手部时,就会在对应的3D位置实例化这个可视化模型。
  3. 手势状态UI:SDK可能还包含一个用于在屏幕上显示当前识别到的手势(如“FIST”、“PINCH”)的UI预制体。同样找到并拖入场景的Canvas下,并按照脚本要求进行关联。

完成以上步骤后,点击Unity的播放按钮,在Game视图里,你应该就能看到模拟的手机摄像头视图(可能是测试图像或颜色背景)。但目前还看不到手势识别效果,因为我们需要构建到真机。

4. Android平台构建与部署

4.1 项目构建设置复查

在打包前,再次确认Build Settings和Player Settings:

  1. Build Settings:确保当前场景已被添加到Scenes In Build列表中(拖入或点击Add Open Scenes)。
  2. Player Settings -> Other Settings:
    • Package Name:修改为一个唯一的反向域名格式,如com.yourcompany.handdemo。
    • Version:设置应用版本。
    • Write Permission:确保External (SDCard)写入权限被勾选。虽然手势识别本身不一定需要,但SDK或你的应用可能需要临时存储数据。
    • Internet Access:如果需要,可以勾选Required。

4.2 解决可能的编译错误与警告

首次为Android构建时,可能会遇到一些错误或警告,常见的有:

  • .NET版本/API兼容性警告:如果SDK使用了较新的C#特性,而项目设置是较旧的.NET Standard 2.0,可能会报警告。在Player Settings -> Other Settings -> Configuration中,将Api Compatibility Level暂时改为.NET 4.x通常可以解决。但要注意,这可能会增加包体大小。
  • AndroidManifest冲突:如果导入的SDK自带AndroidManifest.xml文件,可能会与Unity自动生成的冲突。Manomotion SDK通常以插件形式提供,其Manifest配置会通过Plugins/Android文件夹自动合并。如果构建失败提示Manifest错误,可以尝试删除项目中的Assets/Plugins/Android/AndroidManifest.xml(如果有),让Unity重新生成,但更安全的方法是检查SDK文档,看是否需要手动合并某些权限(如摄像头权限)。
  • 缺失的Gradle依赖:某些SDK版本可能需要额外的Gradle仓库或依赖。这通常会在Assets/Plugins/Android下的mainTemplate.gradle或baseProjectTemplate.gradle文件中配置。Manomotion一般不需要,但如果构建失败提示找不到类,可以检查这些文件。

4.3 构建APK与真机安装

  1. 用USB数据线连接你的Android手机,并确保手机已开启“USB调试”(在开发者选项中)。
  2. 在Unity的Build Settings窗口中,点击Build And Run。选择一个位置保存APK文件。
  3. Unity会开始编译、打包,并自动将APK安装到已连接的手机上。第一次构建可能会花费几分钟时间。
  4. 安装完成后,手机会自动启动应用。请立即在手机上授予应用“相机”权限,这是手势识别能工作的前提。

5. 核心功能实现与脚本交互

5.1 理解SDK的数据流

当应用在手机上运行,你把手放在摄像头前时,Manomotion SDK内部的工作流程大致如下:

  1. 图像采集:ManoManager控制摄像头,获取实时视频帧。
  2. 手部检测与跟踪:SDK的核心算法在后台运行,从视频帧中检测手部区域,并持续跟踪其运动。
  3. 数据解析:算法会计算出丰富的骨骼信息,包括手掌中心(Wrist)、21个手部关键点(类似MediaPipe的手部模型)的3D位置、手的整体边界框、手势分类结果等。
  4. 事件派发:这些数据被封装成结构体(如HandInfo),并通过C#事件或回调函数的方式,提供给开发者使用。

你的代码主要就是订阅这些事件,然后根据获取到的HandInfo数据来驱动游戏逻辑。

5.2 编写第一个手势交互脚本

让我们创建一个简单的脚本,当用户做出“握拳”手势时,让场景中的一个物体变色。

  1. 创建脚本:在Project窗口中右键,选择Create -> C# Script,命名为GestureController。
  2. 编写核心逻辑:双击打开脚本,进行编辑。
using UnityEngine; using Manomotion; // 引入Manomotion的命名空间 public class GestureController : MonoBehaviour { // 一个可拖拽赋值的目标物体,比如一个Cube public GameObject targetObject; // 用于存储物体原始颜色的材质 private Material originalMaterial; // 定义握拳手势对应的枚举值(需参考Manomotion文档) private const ManoGestureContinuous FIST_GESTURE = ManoGestureContinuous.CLOSED_HAND_GESTURE; void Start() { if (targetObject != null) { // 获取物体材质并保存原始颜色 originalMaterial = targetObject.GetComponent<Renderer>().material; } // 订阅Manomotion的手势信息更新事件 // 这是关键步骤!当SDK处理完一帧数据后,会触发此事件 ManomotionManager.OnManoMotionFrameProcessed += HandleManoMotionFrameProcessed; } void OnDestroy() { // 非常重要!在脚本销毁时取消订阅,防止内存泄漏 ManomotionManager.OnManoMotionFrameProcessed -= HandleManoMotionFrameProcessed; } // 事件处理方法 private void HandleManoMotionFrameProcessed() { // 从ManomotionManager的单例中,获取当前帧的手部信息 HandInfo handInfo = ManomotionManager.Instance.Hand_infos[0]; // 通常索引0代表第一只手 // 检查是否检测到了手 if (handInfo.gestureInfo.manoClass != ManoClass.NO_HAND) { // 检查持续手势(如握拳、张开手)是否为握拳 if (handInfo.gestureInfo.manoGestureContinuous == FIST_GESTURE) { ChangeObjectColor(Color.red); } else { // 如果不是握拳,恢复原色 ResetObjectColor(); } // 你也可以获取离散手势(如捏合、滑动) // ManoGestureTrigger triggerGesture = handInfo.gestureInfo.manoGestureTrigger; // 或者获取手部3D位置(手掌中心) // Vector3 wristPosition = handInfo.trackingInfo.skeleton.joints[0]; // 0号关节通常是手腕 } else { // 没有检测到手时,也恢复原色 ResetObjectColor(); } } void ChangeObjectColor(Color newColor) { if (targetObject != null) { targetObject.GetComponent<Renderer>().material.color = newColor; } } void ResetObjectColor() { if (targetObject != null && originalMaterial != null) { targetObject.GetComponent<Renderer>().material.color = originalMaterial.color; } } }
  1. 应用脚本:将GestureController脚本拖拽到场景中的任意GameObject上(比如一个空的GameObject,命名为GameManager)。
  2. 关联物体:在Inspector面板中,将场景中你想要变色的那个物体(比如一个Cube)拖拽到脚本的Target Object字段上。
  3. 构建并测试:再次构建APK到手机。运行后,当你对着摄像头握拳时,指定的物体应该会变成红色,松开手则恢复原色。

5.3 实现更复杂的交互:手势控制物体移动

理解了基础的数据获取,我们可以更进一步,用手势控制物体的3D位置。例如,用手掌的屏幕坐标来控制一个UI元素的移动。

using UnityEngine; using UnityEngine.UI; // 如果需要控制UI using Manomotion; public class HandUIFollower : MonoBehaviour { public RectTransform uiElementToMove; // 要移动的UI元素 public Camera mainCamera; // 用于坐标转换的摄像机(应该是ManoCamera) void Start() { ManomotionManager.OnManoMotionFrameProcessed += UpdateUIFromHand; if (mainCamera == null) { // 尝试自动查找ManoCamera mainCamera = Camera.main; } } void OnDestroy() { ManomotionManager.OnManoMotionFrameProcessed -= UpdateUIFromHand; } private void UpdateUIFromHand() { HandInfo handInfo = ManomotionManager.Instance.Hand_infos[0]; if (handInfo.gestureInfo.manoClass != ManoClass.NO_HAND && uiElementToMove != null) { // 获取手掌中心的屏幕坐标(归一化,0到1) Vector3 normalizedWristPosition = handInfo.trackingInfo.palmCenter; // 将归一化坐标转换为屏幕像素坐标 float screenX = normalizedWristPosition.x * Screen.width; float screenY = normalizedWristPosition.y * Screen.height; // 将屏幕坐标转换为UI的局部坐标(假设Canvas是Screen Space - Overlay) Vector2 localPos; RectTransformUtility.ScreenPointToLocalPointInRectangle( uiElementToMove.parent as RectTransform, // UI元素的父级RectTransform new Vector2(screenX, screenY), null, // 对于Overlay Canvas,相机参数为null out localPos ); uiElementToMove.localPosition = localPos; } } }

这个脚本展示了如何将SDK输出的归一化手部位置,转换到UI坐标系中,实现一个简单的“手指点哪,UI跟到哪”的效果。

6. 性能优化与调试技巧

6.1 性能调优参数

在真机上运行时,你可能会关心帧率和耗电。ManoManager脚本上的一些参数可以帮助你平衡效果和性能:

  • Target Framerate:前面提到设为60。如果觉得发热或耗电快,可以尝试降到30。
  • Processing Resolution:这是最重要的性能参数之一。它决定了送给手势识别算法的图像分辨率。HIGH精度最好但最耗性能,LOW最省电但可能丢失细节。对于大多数手机,MEDIUM是一个不错的起点。你可以在脚本运行时动态调整它,观察效果和帧率的变化。
  • Smoothing Filter:对手部位置和手势进行平滑滤波。值越大越平滑,但延迟感也会增加。对于需要快速响应的游戏,可以调低;对于需要稳定性的UI控制,可以调高。
  • 多手跟踪:默认可能只跟踪一只手。如果你需要同时跟踪两只手,确保在设置中启用了相关选项,但这会显著增加计算量。

6.2 真机调试与日志查看

在真机上调试AR应用,查看日志是定位问题的关键。

  1. 使用Android Logcat:Unity与Android设备连接时,可以通过Window -> Analysis -> Android Logcat打开Logcat窗口。确保设备已连接,并在Logcat窗口中选择你的设备。运行应用,所有Unity的Debug.Log以及系统日志都会在这里打印。这是查找崩溃原因、查看SDK内部警告的必备工具。
  2. 在脚本中添加调试信息:在你的手势脚本中,可以添加Debug.Log来输出关键数据,比如检测到的手势类型、手部坐标等。这能帮你确认数据流是否正常。
    Debug.Log($"Detected Gesture: {handInfo.gestureInfo.manoGestureContinuous}, Hand Position: {normalizedWristPosition}");
  3. 处理权限拒绝:如果你的应用启动后一片黑屏,首先检查手机是否弹出了相机权限请求并被你不小心拒绝了。可以在脚本的Start方法中,检查应用是否有相机权限,如果没有,可以提示用户或引导用户去设置中开启。Unity的Application.HasUserAuthorization可以用来检查,但在Android上更可靠的方式是尝试访问摄像头,如果失败则给出提示。

6.3 常见问题与解决方案速查表

以下是我在配置和开发过程中遇到的一些典型问题及解决方法:

问题现象可能原因解决方案
构建失败,提示Gradle错误JDK、SDK、NDK路径错误或版本不兼容;Gradle版本冲突。1. 检查UnityPreferences -> External Tools中Android路径是否正确且已安装。
2. 尝试在Player Settings -> Publishing Settings中勾选Custom Base Gradle Template,并编辑生成的baseProjectTemplate.gradle文件,调整Gradle版本或仓库源(此操作需谨慎,建议先备份)。
3. 最彻底的方法:关闭Unity,删除项目根目录下的Library、Temp、Obj文件夹,以及[项目名].csproj文件,然后重新打开Unity,让它重新生成。
应用安装后打开立即闪退缺少必要的Android权限;SDK与目标设备ABI不兼容;脚本存在运行时错误。1. 确认AndroidManifest.xml中已声明相机权限 (<uses-permission android:name="android.permission.CAMERA" />)。
2. 检查Player Settings -> Other Settings -> Target Architectures,确保至少勾选了ARMv7和ARM64。
3. 通过Android Logcat查看崩溃瞬间的日志,寻找NullReferenceException或MissingMethodException等错误信息。
摄像头画面黑屏,但应用未崩溃相机权限未授予;ManoManager的Camera字段未正确赋值;手机摄像头被其他应用占用。1. 确保手机已为应用开启相机权限。
2. 检查Hierarchy中ManoMotion预制体上ManoManager脚本的Camera字段是否绑定了场景中的摄像机。
3. 杀掉后台可能占用摄像头的应用(如其他相机App、微信视频等)。
手势检测不稳定或延迟高光线环境太暗;手距离摄像头太近或太远;手机性能不足;Processing Resolution设置过高。1. 确保在光线充足的环境下使用。
2. 让手与摄像头保持约30-80厘米的距离,并尽量在画面中央。
3. 在ManoManager上将Processing Resolution从HIGH调至MEDIUM或LOW。
4. 关闭手机上的省电模式。
可视化手部模型位置漂移或抖动缺乏平滑滤波;摄像头画面存在运动模糊。1. 适当增加ManoManager上的Smoothing Filter值。
2. 尝试在更稳定的环境下操作,避免手部或手机快速移动。
脚本中获取不到HandInfo数据事件订阅代码写在了Update中导致重复订阅/取消订阅;ManoMotionManager.Instance为空。1. 确保事件订阅 (OnManoMotionFrameProcessed +=) 只在Start或Awake中执行一次。
2. 检查Manomotion SDK的核心管理器是否已正确初始化。通常拖入预制体后会自动完成。可以在Start中加Debug.Log(ManomotionManager.Instance)来检查。

7. 项目打包与发布注意事项

当你完成了开发和测试,准备发布应用时,还有最后几关要过:

  1. 图标与闪屏:在Player Settings -> Icon和Splash Image中设置好你的应用图标和启动画面。
  2. 版本号与包名:再次确认Player Settings中的Version和Package Name是最终发布版本。
  3. 减少APK大小:
    • 在Build Settings中点击Export Project而不是直接构建APK,然后用Android Studio打开进行更精细的优化和打包(如启用ProGuard代码混淆和压缩)。
    • 在Unity的Project Settings -> Editor中,可以为Asset Serialization选择Force Text,这有时能略微减小包体,但主要影响的是项目文件本身。
    • 检查Player Settings -> Publishing Settings,如果不需要,可以取消勾选Split APKs by target architecture,但注意兼容性。
  4. Keystore签名:发布到应用商店(如Google Play)需要你自己的密钥库(Keystore)文件对APK进行签名。务必妥善保管这个文件和密码,丢失后将无法更新同一个应用。
  5. 隐私政策:因为你的应用使用了摄像头权限,在大多数应用商店上架时,都需要提供隐私政策链接,说明你如何收集和使用摄像头数据。Manomotion SDK本身可能也要求你在应用中声明其使用。

走完这套流程,从环境搭建、SDK配置、功能开发、调试优化到最终打包,一个基于Manomotion SDK的AR手势交互应用就真正从想法变成了手机上的可运行产品。整个过程最磨人的往往不是代码本身,而是环境配置和真机调试时那些意想不到的兼容性问题。希望这篇超详细的记录,能帮你把路上的坑填平一大半。

相关新闻

  • 终极指南:三步快速获取国家中小学智慧教育平台电子课本PDF文件
  • 为什么说Apollo Save Tool是PS4存档管理的终极神器?
  • AI自媒体实操:如何串联文本、画图、视频大模型?多模型协同创作全流程指南

最新新闻

  • 如何用KLayout实现芯片版图设计:从新手到专家的完整指南
  • 仅限首批500名开发者获取:LLM-Ops团队封存2年的级联调用性能基线报告(含Qwen/GLM/Claude三系Agent压测数据)
  • 基于Bluetooth 5.4与STM32的无线音频系统设计
  • 3款数字人建模方案对比:Blender多边形 vs DAZ辅助 vs AI生成,效率与质量实测
  • VMware 17 Pro虚拟机安装Ubuntu下载安装教程全流程(附安装包)
  • 0 基础入门React Native鸿蒙跨平台开发:身份证验证功能实战

日新闻

  • IX9104 PCIe5.0 高速交换芯片@ACP#完整规格 + 应用场景总结
  • Unity游戏集成Coze智能体:实现NPC智能对话与知识库联动
  • SAP EPIC 建行回单查询:从标准类CL_EPIC_EXAMPLE_CN_CCB_GHTD到Z类的5处关键修改

周新闻

  • IX9104 PCIe5.0 高速交换芯片@ACP#完整规格 + 应用场景总结
  • Unity游戏集成Coze智能体:实现NPC智能对话与知识库联动
  • SAP EPIC 建行回单查询:从标准类CL_EPIC_EXAMPLE_CN_CCB_GHTD到Z类的5处关键修改

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号