大多数浏览器和
Developer App 均支持流媒体播放。
-
在 Unity 游戏中添加辅助功能
了解如何使用我们的开源辅助功能插件,使用户能够在 Apple 平台上更轻松地访问你的 Unity 游戏。跟着我们一起,在示例 Unity 游戏项目中添加对旁白和切换控制等辅助技术的支持。我们将向你介绍如何通过“动态类型”自动扩展文本,以及支持降低透明度或提高对比度等界面调整功能。
资源
相关视频
WWDC22
-
下载
♪ ♪
Eric Liang: 大家好 我是 Eric 我很高兴可以为大家分享 如何为您的 Unity 游戏添加辅助功能
辅助功能是为了让每个人都可以 使用我们的产品 今天我们为 Unity 开发者们 提供的 Apple Accessibility 插件 标志着我们向着无障碍游戏 又前进了一大步 为了让游戏支持辅助功能 我们主要专注于三个 Apple 技术
旁白 是一个帮助失明 或低视力用户的屏幕阅读器 它可以朗读屏幕上的内容 用户也可以用自定义手势 来与控件交互
切换控制 让运动控制能力较弱的用户 使用外部切换控制器来与设备交互 还有动态字体 让用户可以 根据自身的阅读能力 来设置字体大小
首先 克隆代码库 运用代码库根目录下的构建脚本 来构建所有 Apple 插件 接着 这样会生成一个 Build 文件夹 可以将其整合到 您的 Unity 项目中 最后 用 Unity Package Manager 将 Apple Accessibility 插件添加 到您的项目中 您还可以查看代码库中的文档 以及观看介绍所有 Apple 的 Unity 插件的视频课程 “Plug-in and play: Add Apple frameworks to your Unity game projects” 以获取更多细节 现在您已经准备好了插件 我将会从以下三个方面为大家讲解 第一个是辅助功能元素 这让您可以在游戏中 增加辅助技术的支持 如 旁白 或 切换控制 接下来是 动态字体 我们创建了这个易于使用的工具 帮助您根据用户偏好设置 来缩放字体 还有 UI 适应性设置 这些实用工具可以帮助您 读取其它的用户偏好设置 我们先来看下辅助功能元素
我创建了一个简易的卡牌游戏 来帮助解释这个概念 您可以看到 您要点击 “Flip”按钮 来随机抽取两张卡牌 然而 旁白 不会朗读 屏幕上的文本 而外部切换控制器也不会点击按钮 因为现在屏幕上只有像素 我们要帮助系统理解 哪些是可以进行交互的 辅助功能元素定义了辅助技术 可以交互的部分
文本 卡牌和屏幕上的按钮 都应该是辅助功能元素 我们可以用标签来描述 每个元素 旁白 会朗读标签 这样用户能理解屏幕上的内容
如果游戏支持多语言 我们也应该对标签进行本地化
现在 旁白 可以描述 屏幕上的内容了 但是它还不知道屏幕上 还有一个可点击的按钮 我们可以使用另一个属性 称为“Traits” 来告知系统该元素的类型 我们在这里添加 “Button”的特性 现在 旁白 会朗读 “翻转 按钮” 然后外部切换控制器可以控制该按钮
我们也可以添加在文本元素上 添加“Static Text”特性 “Static Text”特性通常是 赋予标签和文本区域的 这样 旁白 可以提供 更好的文本交互体验
除了“Button”和“Static Text”外 还有很多特性 是您可以探索的
那卡牌应该用什么特性呢 我们不需要给每个 辅助功能元素都运用特性 卡牌就不需要任何特性 然而 卡牌上还有一个部分 是 旁白 没有识别的 那就是卡面值 这里我们可以使用另一个属性 称为“Value”
我们为每张卡牌添加了一个“Value”后 旁白 现在可以朗读 “卡牌 1 梅花 3” “卡牌 2 梅花 A” 就是这样 现在您已经理解了基本原理 我们打开 Unity 来看下可以如何将其 添加到我们的项目中
现在我进入了游戏的 Unity 编辑器环境下 我已经为这个项目中 添加了 Apple Accessibility 插件
首先 我们有常规的场景对象 如相机 定向光和 UI 画布 在 画布 下面 有两个文本元素 和一个按钮 然后 我们有两个卡牌游戏对象
每个都由两个网格组件组成 卡牌的每一面都渲染了对应的正反面纹理 我们从定义辅助功能元素开始吧 这需要插件中的 Accessibility Node 组件
选中层级结构中应该设置辅助功能的 所有对象
添加 Accessibility Node 组件 让它们成为辅助功能元素
接下来 添加标签 选择卡牌对象 到右边的 “Accessibility Node”组件 找到“Label”字段
确保 label 字段的复选框已选中 以创建自定义标签
然后输入“Card 1”
对于 Card 2 也做同样的操作
文本和按钮也需要标签 但如果我们用的是 Unity UI 的 标准控件 则不需要为它们提供一个显式的 辅助功能标签 插件 已经默认实现了
接下来 我们要为按钮添加 一个特性
选择 Flip 按钮 将“Traits”从“None” 修改为“Button”
选择两个文本元素
将“Traits”修改为“Static Text”
好了 最后 我们要为卡面值 设置对应辅助功能数值 由于卡牌是随机抽取的 我需要添加脚本 来动态设置卡面值
选择两张卡牌 添加一个 AccessibleCard 的新脚本
首先 在我另一个 C# 文件中 所有卡牌正面都已经有了 一个枚举称为 Playing Card 在我新的 AccessibleCard 这个 Mono Behaviour 脚本中 设置了一个关于卡牌类型的变量 和一个关于卡面上下朝向的布尔值
现在我们为这些卡牌 添加 accessibilityValue 首先 获取附属于这个 gameObject 的 accessibilityNode 组件
接下来 将 accessibilityValue 代理设置为 动态返回卡面值的函数
在函数中 如果卡面朝下 会在 accessibilityValue 中 返回“covered” 如果卡面朝上 我们会枚举 所有卡面 返回每张卡牌的描述 如“黑桃 A” 就是这样 现在我们来构建项目 看下其实际运行情况 这就是我们的游戏 我们打开 旁白
【自动语音: 旁白】 开启 Eric 的游戏 卡牌 2 面朝下 【Eric】 我可以向右滑动 来移动到下一个元素 【自动语音】 卡牌 1 面朝下
Eric 的卡牌游戏
翻牌
Flip 按钮 【Eric】 您看现在所有五个对象 都可以用 旁白 来访问 太赞了 当 旁白 开启时 对这个要点击的按钮进行双击 【自动语音】 翻牌 【Eric】 我们再来看下卡牌
【自动语音】 卡牌 1 梅花 2
卡牌 2 梅花 A 【Eric】 旁白 现在可以正确 朗读更新后的卡面值 这样很酷 我们现在可以为数百万的 旁白 用户制作无障碍游戏了 他们一定会很喜欢的 还有使用外部切换控制器的用户 也会玩我们的游戏 这就是辅助功能元素 接下来 我们来看下动态字体
由于文本太小看不清 对很多人来说 玩游戏可能并不容易 在 iOS 和 tvOS 中 每个人可以 根据自身阅读能力 在设置中调整合适的字体大小
通过 Accessibility 插件 您也可以读取该设置 确保游戏的文本能 按预期字体大小来显示
我们根据游戏示例来看下 动态字体是如何使用的
创建一个 DynamicTextSize.cs 的 Mono Behaviour脚本 在开始函数中 首先将默认 文本大小存储为变量 然后在 OnEnable 函数中 使用 AccessibilitySettings.onPreferredTextSizesChanged 来订阅 settingsChanged 事件 这样用户在改变字体设置时 我们可以马上更改 UI
接下来 在 settingsChanged 函数中 首先读取 PreferredContentSizeMultiplier 然后乘以您的原始字体大小 然后分配回 Text 元素 在 Unity 编辑器中 选择有 Text 元素的 所有游戏对象 添加我们刚刚创建的 DynamicTextSize 组件
现在我们的游戏都设置好 动态字体支持了 我们看实际的运行效果前 我先给大家演示下 一个快速测试游戏中 动态字体的方法 打开设置 找到控制中心
向下滚动 直到看见字体大小 将其添加到控制中心
现在我们通过打开控制中心 改变字体大小选项 就能快速调整字体大小了
很好 我改变字体大小时 游戏也会实时改变字体大小
控制中心中显示的 字体百分比值 正是我们从乘数读取的 您也可以将这个设置 应用到非文本对象中 例如 在字体大小增加时 我可以将卡牌正面素材 替换为 Large Print
首先 我创建一个 DynamicCardFaces 脚本 然后和之前一样 订阅 TextSizeChanged 事件
这次不是读取乘数 而是读取一个字体大小类别的枚举 它被映射到控制中心滑块的刻度上 有人选择大号字体的时候 我就可以替换素材
我只要在常规材质 和大号印刷体材质之间选择即可 现在 如果我们选择了 非常大的字体
用户可能会看到大号印刷体的卡牌 对于低视力的用户来说 这种卡牌正面的易读性很强
最后 我跟大家分享下 您可以用这个插件访问 UI 适应性设置
第一个设置是 Reduce Transparency 开启这个设置后 背景变成不透明 而不是模糊或透明效果 文本在这些效果下难以识别时 该设置可以提高易读性 调用 AccessibilitySettings. IsReduceTransparencyEnabled 来查看这个偏好设置
接下来是 Increase Contrast 设置 深灰色的开关会更显眼 在整个设备中也会更易于识别
您可以使用 AccessibilitySettings.IsIncreaseContrastEnabled 来查看这一设置 启用后即可增加 UI 对比度
接下来是 Reduce Motion 设置 有些人对手势很敏感 正如我们在这个翻牌动画中一样
Reduce Motion 启用时 我们应该移除该动画
我们看下实现的代码
在我们的 CardController 脚本中 有这个 Flip 函数 首先我们看下用户的 Reduce Motion 设置是否开启 如果没有开启 我们应通过 Coroutine 调用动画来翻牌 否则就只是设置单纯旋转 而不带动画 就这样 现在对手势比较敏感的用户 也能享受我们的游戏了 回顾一下 首先通过克隆 这个讲座资源关联的 GitHub 数据库来 开启 Apple 辅助功能插件
添加辅助功能元素 这样用户可以在游戏中 使用 旁白 和 切换控制
用动态字体来调整字体大小
检查 UI 适应性设置 这样每个人都能对游戏 有绝佳的体验
感谢大家的参与 我们很期待能看到您的游戏 有完美的无障碍体验
-
-
7:43 - PlayingCard enum
public enum PlayingCard { AceOfSpade, AceOfClubs, AceOfDiamonds }
-
7:53 - AccessibleCard class
using Apple.Accessibility; public class AccessibleCard : MonoBehaviour { public PlayingCard cardType; public bool isCovered; void Start() { var accessibilityNode = GetComponent<AccessibilityNode>(); accessibilityNode.accessibilityValueDelegate = () => { if (isCovered) { return "covered"; } if (cardType == PlayingCard.AceOfSpades) { return "Ace of Spades"; } } } }
-
10:35 - DynamicCardFaces
public class DynamicCardFaces : MonoBehaviour { public Material RegularMaterial; public Material LargeMaterial; void OnEnable() { AccessibilitySettings.onPreferredTextSizesChanged += _settingsChanged; } void _settingsChanged() { var shouldUseLarge = AccessibilitySettings.PreferredContentSizeCategory >= ContentSizeCategory.AccessibilityMedium; GetComponent<Renderer>().material = shouldUseLarge ? RegularMaterial : LargeMaterial; } }
-
10:36 - Dynamic Type
using UnityEngine.UI; public class DynamicTextSize : MonoBehaviour { int originalSize; void Start() { originalSize = GetComponent<Text>().textSize; } void OnEnable() { AccessibilitySettings.onPreferredTextSizesChanged += _settingsChanged; } void _settingsChanged() { GetComponent<Text>().textSize = (int)(originalSize * AccessibilitySettings.PreferredContentSizeMultiplier); } }
-
14:54 - Reduce motion
using Apple.Accessibility; public class CardController : MonoBehaviour { public void Flip() { var reduceMotionOn = !AccessibilitySettings.IsReduceMotionEnabled; if (!reduceMotionOn) { StartCoroutine(Animate()); } else { transform.rotation = Quaternion.identify; } } IEnumerator Animate() { } }
-
-
正在查找特定内容?在上方输入一个主题,就能直接跳转到相应的精彩内容。
提交你查询的内容时出现错误。请检查互联网连接,然后再试一次。