Unity 6.3
0 онлайн 101 гостей 3 в системе
Вход
Доступность Шаг 3 из 7

Начало работы с поддержкой экранного чтения

Поддержка экранных читателей APIs не зависит от системы UI, поэтому они работают с UI Toolkit, uGUI, пользовательскими UI фреймворками и не-UI контентом, таким как 2D или 3D объекты в игровом мире. Для простоты, в этом руководстве используется UI Toolkit, но вы можете адаптировать код к вашему UI фреймворку по выбору.

Примерный обзор

В этом примере показано, как создать узел доступности, подключить его к кнопке UI Toolkit и протестировать его с помощью экранных читателей платформы. В конце у вас будет кнопка, которую могут читать и активировать собственные экранные читатели платформы.

Предварительные условия

Это руководство предназначено для разработчиков, знакомых со скриптами Unity Editor, UI Toolkit и C#. Перед началом работы ознакомьтесь со следующим:

Включить модуль доступности

Модуль специальных возможностей включён по умолчанию. Если по какой-либо причине он не включён в проекте, выполните следующие действия:

  1. Выберите Окно > Управление пакетами > Package Manager, чтобы открыть Package Manager.
  2. Выберите раздел Встроенный.
  3. Выберите модуль Доступность.
  4. Выберите Включить.

Создание кнопки

Используйте UI Toolkit для создания кнопки Start Game в сцене.

  1. Создайте проект с любым шаблоном.

  2. Создайте файл UXML с именем AccessibleStartMenu.uxml со следующим содержимым:

    <ui:UXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
        <ui:Button text="Start Game" name="startButton"/>
    </ui:UXML>
    
  3. Создайте скрипт C# с именем AccessibleStartMenu.cs со следующим содержанием:

using UnityEngine;
using UnityEngine.UIElements;

public class AccessibleStartMenu : MonoBehaviour
{
    Button m_Button;

    void OnEnable()
    {
        VisualElement root = GetComponent<UIDocument>().rootVisualElement;
        m_Button = root.Q<Button>("startButton");

        m_Button.clicked += OnButtonClicked;
    }

    void OnDisable()
    {
        m_Button.clicked -= OnButtonClicked;
    }

    void OnButtonClicked()
    {
        Debug.Log("Start Game button clicked");
    }
}

Создание иерархии доступности

Иерархия доступности представляет собой семантическое представление вашего UI, которое экранные редакторы используют для обнаружения и взаимодействия с вашим контентом. Экранные редакторы не могут непосредственно обнаружить компоненты GameObject или элементы UI. Они полагаются на эту иерархию для навигации по вашему приложению. Вы создаете AccessibilityHierarchy, а затем добавляете AccessibilityNode, который представляет кнопку Start Game.

Чтобы создать иерархию доступности:

  1. Добавить пространство имен UnityEngine.Accessibility.
  2. Создание экземпляра AccessibilityHierarchy.
  3. Создайте и добавьте AccessibilityNode в иерархию доступности.
  4. Установите свойства label, roleи state узла в соответствии с текстом кнопки и состоянием интерактивности.
// ...
using UnityEngine.Accessibility;

public class AccessibleStartMenu : MonoBehaviour
{
    // ...

    AccessibilityHierarchy m_AccessibilityHierarchy;
    AccessibilityNode m_AccessibilityNode;

    void OnEnable()
    {
        // ...

        CreateAccessibilityHierarchy();
    }

    // ...

    void CreateAccessibilityHierarchy()
    {
        // Create a new accessibility hierarchy.
        m_AccessibilityHierarchy = new AccessibilityHierarchy();

        // Create a new accessibility node with the button's text as the label
        // (what the screen readers announces).
        m_AccessibilityNode = m_AccessibilityHierarchy.AddNode(m_Button.text);

        // Set a semantic role (tells the screen reader this is a button).
        m_AccessibilityNode.role = AccessibilityRole.Button;

        // Set the state (is it currently interactable?).
        m_AccessibilityNode.state = m_Button.enabledSelf ?
            AccessibilityState.None : AccessibilityState.Disabled;
    }
}

Установите координаты экрана узла в соответствии с размером и положением кнопки

Чтобы установить координаты экрана узла:

  1. Отслеживайте изменения размера и положения кнопки.
  2. Рассчитать его экранные координаты из его мировых координат и масштаба UI.
  3. Установите свойство узла frame на вычисленный прямоугольник экрана.

Обновите скрипт AccessibleStartMenu.cs следующим образом:

public class AccessibleStartMenu : MonoBehaviour
{
    // ...

    void OnEnable()
    {
        // ...

        m_Button.RegisterCallback<GeometryChangedEvent>(OnGeometryChanged);
    }

    void OnDisable()
    {
        // ...

        m_Button.UnregisterCallback<GeometryChangedEvent>(OnGeometryChanged);
    }

    // ...

    void OnGeometryChanged(GeometryChangedEvent evt)
    {
        Rect worldRect = m_Button.worldBound;
        float scale = m_Button.panel.scaledPixelsPerPoint;

        // Update the screen coordinates of the node.
        m_AccessibilityNode.frame =
            new Rect(worldRect.position * scale, worldRect.size * scale);
    }
}

Подключите событие активации узла к кнопке

Подписаться на событие узла invoked, которое запускается, когда пользователь активирует узел с помощью экранного читателя, а затем вызвать событие кнопки NavigationSubmitEvent в обработчике событий.

Обновите метод CreateAccessibilityHierarchy в скрипте AccessibleStartMenu.cs следующим образом:

public class AccessibleStartMenu : MonoBehaviour
{
    // ...

    void CreateAccessibilityHierarchy()
    {
        // ...

        // Handle when the user activates this node (e.g., double-tap).
        // Called `selected` in versions before Unity 6.3.
        m_AccessibilityNode.invoked += () =>
        {
            using var evt = NavigationSubmitEvent.GetPooled();
            evt.target = m_Button;
            m_Button.SendEvent(evt);

            return true;
        };
    }
}

Активация иерархии доступности при включении программы чтения экрана

  1. Когда появится меню, активируйте иерархию доступности, назначив ее AssistiveSupport.activeHierarchy.
    • Когда пользователь выключает экранный проигрыватель, AssistiveSupport.activeHierarchy автоматически настраивается на null для высвобождения ресурсов.
  2. Переназначение иерархии каждый раз, когда пользователь включает экранный читатель.
  3. Когда меню исчезнет, удалите иерархию, установив AssistiveSupport.activeHierarchy на null.
public class AccessibleStartMenu : MonoBehaviour
{
    // ...

    void OnEnable()
    {
        // ...

        AssistiveSupport.activeHierarchy = m_AccessibilityHierarchy;
        AssistiveSupport.screenReaderStatusChanged += OnScreenReaderStatusChanged;
    }

    void OnDisable()
    {
        // ...

        AssistiveSupport.activeHierarchy = null;
        AssistiveSupport.screenReaderStatusChanged -= OnScreenReaderStatusChanged;
    }

    // ...

    void OnScreenReaderStatusChanged(bool enabled)
    {
        if (enabled)
        {
            AssistiveSupport.activeHierarchy = m_AccessibilityHierarchy;
        }
        // else
        // {
        //     // This is automatically done when the user turns the screen
        //     // reader off.
        //     AssistiveSupport.activeHierarchy = null;
        // }
    }
}

Вы создали семантическое представление (AccessibilityNode) визуальной кнопки, которую могут обнаружить и с которой могут взаимодействовать программы для чтения экрана.

Полный скрипт AccessibleStartMenu.cs выглядит следующим образом:

using UnityEngine;
using UnityEngine.Accessibility;
using UnityEngine.UIElements;

public class AccessibleStartMenu : MonoBehaviour
{
    Button m_Button;

    AccessibilityHierarchy m_AccessibilityHierarchy;
    AccessibilityNode m_AccessibilityNode;

    void OnEnable()
    {
        VisualElement root = GetComponent<UIDocument>().rootVisualElement;
        m_Button = root.Q<Button>("startButton");

        m_Button.clicked += OnButtonClicked;
        m_Button.RegisterCallback<GeometryChangedEvent>(OnGeometryChanged);

        CreateAccessibilityHierarchy();

        AssistiveSupport.activeHierarchy = m_AccessibilityHierarchy;
        AssistiveSupport.screenReaderStatusChanged += OnScreenReaderStatusChanged;
    }

