XR实现示例:iOS中的AR


文档摘要

XR 实现示例:iOS 中的 AR 前提条件 Unity 此示例要求您在 Unity 中创建一个应用程序。如果您还没有安装 Unity,请访问 unity.com/download 下载 Unity Hub。此活动可以使用 Unity 版本 2020.3.20f1 或更高版本完成。 Visual Studio 此示例要求您在 Visual Studio 中编写代码。确保已下载 Visual Studio 并将其设置为 Unity 的默认编辑器。如果您不熟悉如何将 Visual Studio 设置为默认编辑器,请查阅 设置默认脚本编辑器。此活动可以使用 Visual Studio 2019 或更高版本完成。

XR 实现示例:iOS 中的 AR

前提条件

Unity

此示例要求您在 Unity 中创建一个应用程序。如果您还没有安装 Unity,请访问 unity.com/download 下载 Unity Hub。此活动可以使用 Unity 版本 2020.3.20f1 或更高版本完成。

Visual Studio

此示例要求您在 Visual Studio 中编写代码。确保已下载 Visual Studio 并将其设置为 Unity 的默认编辑器。如果您不熟悉如何将 Visual Studio 设置为默认编辑器,请查阅 设置默认脚本编辑器。此活动可以使用 Visual Studio 2019 或更高版本完成。

Xcode

此示例会生成一个 Xcode 项目,允许将应用部署到 iOS,并需要安装 Xcode。Xcode 是苹果的开发环境,仅适用于 macOS。

项目设置

  1. 使用 AR 模板创建一个新的 Unity 项目。

    Unity Hub 模板选择屏幕截图

  2. 导航至 编辑 > 项目设置 > XR 插件管理,通过检查 iOS 标签下 ARKit 来设置项目以支持 ARKit 作为插件提供程序。

    Unity 的 XR 插件管理设置截图

  3. 提供应用的 公司名称产品名称。为此,请导航至 编辑 > 项目设置 > 玩家

  4. 玩家设置标识 下关闭 覆盖默认包标识符自动签名 复选框,因为我们在 Xcode 部署前将管理这些选项。

  5. 目标设备 更改为 仅 iPhone,并将 目标最低 iOS 版本 更改为 11.0 或更高版本。启用 需要 ARKit 支持 复选框。

  6. 通过导航到 文件 > 构建设置,选择 iOS 标签并点击 切换平台 来将部署平台更改为 iOS。

  7. 项目 窗口中,在 Assets 文件夹内创建以下 5 个文件夹:

    • Materials
    • Models
    • Prefabs
    • Scripts
    • Textures

    要创建新文件夹,请右键单击 Assets 文件夹并选择 创建 > 文件夹

    Unity 项目的文件夹创建过程截图

创建放置指示器

放置指示器帮助用户将数字对象放置在现实世界中,通过指示放置位置和方向。

  1. 层级 窗口中,右键单击并选择 创建空对象。将该对象命名为 PlacementIndicator

  2. 右键单击我们刚创建的 PlacementIndicator 对象,然后选择 3D 对象 > 四边形。将该对象命名为 Target

  3. 目前,目标看起来像一个空白的正方形。为了改变这一点,我们将导入一个 指示器 图像到我们的 纹理 文件夹中,然后使用该图像为对象创建材质。通过下载并将其拖入 纹理 文件夹来导入 目标图像(来源:Flaticon)。

  4. 检查器窗口 中,将纹理类型更改为 Sprite (2D 和 UI) 并点击 应用

  5. 现在我们可以创建一个 材质。在 项目 窗口中,右键单击 Materials 文件夹,然后选择 创建 > 材质。将其命名为 Indicator

  6. 检查器窗口 中,将 着色器 属性更改为 未照亮 > 透明。在 纹理 下点击选择并选择目标图像。

    Unity 的检查器窗口着色器和纹理截图

  7. 选择 层级 窗口中的 Target 对象,然后查看 检查器窗口。在 网格渲染器 标签下,点击 材质 并将我们刚刚创建的 Indicator 材质拖动到其中。

    Unity 检查器窗口中材质被拖动到网格渲染器的截图

  8. 最后,在 检查器窗口变换 下,将 Target 对象的 旋转 更改为 90, 0, 0

