Разработка игрData и ИИLua / Luau

Как сделать NPC с ИИ-диалогом и голосом в Roblox Studio

Создаём NPC в Roblox Studio, генерируем короткую реплику через TextGenerator, фильтруем её для игроков и озвучиваем через AudioTextToSpeech в 3D-пространстве.

Кодик

Автор

7 мин чтения

ИИ-NPC в Roblox можно собрать из трёх независимых частей: триггера игрока, TextGenerator для реплики и AudioTextToSpeech для голоса. Между генерацией и показом текста обязательна фильтрация Roblox. Мы сделаем гида с ProximityPrompt, короткой репликой на экране, 3D-голосом и безопасным запасным ответом.

Такой NPC может учитывать цель игрока, но не должен управлять наградами и прогрессом. Модель формулирует фразу, игровые правила остаются в серверном коде. Первая версия отвечает на фиксированный вопрос о кристаллах: prompt запускает генерацию, фильтр, BillboardGui и голос у головы NPC.

1Запрашиваем

ProximityPrompt передаёт серверу конкретного игрока и запускает одну реплику.

2Фильтруем

TextGenerator создаёт черновик, TextService готовит безопасный текст для показа.

3Озвучиваем

AudioTextToSpeech соединяется Wire с AudioEmitter у головы NPC.

Как устроена цепочка ИИ-диалога и голоса

Создайте GuideNPC с Humanoid и Head. В Head добавьте ProximityPrompt, BillboardGui/TextLabel, AudioTextToSpeech, AudioEmitter и Wire. Свяжите Wire от TTS к Emitter. Включите нужные AI beta features, если они ещё не общедоступны. Скрипт в ServerScriptService получает объекты по точным путям. Фиксированный первый вопрос облегчает проверку длины и содержания.

ОбъектГде находитсяЗа что отвечает
ProximityPromptGuideNPC/HeadЯвное действие игрока
TextGeneratorGuideNPCКороткая динамическая реплика
TextServiceСервис RobloxФильтрация перед показом
BillboardGui/TextLabelGuideNPC/HeadСубтитр над NPC
AudioTextToSpeechGuideNPC/HeadПреобразование текста в речь
AudioEmitter + WireGuideNPC/Head3D-источник звука

Каждый объект имеет одну работу. Если голос молчит, можно отдельно проверить TTS и Wire. Если ответ не генерируется, запасная реплика всё равно покажет, что prompt, интерфейс и звук подключены правильно.

Путь реплики NPC
Текст становится видимым только после фильтра. Один отфильтрованный результат идёт в оба канала

Сначала проверьте статическую реплику. Задайте AudioTextToSpeech.Text вручную и вызовите Play. Если звук не слышен, генеративная модель здесь ни при чём. Проверьте Wire, AudioEmitter, расположение NPC и настройки слушателя до подключения TextGenerator.

Собираем NPC и серверный Luau-скрипт

Код ожидает объекты из таблицы. TextGenerator уже добавлен в GuideNPC. SystemPrompt ограничивает роль, MaxTokens сокращает ответ, а строка обрезается до лимита TTS. GenerateTextAsync и фильтрация работают в pcall. При любом сбое возвращается безопасная подсказка.

local TextService = game:GetService("TextService")
local npc = workspace:WaitForChild("GuideNPC")
local head = npc:WaitForChild("Head")
local prompt = head.ProximityPrompt
local label = head.BillboardGui.TextLabel
local voice = head.AudioTextToSpeech
local generator = npc.TextGenerator
local FALLBACK = "Ищи три кристалла у водопада."
local busy = false

generator.SystemPrompt = "Ты добрый проводник. Ответь одной фразой до 25 слов."

local function safeReply(player)
	local ok, response = pcall(function()
		return generator:GenerateTextAsync({
			UserPrompt = "Где искать кристаллы?", MaxTokens = 50})
	end)
	if not ok or not response.GeneratedText then return FALLBACK end
	local filteredOk, filtered = pcall(function()
		return TextService:FilterStringAsync(
			response.GeneratedText, player.UserId
		):GetNonChatStringForBroadcastAsync()
	end)
	if not filteredOk or filtered == "" then return FALLBACK end
	return string.sub(filtered, 1, 300)
end

prompt.Triggered:Connect(function(player)
	if busy then return end
	busy = true
	prompt.Enabled = false
	label.Text = "Думаю..."
	local reply = safeReply(player)
	label.Text = reply
	voice.Text = reply
	voice.TimePosition = 0
	voice:Play()
	voice.Ended:Wait()
	prompt.Enabled = true
	busy = false
end)
Что должно произойти после запуска
  • Нажатие prompt показывает состояние «Думаю...», затем безопасную короткую реплику.
  • Тот же отфильтрованный текст передаётся в AudioTextToSpeech и звучит от головы NPC.
  • Повторное нажатие во время речи не создаёт второй параллельный запрос.
  • При сбое TextGenerator или фильтрации используется FALLBACK, и сценарий не ломается.

Атмосфера и игровые правила
Модели подходит только одна сторона. Текст не является командой игровому серверу

Почему текст нужно фильтровать до показа и речи

TextGenerator возвращает GeneratedText, который нельзя сразу показывать или озвучивать. Roblox требует TextService:FilterStringAsync. Для общей реплики берём GetNonChatStringForBroadcastAsync. Только этот результат идёт в TextLabel и AudioTextToSpeech.Text. Строка ограничена 300 символами, busy и отключение prompt защищают от параллельных запросов.