    void OnDisable()
    {
        m_Button.clicked -= OnButtonClicked;
        m_Button.UnregisterCallback<GeometryChangedEvent>(OnGeometryChanged);

        AssistiveSupport.activeHierarchy = null;
        AssistiveSupport.screenReaderStatusChanged -= OnScreenReaderStatusChanged;
    }

    void CreateAccessibilityHierarchy()
    {
        // Create a new accessibility hierarchy.
        m_AccessibilityHierarchy = new AccessibilityHierarchy();

        // Create a new accessibility node with the button's text as the label
        // (what the screen readers announces).
        m_AccessibilityNode = m_AccessibilityHierarchy.AddNode(m_Button.text);

        // Set a semantic role (tells the screen reader this is a button).
        m_AccessibilityNode.role = AccessibilityRole.Button;

        // Set the state (is it currently interactable?).
        m_AccessibilityNode.state = m_Button.enabledSelf ?
            AccessibilityState.None : AccessibilityState.Disabled;

        // Handle when the user activates this node (e.g., double-tap).
        // Called `selected` in versions before Unity 6.3.
        m_AccessibilityNode.invoked += () =>
        {
            using var evt = NavigationSubmitEvent.GetPooled();
            evt.target = m_Button;
            m_Button.SendEvent(evt);

            return true;
        };
    }

    void OnGeometryChanged(GeometryChangedEvent evt)
    {
        Rect worldRect = m_Button.worldBound;
        float scale = m_Button.panel.scaledPixelsPerPoint;

        // Update the screen coordinates of the node.
        m_AccessibilityNode.frame =
            new Rect(worldRect.position * scale, worldRect.size * scale);
    }

    void OnButtonClicked()
    {
        Debug.Log("Start Game button clicked");
    }

    void OnScreenReaderStatusChanged(bool isEnabled)
    {
        if (isEnabled)
        {
            AssistiveSupport.activeHierarchy = m_AccessibilityHierarchy;
        }
        // else
        // {
        //     // This is automatically done when the user turns the screen
        //     // reader off.
        //     AssistiveSupport.activeHierarchy = null;
        // }
    }
}

Приложить скрипт

Чтобы прикрепить скрипт к вашей сцене:

  1. Создайте пустой GameObject в вашей сцене и дайте ему имя AccessibleStartMenu.
  2. Добавить компонент UI Document в GameObject.
  3. Создайте ассет Настройки панели и назначьте его в поле Panel Settings в окне Inspector компонента UI Document.
  4. Назначьте файл AccessibleStartMenu.uxml в поле Source Asset.
  5. Добавить скрипт AccessibleStartMenu.cs к GameObject.

Проверка свойств иерархии и узла в режиме воспроизведения

Для проверки свойств иерархии и узлов в Unity Editor:

  1. Введите режим воспроизведения.
  2. Выберите Окно > Доступность > Hierarchy Просмотр.
  3. Убедитесь, что в иерархии доступности отображается узел доступности с правильными свойствами.
Просмотрщик доступности Hierarchy, отображающий свойства узла доступности, представляющего кнопку Пуск Game
Просмотрщик доступности Hierarchy, отображающий свойства узла доступности, представляющего кнопку “Start Game”

Проверка взаимодействия экранного чтения на вашей целевой платформе

Чтобы проверить взаимодействие экранного чтения на целевой платформе:

  1. Создайте и запустите приложение на целевой платформе (Android, iOS, Windows или macOS).
  2. Ознакомьтесь с жестами или командами встроенного в платформу экранного чтителя:
    • Android: TalkBack жесты на Android
    • iOS: VoiceOver жесты на iPhone
    • Windows: Команды Диктора на Windows
    • macOS: VoiceOver команды на Mac
  3. Включите экранный читатель.
  4. Перейдите к кнопке с помощью жестов или команд экранного считывателя. Считывающее устройство должно фокусироваться на кнопке и объявлять «Пуск Game, кнопка».
  5. Активируйте кнопку с помощью жеста или команды активации средства чтения с экрана. Кнопка должна сработать, а текст “Start Game button clicked” — появиться в журнале проигрывателя.

Дополнительные ресурсы

  • 📚 Документация: Модуль доступности API ссылка
  • 📺 Видео: Охват новых аудиторий с помощью доступности и локализации в Unity 6 (Unite 2025)
  • ⚙️ Образец проекта: LetterSpell: пример доступного Unity применение
  • Сообщество: Unity Дискуссии: Доступность