创建对象放置脚本

  1. 此脚本使用户能够扫描周围环境并在放置指示器的位置放置一个对象。要创建新脚本,请在 项目 窗口中,右键单击 Scripts 文件夹,然后选择 创建 > C# 脚本。将脚本命名为 ObjectPlacement,然后双击以编译并在 Visual Studio 中打开。

  2. 在 Visual Studio 中,添加以下脚本:

    using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.XR.ARFoundation; using UnityEngine.XR.ARSubsystems; public class ObjectPlacement : MonoBehaviour { //Declaring the Objects that will be placed (Basketball, Basketball Hoop and Indicator) public GameObject Hoop; public GameObject Ball; public GameObject placementIndicator; //Spawned Object serves as a mediator to determine whether the object has been placed or not. private GameObject spawnedObject; //Pose Object that will allow us to validate the indicator's position private Pose PlacementPose; //an AR Raycast Manager to give us access to Raycasting (used in placing objects via indicator) private ARRaycastManager arRaycastManager; //Initial pose is set to false so that we can validate it later. private bool placementPoseIsValid = false; private bool isHoopPlaced = false; void Start() { //This calls for the AR Raycast Manager to be instantiated as the application starts. arRaycastManager = FindObjectOfType<ARRaycastManager>(); } void Update() { //Check if there is any spawnedObjects, that the placement location is valid, and that the user has touched the screen to place an object. if(spawnedObject == null && placementPoseIsValid && Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began) { //Places the Hoop ARPlaceObject(); isHoopPlaced = true; //Check if the Hoop has been placed before showing the ball if(isHoopPlaced) { //Spawns the ball spawnedObject = Instantiate(Ball); //Sets the ball's position to the camera's (the user Point of View) position. spawnedObject.transform.parent = arRaycastManager.transform.Find("AR Camera").gameObject.transform; } } //Continuously updates the location of the indicator and the pose's values until the object is placed. UpdatePlacementPose(); UpdatePlacementIndicator(); } //This method allows the user to move the placement indicator based on the Pose's position void UpdatePlacementIndicator() { //Checks that no objects are spawned and that the placement pose is currently valid if(spawnedObject == null && placementPoseIsValid) { //Spawns the indicator and updates it according to the PlacementPose position and rotation. placementIndicator.SetActive(true); placementIndicator.transform.SetPositionAndRotation(PlacementPose.position, PlacementPose.rotation); } else { //Once the object is placed, the indicator is despawned. placementIndicator.SetActive(false); } } //This method updates the placement pose based on Ray casting. void UpdatePlacementPose() { //Defines the screen's center var screenCenter = Camera.current.ViewportToScreenPoint(new Vector3(0.5f, 0.5f)); //Stores the ray cast' hits as the user moves the camera around. var hits = new List<ARRaycastHit>(); arRaycastManager.Raycast(screenCenter, hits, TrackableType.Planes); //Validates based on whether there are hits or not. placementPoseIsValid = hits.Count > 0; if(placementPoseIsValid) { PlacementPose = hits[0].pose; } } //This method allows for the Hoop object to be placed. void ARPlaceObject() { spawnedObject = Instantiate(Hoop, PlacementPose.position, PlacementPose.rotation); } }
  3. 现在我们将脚本添加为 AR Session Origin 对象的组件。在 层级 窗口中,选择 AR Session Origin 对象,然后在 检查器 窗口中,点击 添加组件。搜索 ObjectPlacement 并选择它。

创建球体操作脚本

  1. 此脚本允许用户投掷球,并控制球从投掷开始的行为。要创建新脚本,请在 项目 窗口中,右键单击 Scripts 文件夹,然后选择 创建 > C# 脚本。将脚本命名为 BallManipulation,然后双击以编译并在 Visual Studio 中打开。

  2. 在 Visual Studio 中,添加以下脚本:

    /** 该代码改编自 github 用户 tudorelu 的 ar-free-throw 应用程序。要查看原始代码,请访问他的仓库 https://github.com/tudorelu/ar-free-throw **/ using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.XR.ARFoundation; //这将分配一个刚体组件(物理行为所需)给附加此脚本的对象。 [RequireComponent(typeof(Rigidbody))] public class BallManipulation : MonoBehaviour { //定义投掷时球的力量。您可以自由修改此值以观察其影响! public float throwForce = 75f; //X 和 Y 轴阻尼因子,用于投掷方向以及球相对于相机位置的偏移。如有必要,可以修改这些值,这取决于您希望投掷感觉如何。 public float throwDirectionX = 0.17f; public float throwDirectionY = 0.67f; public Vector3 ballCamOffset = new Vector3(0f, -1.4f, 3f); //声明起始点和方向向量 private Vector3 startPosition; private Vector3 direction; //声明时间及持续时间值 private float startTime; private float endTime; private float duration; //声明方向和投掷的条件 private bool directionChosen = false; private bool throwStarted = false; [SerializeField] GameObject ARCam; [SerializeField] ARSessionOrigin sessionOrigin; Rigidbody rbody; private void Start() { //在应用启动时,确保我们有对刚体组件的访问权限, //AR 会话、AR 相机,并且球处于起始位置。 rbody = gameObject.GetComponent<Rigidbody>(); sessionOrigin = GameObject.Find("AR Session Origin").GetComponent<ARSessionOrigin>(); ARCam = sessionOrigin.transform.Find("AR Camera").gameObject; transform.parent = ARCam.transform; ResetBall(); } private void Update() { //当屏幕被触摸时,收集有关投掷的信息 if (Input.GetMouseButtonDown(0)) { //此方法在移动设备上使用鼠标和触摸都有效。 startPosition = Input.mousePosition; startTime = Time.time; throwStarted = true; directionChosen = false; } //一旦触摸结束,我们停止收集有关投掷的信息并定义所选的方向 else if (Input.GetMouseButtonUp(0)) { endTime = Time.time; duration = endTime - startTime; direction = Input.mousePosition - startPosition; directionChosen = true; } //检查是否选择了方向,如果是,则释放球 if (directionChosen) { rbody.mass = 1; rbody.useGravity = true; rbody.AddForce( ARCam.transform.forward * m_ThrowForce / duration + ARCam.transform.up * direction.y * throwDirectionY + ARCam.transform.right * direction.x * throwDirectionX); startTime = 0.0f; duration = 0.0f; startPosition = new Vector3(0, 0, 0); direction = new Vector3(0, 0, 0); throwStarted = false; directionChosen = false; } //在一定时间后,这里设为 4 秒,我们将球重置到起始位置(在相机前) if (Time.time - endTime >= 3 && Time.time - endTime <= 5) ResetBall(); } //此方法允许球回到用户的“手中” public void ResetBall() { //重置质量、速度、角速度并将球的重力关闭。 rbody.mass = 0; rbody.useGravity = false; rbody.velocity = Vector3.zero; rbody.angularVelocity = Vector3.zero; endTime = 0.0f; //更改球的位置到相机的位置。 Vector3 ballPos = ARCam.transform.position + ARCam.transform.forward * ballCamOffset.z + ARCam.transform.up * ballCamOffset.y; transform.position = ballPos; } }
  3. 我们将在接下来步骤中创建的球体预制体中添加此脚本。

创建篮筐和篮球预制体

  1. 我们将使用 第 6 单元活动 中使用的篮球架和篮球模型。

  2. 从创建篮球架开始,导航到 创建一个篮球架 部分并执行到步骤 3,其中我们将模型拖入场景并禁用随模型一起提供的 相机 游戏对象。如果您已经完成了该活动,可以直接从活动的项目中拖动模型到新项目中。

  3. basketball-hoop 需要调整大小以适应应用程序的比例。在 检查器 窗口中,将 basketball-hoop 变换缩放 修改为 0.2, 0.2, 0.2

    Unity 检查器窗口变换组件截图

  4. 为了确保球能与篮筐碰撞,我们需要向篮筐模型添加一个 网格碰撞器。在 检查器窗口 中,点击 添加组件。搜索并选择 网格碰撞器,并勾选 凸面 复选框。

    Unity 检查器窗口网格碰撞器组件截图

  5. 我们将从该模型创建一个预制体,以便可以删除层次窗口中的游戏对象但仍能在脚本中使用它。要创建预制体,请将 调整大小后的模型项目窗口 拖到预制体文件夹中,并选择 创建原始预制体。从 层次窗口 中删除篮球架模型。

  6. 要创建 篮球,请返回 第 6 单元活动 并查找 创建一个篮球 部分。执行到步骤 2,或直接从活动的 Unity 项目中拖动模型。

  7. 篮球 模型拖入场景,并通过在 检查器窗口 中修改 变换缩放0.015, 0.015, 0.015 来调整其大小。

  8. 在将篮球转换为预制体之前,我们将向球模型添加两个组件。第一个将是 球体操作脚本。在 检查器窗口 中,点击 添加组件 并搜索 球体操作脚本。添加后,您会注意到也添加了一个 刚体 组件。

  9. 接下来我们将添加一个 球体碰撞器。在 检查器窗口 中,点击 添加组件 并选择 球体碰撞器。将 半径 修改为 13

  10. 为了让球体碰撞器正常工作,我们需要向组件添加一个 物理材质。右键单击 Materials 文件夹,然后选择 创建 > 物理材质。将其重命名为 弹跳球

  11. 检查器窗口 中,将材质的 动态摩擦 值更改为 0.4静态摩擦 值更改为 0.4弹性 值更改为 0.5

  12. 选择 篮球 模型,并将 弹跳球材质 拖动到 球体碰撞器 的材质字段中。

    Unity 球体碰撞器组件截图

  13. 现在我们可以创建篮球 预制体。将篮球对象拖到 预制体 文件夹中并选择 创建预制体变体。将预制体重命名为 basketball,并从 层次窗口 中删除篮球游戏对象。

完成对象放置脚本

  1. 现在预制体已经创建完毕,我们可以将它们拖到 AR Session Origin 对象的 对象放置脚本 字段中。选择 AR Session Origin 对象,在层次窗口中,将篮球架预制体拖到 篮筐 字段中,篮球预制体拖到 字段中,从 层次窗口 中的 放置指示器 游戏对象拖到 放置指示器 字段中。

    Unity 检查器窗口脚本对象字段填充截图

构建和部署

  1. 应用程序现在准备构建。导航到 文件 > 构建设置 并点击 构建。这将提示您选择一个位置来构建应用程序。导航到 桌面 并创建一个名为 AR 实现 的新文件夹。打开它并点击 选择

  2. 一旦构建完成,文件夹将包含一个可以使用 Xcode 打开并部署的 Xcode 项目 文件 (.xcodeproj)。

  3. 要部署到 iOS 设备,您需要链接一个 Apple ID 到 Xcode,并为签名创建一个个人团队。Unity 文档解释了如何设置这些内容。

  4. 一旦您的 Apple ID 和个人团队设置完毕,点击 Xcode 项目,导航到 签名与功能,点击 自动管理签名 并从 团队 下拉菜单中选择您的 个人团队

    Xcode 的签名与功能标签截图

  5. 连接一个兼容的 iOS 设备并点击 播放按钮 以部署。

    Xcode 的播放按钮截图

运行应用

  1. 您现在可以在设备上运行应用并进行测试!

    放置指示器截图

    球飞向篮筐截图

    应用运行 GIF

声明:
本文件灏天文库团队进行了翻译。尽管我们力求准确,但请注意,翻译可能包含错误或不准确之处。原文档以其原始语言为准。我们不对因使用此翻译而产生的任何误解或误译负责。


作者与出处
原作者: microsoft
来源:microsoft
许可证:MIT
整理: 灏天文库整理
由灏天文库结构化整理,提供目录导航、全文检索与在线阅读,便于系统化学习
发布者: 作者: microsoft 转发
评论区 (0)
U