Что хотим получить
Логика должна быть такой:
При возвращении в игру пауза автоматически не снимается.
Игрок возвращается и видит обычное меню:
А уже сам нажимает «Продолжить».
Почему не обычный LostFocus
Изначально я пробовал использовать:
На первый взгляд всё работает.
Но возникла проблема: если в проекте используется CommonUI, игровой viewport может потерять фокус даже тогда, когда игрок просто открывает внутриигровое меню.
В результате получалось:
То есть событие срабатывало дважды.
Поэтому в итоге я отказался от проверки фокуса самого viewport и стал отслеживать именно состояние приложения.
Для этого используется:
Теперь мы различаем:
и:
Шаг 1. Добавляем C++ в Blueprint-проект
Если проект до этого был полностью на Blueprint ничего страшного.
В Unreal Engine:
Tools → New C++ Class
В качестве родителя я использую:
потому что в проекте уже используется CommonUI.
Создаём класс:(за место Pangit…..используйте свое имя
После этого Blueprint-проект становится гибридным Blueprint + C++, но переписывать существующие Blueprint'ы на C++ не требуется.
Шаг 2. Добавляем зависимости
Открываем:
У меня это
У меня он выглядит так:
Здесь нам нужны:
потому что наш Viewport Client наследуется от:
и:
потому что дальше будем использовать:
Шаг 3. PangitGameViewportClient.h
Создаём заголовочный файл:
Главная часть здесь:
Это позволяет пробросить событие из C++ обратно в Blueprint.
То есть C++ будет только определять:
Игра действительно потеряла фокус приложения.
А что делать после этого - решаем уже в Blueprint.
Шаг 4. PangitGameViewportClient.cpp
Когда приложение становится неактивным:
вызывается:
И дальше управление переходит в Blueprint.
Шаг 5. Компилируем
После изменения C++:
и:
Build → Build Solution
Если всё нормально:
Шаг 6. Создаём Blueprint Viewport Client
Теперь создаём Blueprint-наследника нашего класса:
И назначаем его:
Project Settings → Engine → General Settings → Default Classes
В:
ставим:
При этом CommonUI не пропадает.
Иерархия остаётся:
Шаг 7. Ловим событие в Blueprint
В BP_PangitGameViewportClient появляется:
Дальше можно вызвать уже существующую систему паузы.
Я использую ассет Menu System Pro
У меня получилось примерно так:
Вы можете вызывать свой виджет где у вас меню (с логикой Pause/Unpause)
Что получилось
Теперь:
То же самое работает при сворачивании окна или переключении на другое приложение.
А обычное:
не вызывает событие повторно, потому что мы отслеживаем не потерю фокуса GameViewport, а именно изменение активности всего приложения.
В итоге C++ здесь нужен буквально как небольшой мост: