大多数浏览器和
Developer App 均支持流媒体播放。
-
使用 RealityKit 构建空间体验
了解 RealityKit 如何将你的 App 带到新的维度。欢迎使用 RealityKit 实体、组件和系统,并了解如何向 visionOS 中的 App 添加 3D 模型和效果。我们还将为你介绍 RealityView API,并演示如何将 3D 对象添加到窗口、容积和空间中,从而使 App 更具沉浸感。此外,我们还将探索如何将 RealityKit 与空间输入、动画和空间音频进行结合。
章节
- 0:00 - Introduction
- 2:50 - RealityKit and SwiftUI
- 9:36 - Entities and components
- 12:20 - RealityView
- 15:37 - Input, animation and audio
- 23:00 - Custom systems
- 26:15 - Wrap-up
资源
相关视频
WWDC23
-
下载
♪ 悦耳的器乐嘻哈 ♪ ♪ 大家好 我是 John 是 RealityKit 团队的一名工程师 今天 我很高兴向你介绍 用于打造空间体验的 RealityKit RealityKit 是一个框架 可用于提供逼真渲染、 动画以及 3D 模型和效果的模拟 我们在 2019 年 推出了 RealityKit 并在此之后不断增加了许多新功能 如果你曾经在其他设备上 使用过 RealityKit 来构建 App 你就会发现其中有许多共通之处 借助 RealityKit 你可以使用 3D 内容 来增强 App 的 2D 窗口 在独立窗口的前部中央 呈现 3D 内容 或将自身与周围环境 置于沉浸式体验之中 RealityKit 是 Apple 平台的 3D 核心框架 尤其是在 xrOS 中 该框架提供了非常多的功能 在本次讲座中 我将重点向你介绍 实体、组件 以及 RealityView 等关键功能 其中 还会向你介绍 RealityKit 并向你演示如何使用该框架 同时 我还会提到一些包含其他概念 以及更多细节内容的讲座 我们开始吧 接下来 我会使用 Hello World 体验 来解释本次讲座中的概念 在开始介绍这些概念之前 我先来介绍一下本次体验 所包含的 3 个模块 第一个模块 Planet Earth (行星地球) 该模块会在自己的窗口中 呈现 3D 地球 可供你从任何角度与之进行交互 第二个模块 Objects in Orbit (轨道物体) 该模块会让你 沉浸在由地球、月亮及卫星 构成的模型中 同时向你展示动画、 空间音频以及自定义操作 例如卫星跟踪轨道 第三个模块 Solar System (太阳系) 该模块包含了完全沉浸式体验 此外 你可以在其他讲座中 了解更多有关该内容的信息 接下来 我会向你演示如何使用 SwiftUI、RealityKit 以及 Reality Composer Pro 来编译 Hello World 体验中的 3D 元素 我们这就开始吧 我会先向你介绍如何结合使用 RealityKit 和 SwiftUI 将 App 带入新的维度 接着 我会探讨 RealityKit 的构建块、 地球模型等实体 以及可实现自己行为的组件 在这部分中 你会了解到 RealityView 的功能 即用于 3D 模型和效果的 新 SwiftUI 视图 然后 我会解释如何处理输入 以及如何使用动画和空间音频 来让 App 生动逼真 最后 我会谈谈如何使用 自定义组件和系统 来释放 RealityKit 的无限潜力 我们先来探索如何结合使用 RealityKit 和 SwiftUI 吧 SwiftUI 用于定义视图和窗口 Reality 用于添加 3D 元素 例如 此 World App 使用 SwiftUI 来显示 带有按钮的标准 2D 窗口 轻点左下方的 Planet Earth 按钮 便可导航至细节视图 其中呈现了一幅 2D 地球示意图 但如果我想将该 2D 图像 替换为 3D 地球 该怎么办呢? 使用 Reality 中的 Model 3D 视图 便可轻松在 2D 窗口中 添加 3D 内容 我们来看一下代码 这里展示的是 SwiftUI 视图 用于显示地球图像 为了将其转换为 3D 地球 接下来 我将导入 RealityKit 并将图像更改为 Model 3D 视图 其中 我会引用 Globe 项目中的 USD 文件 在显示模型前 我们可添加两段代码 来自定义加载的模型: 一段用于返回模型的内容闭包 还有一段则用于指定 模型加载时所显示视图的 占位符视图构建器 在内容闭包中 我会添加 resizable 和 scaledToFit 修饰符 来确保模型能够适应 UI 中的可用空间 因为 Model 3D 异步加载模型 所以 我在这里使用了 一个占位符视图构建器 用于自定义 加载过程中显示的视图 在本例中 我使用内置的 ProgressView 来显示旋转球体 最后 我会将 3D 模型作为资源 添加到 App 或 Swift 软件包中
现在 模型在 App 中的外观 就和它在快速查看 以及 Reality Composer Pro 中 看上去一样了 将 3D 内容 放进 2D 窗口确实很棒 但我希望 3D 模型可以 位于窗口的前部中央位置 为实现这一点 我需要将地球放在一个单独的窗口中 我会在 App 详细视图中 添加一个按钮 用于打开该新窗口 在这里 我不使用负责在 2D 背景中 显示内容的常规窗口 而是使用一种将内容 放置于容器之中的新窗口样式 该样式称为体三维窗口 非常适合用于观看 3D 内容 与 2D 窗口不同 体三维窗口可用于任意视角 因此非常适用于 3D 模型 同时 体三维窗口还可以 按真实大小保持固定 在体三维窗口中 可以将模型 缩放到 1 米 然后 该模型就会 始终以该大小进行显示 这一点非常适合 用于 Hello World 中的地球 接下来 我们来看看 添加体三维窗口的过程 首先 我会在 App 中 添加 WindowGroup WindowGroup 的作用 就是充当模板 让 App 可以用来打开新窗口 我会为这个新窗口提供识别符 以便与 App 中的主窗口 区分开来 接着 我会在 WindowGroup 中 添加 windowStyle volumetric 修饰符 同时 我还添加了一个 defaultSize 修饰符 来以米为单位设定该窗口的大小 最后 在细节视图中添加一个按钮 为了使我刚添加的按钮可以打开窗口 我会添加一个属性 允许从 SwiftUI 环境中 访问打开窗口的操作
然后 在按钮中对该操作进行调用
现在 我们在模拟器中 运行这个 App 当我按下 View Globe 按钮 就会出现一个体三维窗口 现在 我就可以 从多个角度与该地球交互 而不仅限于前面这一角度
但有时 对于你想创造的体验而言 能够真正释放其潜力的关键 在于沉浸感 在 World App 的 Objects in Orbit 模块中 你可以沉浸在地球的动态模型中 其中 卫星还会进行轨道展示 这里使用的就是沉浸式空间 是可让 App 将 3D 元素 放置于该空间任意位置的 新的场景类型 当你打开一个沉浸式空间 你的 App 就会延伸到窗口之外 为你提供神奇的体验 添加 ImmersiveSpace 的方式 和添加 WindowGroup 的类似 这就是我的 App 主体内的新场景 在这里 我将使用 RealityView 来获取比 Model 3D 还要多的 对场景的控制权 稍后 我会更加详细地 介绍一下 RealityView 和之前一样 我现在要在 App 细节视图中添加一个按钮 我会从 Environment 中打开 openImmersiveSpace 操作 然后 使用此前定义的场景标识符 来对其进行调用
需要注意的是 openImmersiveSpace 操作是异步的 只有空间完成打开之后 该操作才会完成 按下查看轨道按钮后 沉浸式空间随即出现 这看上去已经很棒了 但也可以使用 RealityKit 添加交互性、动画以及音频 来使其更具吸引力 无论你是使用 包含 3D 内容的2D 窗口 还是使用突出显示 3D 模型的体三维窗口 如果你还没有 看过这些 SwiftUI 讲座 我都建议你去观看 讲座 “认识适用于空间计算的 SwiftUI” 概括了该平台上 SwiftUI 的新功能 讲座“让 SwiftUI 进入新维度” 演示了如何充分利用 窗口中的 3D 内容 沉浸感包含多种风格 Hello World 的 Solar System 模块 使用了完全沉浸式空间 该空间可隐藏穿透效果 并显示自己的背景 讲座“通过 SwiftUI 突破窗口的界限” 详细介绍了沉浸式空间的所有风格 如果你想要创造 沉浸式体验 我强烈建议你观看该讲座 至此 你已经了解了两种 在 SwiftUI 视图中 使用 RealityKit 的方法: 简便易用的 Model 3D 以及 RealityView 在接下来的讲座中 我将使用 RealityView 因为该方法可让你使用 RealityKit 实体 来合成 3D 内容 那么 什么是 RealityKit 实体呢? 实体就是容器对象 如果你在代码中创建一个空的实体 该实体便无法发挥任何作用 如果需要对其进行渲染 赋予操作 那该实体就必须具有组件 每个组件都会为实体提供特定的操作 我来举一些例子 本 App 中的地球实体 由两个组件实现: 一个是为实体提供网格 和材质的模型组件 还有一个是将实体 放入 3D 空间的变换组件 卫星实体也是如此构成 模型组件为实体渲染网格 并应用材质 本例中的地球和卫星模型 都是由数字内容创作工具所创建 然后 导出到 USDZ 文件 并加载到 RealityKit 中 这些网格会在模型上 使用基于物理的材质 并赋予其最终外观 材质会使用一组纹理和着色器 来描述网格表面对光的反应方式 想要进一步了解材质的信息 建议你观看 Niels 的讲座 “探索 Reality Composer Pro 中的材质” 除了模型组件之外 这些实体还包含变换组件 变换组件会将实体放置于 3D 空间中 可以通过设定变换组件的属性 以及实体的父级 来控制实体的位置、 方向和大小 与 ARKIt 等 3D 引擎一样 RealityKit 也使用 3D 坐标系约定 原点位于 RealityView 中心 Y 轴指向上方 Z 轴指向你 X 轴指向你的右侧 单位为米 需要注意的是 这些约定 与 SwiftUI 的约定不同 RealityView 内容实例 所具备的函数 可以帮助你在 RealityKit 和 SwiftUI 的坐标空间之间 进行轻松转换 每个实体都有一个变换组件 但并不是每个实体都有一个模型 有时 实体是由多个子实体合成 且每个子实体都有自己的组件集合 这样 你便拥有了 更多的编程控制权 例如 你可以在子实体的 变换组件上播放单个动画 RealityKit 所包含的组件 取决于你想实现的目的 接下来 我会介绍一些特定的组件 例如:碰撞、输入目标 以及悬停效果 此外 我还会演示如何创建组件 现在 我们已经了解了实体和组件的 工作原理 接下来 我们就来 使用 RealityView 将这些实体放入 App 中 RealityView 是一个包含了 大量实体的 SwiftUI 视图 实体需要添加到 RealityView 中 才能进行渲染、动画以及模拟 那么 RealityView 的 工作原理是什么呢? RealityView 会提供内容实例 来让你将实体添加到视图中 如果你曾经加载过实体 或想要以编程的方式创建实体 那接下来的内容你会很容易上手 但是 由于这个闭包是异步的 所以 你可以很简便地 从文件中加载实体 并将其显示在视图中 在这里 我会从 USD 文件中 异步加载地球模型 并在加载完成后 将其添加到内容实例 也可以加载不止一个实例 并将其都放入 RealityView 中 这些模型会在空间中重合 而非彼此相邻地进行排列 如果你对这种布局方式不满意 可以改变添加到视图中的实体位置 在本例中 我将月球实体 放在右侧 1.5 米处 在设置完 RealityView 之后 你可能会希望将 App 中的状态 与保存在 RealityKit 组件中的 属性进行关联 RealityView 可让你 使用更新闭包 在 SwiftUI 托管状态 与 RealityView 中的 实体建立连接 这样 你可以通过 App 数据模型中的 数据源轻松驱动 3D 模型的操作 本视图加载了一个模型 并应用了一个 由视图使用者控制的 rotation 请注意 update 部分的代码 只会在其依赖值发生改变时运行 如果你正在构建同时包含 2D 和 3D 元素的 UI 那你偶尔会需要 在视图和实体之间进行作坐标转换 RealityView 提供了用于 在 SwiftUI 视图坐标空间 和 RealityKit 实体视图 坐标空间之间 进行转换的函数 RealityView 的内容实例 提供了转换函数 用于将坐标点、 边界框以及变换组件 从 SwiftUI 坐标空间 转换到实例本地空间 也提供了反方向进行转换的函数 在这里 我会获取 任意视图维度中的最小长度 并将加载后的实体进行缩放 以适应可用空间 RealityView 还提供了一个机制 用于订阅实体和组件 发布的事件 在本例中 我会在加载完成后 播放加载的 USD 文件中 得到定义的动画 接着 在内容实例中使用 subscribe to: function 来添加事件处理程序 并且 本示例在动画完成后 还会运行一些代码 RealityKit 会针对各种事项 发布事件 从动画到物理 再到音频, 涵盖多个方面 此外 你还可以 将 SwiftUI 视图赋予实体 RealityView 的附件功能可以 让你可以在 3D 空间中 轻松实现定位 想了解更多信息 请观看 Eugene 的讲座 “使用 RealityKit 增强你的空间计算 App” 使用 RealityView 你可以实现多种功能 但现在 让我们再回到刚才的天体 在现实中对其进行实现 首先 我会向你展示 如何添加拖移手势 来重新定位地球实体 接着 我会介绍动画和空间音频 这个示例包含了 3 个实体的 RealityView 对于 RealityView 你可以像在其他 SwiftUI 视图中那样 在其中添加手势 并且该手势会对视图中的 实体进行命中测试 为了接收输入 实体必须同时具有 输入目标组件以及碰撞组件 在 RealityView 处理触控事件时 它会忽略没有同时具有碰撞组件 和输入目标的实体 因为只有最后这个实体 同时具有两个组件 因此 添加到 RealityView 中的 手势只会对该实体接收的 输入作出反应 为了可以拖移地球实体 我会为其提供目标组件 以及碰撞组件 并在 RealityView 中 添加拖移手势 而为了添加组件 我会用到 Reality Composer Pro Reality Composer Pro 是一个新的开发者工具 可用于合成、编辑 以及预览 3D 内容 在这里 我只用它来 向实体添加组件 想要进一步了解有关 Reality Composer Pro 功能的信息 请观看 Eric 的讲座 “认识 Reality Composer Pro” World App 已经设置了一个 World Assedts 软件包 并包含了本体验 所使用的 USD 文件 接着 我会在 Reality Composer Pro 中打开该软件包
地球模型位于 USDZ 文档中 该文档为自包含文档 且不可修改 所以 我不会修改该文档 而是创建一个新的 USD 场景文件 并将地球模型作为引用 USD 文件可以引用其他 USD 文件 并对其进行修改 但却不会真的改变被引用文件 像这种非破坏性的编辑真的很方便 尤其是你需要对其他人正在使用的文本 进行微小更改的情况下 接下来 我会创建一个名为 DraggableGlobe 的新场景 并将 Globe 文件拖移进来 以创建引用
现在 我就可以向其中添加组件了 我会添加一个输入目标组件 以及一个碰撞组件 碰撞组件的默认形状为 立方体 所以 我会将其更改为球体 以便更好地匹配该模型 碰撞模型与视觉模型 保持合理的近似十分重要 匹配越近似 你与模型的交互就会更直观 我希望地球模型可以转动 所以 我会在 RealityView 中 添加 DragGesture 这样 标准的 SwiftUI 拖移手势便设置好了 但除此之外 还可以对 gesture 添加 targetedToEntity 来让手势不仅可以操作整个视图 还可以对特定实体进行操作 当 gesture 的值发生改变 我就会更改实体的位置 以便与之进行匹配 但这里有个关键细节需要注意一下 由于 gesture 的值 对应于 SwiftUI 坐标空间 因此 我必须将其转换至 RealityKit 坐标空间 来实现实体位置的更改 至此 一切准备完毕 在当前 Objects in Orbit 模型中 我可以通过双指捏合并拖动 来四处移动地球 太棒了 现在我们的 App 就可以实现交互了 但我还希望这个地球实体 可以表明自己可以进行交互 为了实现这一点 我可以使用 RealityKit 组件 HoverEffectComponent 由 SwiftUI 和 RealityKit 提供的悬浮效果 是实现 App 对你观察位置 做出反应的唯一方式 并且 该效果能以保护隐私的方式 应用于 App 的进程之外 在将地球实体添加到 RealityView 之后 我会向其添加悬浮效果组件 现在 当我将光标置于地球模型之上 表明当前可以进行交互时 该模型便会发光 接下来 来了解一下动画 RealityKit 具有大量 内置动画类型 例如 From-to-by 动画 它能以动画形式将属性 从初始值变化到最终值 轨道动画可以让实体 围绕其父级进行旋转 最后逐帧动画可以 对一系列值进行逐帧推进 我会对月球设置轨道动画 月球在轨道上 完成环绕一周需要 30 秒 并且轨道轴为 Y 轴 接着 我还会确保轨道 从月球的当前位置开始 在定义完轨道动画的属性后 我会为其生成一个动画资源 并在月球实体上播放该动画 现在 我们就可以看到 月球围绕着地球运动了 对我来说 这简直是神奇的时刻 使用动画 场景便会栩栩如生 动画会帮助 App 更加生动逼真 而空间音频还可以让模型 具有身临其境的效果 RealityKit 中的音频可分为 3 类: 空间音频、环境音频以及通道音频 现在来了解一下每种音频 默认情况下 RealityKit 的声音 是空间音频 所以 音频源听起来 就像在你身边一样 空间音频组件可以让你自定义 物体在你空间中发出声音的方式 从而使其更加真实 或更具艺术性 可以使用指向性 来向所有方向发出声音 也可以向特定方向投射声音 环境音频组件非常适合多声道文件 并且可以捕捉环境的声音 环境音源不会添加额外的混响效果 并且环境中的每个声道 都是从固定方向进行播放的 最后 通道音频组件 可将音频文件通道直接发送给扬声器 同时不会带来任何空间效果 此组件非常适合于背景音乐 因为该音乐不与任何视觉元素相连 可以将音频添加到 Reality Composer Pro 中的场景内 并使用 RealityKit 与其进行交互 或者 也可以在代码中连接音频 我们来具体看一下 我将在轨道卫星 添加一段循环播放的音频 首先 我会在一个空的实体中 添加空间音频 并将其作为音源 接着 将指向性设置为 0.75 创建一个指向特定方向的 狭窄声束 我会将该音源实体 围绕其 Y 轴转动 以使音频投射向我需要的方向 然后 我会从资源中加载 一段循环播放的音频剪辑 并调用 playAudio 在 audioSource 实体上播放该音频 我们来看看实际效果如何 由于空间音频源的配置 具有高度集中的指向性 因此 地球靠近我这一侧的 音频十分清楚 但是当卫星移动到另一侧时 音频音量会降低 以上就是输入、动画 以及音频的全部内容 通过多种方式将现有 RealityKit 功能进行组合 你便可以在其中构建出更多功能 为此 你可以使用这两种主要工具 来定义自己的组件以及自己的系统 组件包含了用于控制 3D 体验 其中一方面的数据 组件会被分到各个实体 没有组件 实体就无法进行任何操作 并且 每个组件都会为实现实体 提供一种元素 此前 你已经了解了变换组件 可以定位实体 模型组件可以 渲染 3D 模型 除了使用 RealityKit 所提供的预定义组件 你还可以定义自己的组件 本示例中的自定义组件 便包含了我的同事 Paul 创建的 TraceMesh 对象 由于 TraceComponent 类型 遵循组件协议 因此 你可以在运行时 从任何实体上获取该组件 并对其进行设置 同时 你还可以在 Swift 页面中 定义一个组件 并使其遵循 Codable 协议 来使用数据驱动型工作流 接着 可编码组件就会出现在 Reality Composer Pro 的界面中 并可以在设计时直接添加到实体中 你可以观看“在 Xcode 中处理 Reality Composer Pro 内容”讲座 了解更多有关自定义组件的内容 我在讲座前半段介绍了实体 并且刚才也对组件进行了介绍 接下来 我们来了解一下系统 系统包含了由实体和组件执行的代码 若将实体、组件以及系统 或 ECS 进行组合 它们就可以成为对 3D 体验的 外观和操作进行建模的工具 系统可用于构造 实现 App 操作的代码 并且 系统中的代码 会以一定时间间隔运行 具体取决于组件当前的状态 例如 该 TraceSystem 会在 卫星实体围绕地球转动时 更新其身后的线条网格 并且 其在每次更新中都会向轨迹 添加实体当前的位置 系统在完成注册后 就会自动应用到你在 App 中 使用 RealityKit 的所有位置 因此 在 App 初始化定式中 注册轨迹系统后 其便会对所有相关实体进行更新 但哪些实体是相关的 系统又会何时更新呢? 由于该系统只会更新 具有轨迹组件的实体 所以 我会创建一个实体查询 用于过滤具有轨迹组件的实体 在 update 函数中 系统会传入实体查询 并指定其需要在渲染时更新的实体 渲染条件是指该系统 会以适当的速度进行更新 以获得平滑的动画 这里是跟踪系统的实际效果 即 将实体位置添加到线条网格 来生成流畅的自定义动画 系统是实现多种效果 和操作的有效方式 RealityKit 具有许多功能 可以让构建 3D App 更加轻松 你可以使用 RealityKit 和 RealityView 将 3D 元素 添加至由 SwiftUI 定义的 视图、窗口以及沉浸式环境中 仅通过 RealityKit 你就可以 加载 USD 文件、处理手势 以及播放动画和空间音频 RealityKit 提供了大量 预定义的组件 但你也可以根据 App 的特殊需求 来定义自定义组件和系统 以上便是你开始使用 RealityKit 所需运用的概念 Eugene 的讲座 “使用 RealityKit 增强你的空间计算 App” 会带你了解更多 RealityKit 的功能 例如:门户、粒子发射器以及附件等 同时 Amanda 的讲座 “在 Xcode 中使用 Reality Composer Pro 的内容” 还会带你了解使用 Reality Composer Pro、 RealityKit、Xcode 预览 以及模拟器编译沉浸式 App 的过程 RealityKit 具有许多出色的功能 可用于你的 App 中 我非常期待看到你创造出的 美妙体验 感谢你的观看 ♪
-
-
3:40 - Model3D
import SwiftUI import RealityKit struct GlobeModule: View { var body: some View { Model3D(named: "Globe") { model in model .resizable() .scaledToFit() } placeholder: { ProgressView() } } }
-
5:52 - Volumetric window
import SwiftUI import RealityKit // Define a volumetric window. struct WorldApp: App { var body: some SwiftUI.Scene { // ... WindowGroup(id: "planet-earth") { Model3D(named: "Globe") } .windowStyle(.volumetric) .defaultSize(width: 0.8, height: 0.8, depth: 0.8, in: .meters) } }
-
7:31 - ImmersiveSpace
import SwiftUI import RealityKit // Define a immersive space. struct WorldApp: App { var body: some SwiftUI.Scene { // ... ImmersiveSpace(id: "objects-in-orbit") { RealityView { content in // ... } } } }
-
12:40 - RealityView
import SwiftUI import RealityKit struct Orbit: View { let earth: Entity var body: some View { RealityView { content in content.add(earth) } } }
-
12:54 - RealityView asynchronous loading and entity positioning
import SwiftUI import RealityKit struct Orbit: View { var body: some View { RealityView { content in async let earth = ModelEntity(named: "Earth") async let moon = ModelEntity(named: "Moon") if let earth = try? await earth, let moon = try? await moon { content.add(earth) content.add(moon) moon.position = [0.5, 0, 0] } } } }
-
13:54 - Earth rotation
import SwiftUI import RealityKit struct RotatedModel: View { var entity: Entity var rotation: Rotation3D var body: some View { RealityView { content in content.add(entity) } update: { content in entity.orientation = .init(rotation) } } }
-
14:27 - Converting co-ordinate spaces
import SwiftUI import RealityKit struct ResizableModel: View { var body: some View { GeometryReader3D { geometry in RealityView { content in if let earth = try? await ModelEntity(named: "Earth") { let bounds = content.convert(geometry.frame(in: .local), from: .local, to: content) let minExtent = bounds.extents.min() earth.scale = [minExtent, minExtent, minExtent] } } } } }
-
14:56 - Play an animation
import SwiftUI import RealityKit struct AnimatedModel: View { @State var subscription: EventSubscription? var body: some View { RealityView { content in if let moon = try? await Entity(named: "Moon"), let animation = moon.availableAnimations.first { moon.playAnimation(animation) content.add(moon) } subscription = content.subscribe(to: AnimationEvents.PlaybackCompleted.self) { // ... } } } }
-
18:31 - Adding a drag gesture
import SwiftUI import RealityKit struct DraggableModel: View { var earth: Entity var body: some View { RealityView { content in content.add(earth) } .gesture(DragGesture() .targetedToEntity(earth) .onChanged { value in earth.position = value.convert(value.location3D, from: .local, to: earth.parent!) }) } }
-
20:20 - Playing a transform animation
// Playing a transform animation let orbit = OrbitAnimation(name: "Orbit", duration: 30, axis: [0, 1, 0], startTransform: moon.transform, bindTarget: .transform, repeatMode: .repeat) if let animation = try? AnimationResource.generate(with: orbit) { moon.playAnimation(animation) }
-
22:12 - Adding audio
// Create an empty entity to act as an audio source. let audioSource = Entity() // Configure the audio source to project sound out in a tight beam. audioSource.spatialAudio = SpatialAudioComponent(directivity: .beam(focus: 0.75)) // Change the orientation of the audio source (rotate 180º around the Y axis). audioSource.orientation = .init(angle: .pi, axis: [0, 1, 0]) // Add the audio source to a parent entity, and play a looping sound on it. if let audio = try? await AudioFileResource(named: "SatelliteLoop", configuration: .init(shouldLoop: true)) { satellite.addChild(audioSource) audioSource.playAudio(audio) }
-
23:47 - Defining a custom component
import RealityKit // Components are data attached to an Entity. struct TraceComponent: Component { var mesh = TraceMesh() } // Entities contain components, identified by the component’s type. func updateTrace(for entity: Entity) { var component = entity.components[TraceComponent.self] ?? TraceComponent() component.update() entity.components[TraceComponent.self] = component } // Codable components can be added to entities in Reality Composer Pro. struct PointOfInterestComponent: Component, Codable { var name = "" }
-
24:51 - Defining a system
import SwiftUI import RealityKit // Systems supply logic and behavior. struct TraceSystem: System { static let query = EntityQuery(where: .has(TraceComponent.self)) init(scene: Scene) { // ... } func update(context: SceneUpdateContext) { // Systems often act on all entities matching certain conditions. for entity in context.entities(Self.query, updatingSystemWhen: .rendering) { addCurrentPositionToTrace(entity) } } } // Systems run on all RealityKit content in your app once registered. struct MyApp: App { init() { TraceSystem.registerSystem() } }
-
-
正在查找特定内容?在上方输入一个主题,就能直接跳转到相应的精彩内容。
提交你查询的内容时出现错误。请检查互联网连接,然后再试一次。