ЭтапЕсли всё хорошоЕсли произошёл сбой
GenerateTextAsyncЕсть GeneratedTextЛог и FALLBACK
FilterStringAsyncПолучен безопасный broadcast textЛог и FALLBACK
TextLabelПоказывает субтитрОстаётся понятная подсказка
AudioTextToSpeechПроигрывает ту же строкуТекст всё равно виден
EndedВозвращает promptНужен таймаут в развитой версии

AudioTextToSpeech ограничивает запросы и длину Text до 300 символов. Не запускайте генерацию на каждом Touched. Prompt, cooldown и кэш сокращают обращения. Храните несколько fallback-фраз и добавьте таймаут ожидания Ended. Генеративный текст отвечает за атмосферу, а число кристаллов, награды и условия квеста берёт сервер.

Один безопасный текст идёт во все каналы. Не показывайте пользователю исходный GeneratedText, пока голос получает отфильтрованную версию. Субтитр и речь должны использовать одну и ту же строку после TextService, иначе игрок услышит не то, что видит.

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

Сначала отключите генерацию и верните FALLBACK напрямую. Проверьте prompt, BillboardGui, TTS и повторное нажатие. Затем включите TextGenerator и временно распечатайте только статус этапов, не полный пользовательский текст. Смоделируйте ошибку неверным именем NPC, отключённой beta feature и пустым GeneratedText. После восстановления запустите тест с двумя клиентами. Текущая версия использует общий busy, поэтому второй игрок ждёт окончания реплики. Это осознанное ограничение первого примера. Для персональных диалогов понадобится отдельное состояние по Player и решение, кому именно транслировать звук и субтитры.

Проверка своими руками
  1. Создайте структуру GuideNPC и вручную проиграйте статический TTS-текст.
  2. Подключите Script с временным return FALLBACK и проверьте интерфейс.
  3. Включите генерацию и убедитесь, что ответ проходит TextService до показа.
  4. Нажмите prompt дважды во время речи. Второй запрос не должен стартовать.
  5. Нарушьте путь к TextGenerator и получите запасную реплику без падения сценария.
  6. Проведите тест с двумя клиентами и зафиксируйте выбранное поведение общего busy.
Готово, если выполняются все пункты
  • Статический TTS работает независимо от модели.
  • Сгенерированный текст всегда фильтруется.
  • Субтитр и голос получают одинаковую безопасную строку.
  • Сбой генерации приводит к FALLBACK, а не к сломанному NPC.

Четыре режима проверки NPC
Проверяем каждый слой отдельно. Сбой AI не ломает квест

Развиваем персонажа без передачи ему игровых правил

Дальше передавайте небольшой контекст: задание, найденные предметы и разрешённую подсказку. SystemPrompt запрещает менять правила, сервер фильтрует ответ. Кэшируйте одинаковые состояния, добавьте таймаут и оставьте субтитры. Фраза NPC «дам 100 монет» не является серверной командой.

Как изучить тему в Кодике

В Кодике сначала изучите обычного NPC: Model, Head, ProximityPrompt, события и свойства. Затем разберите pcall и серверные таблицы состояния. После этого подключите отдельно TTS и отдельно TextGenerator. Только когда оба компонента работают по одному, соединяйте их фильтрованной строкой.

ШагЧто изучитьПроверяемый результат
1Instances и пути ExplorerНайти все шесть объектов NPC
2События LuauПоказать статическую реплику по prompt
3pcall и fallbackПережить искусственную ошибку
4TextService и безопасностьПоказать только фильтрованный текст
5AudioTextToSpeechОзвучить тот же субтитр

В курсе Lua / Luau повторите функции, условия и события, затем соберите статического гида без генеративного API. В Кодике полезно нарисовать цепочку от Triggered до Play и подписать, на каком шаге появляется пользовательский контент и где он фильтруется.

GeneratedText сразу показывается игроку

Любой сгенерированный текст должен пройти обязательную фильтрацию Roblox.

Голос и субтитр получают разные строки

Используйте один результат после TextService для обоих каналов.

Генерация запускается на Touched без debounce

Запросы дублируются, расходуют лимит и перекрывают звук.

Модель определяет награду квеста

Игровые правила и прогресс остаются в проверяемом серверном коде.

Сверьтесь с первичным источником. Команды, API и ограничения примера проверяйте по официальной документации Roblox по natural language API. Если интерфейс или версия изменились, первичная документация важнее скриншота из старой инструкции.

Что получится в итоге

Готовый результат: Как сделать NPC с ИИ-диалогом и голосом в Roblox Studio
NPC показывает отфильтрованную подсказку над головой и произносит ту же строку в 3D-пространстве, сохраняя рабочий fallback при сбое AI.

Короткие ответы
Можно ли сразу показать GeneratedText?

Нет. Roblox требует обработать сгенерированный текст через TextService:FilterStringAsync.

Зачем нужен FALLBACK?

Генерация, фильтрация или TTS могут быть недоступны. Основной игровой сценарий должен продолжаться.

Должна ли модель решать, сколько монет выдать?

Нет. Она формулирует реплику, а правила и награды определяет серверный код.

Как понять, что проект действительно работает?

Проверьте основной сценарий, ошибочный ввод, повторный запуск и один граничный случай. Затем объясните вслух, где появляются данные, кто принимает решение и где хранится состояние.

Можно ли начать с готового кода из статьи?

Да. После первого запуска измените один параметр, добавьте одну проверку и повторите проект без подсказки. Так пример превращается в собственный навык.

Сначала надёжный NPC, потом вариативный характер

События, функции и серверную логику изучите в курсе Lua / Luau. Для первого персонажа полезны границы клиента и сервера и работа с Output.

Если хотите ускорить сборку объектов, сначала прочитайте как подключить Studio MCP. В Кодике повторите статический prompt и TTS, затем добавьте генерацию последним шагом.