Разработка / ROBLOX
Кнопка помощи в Roblox Studio: ПК, телефон и геймпад
Соберите отдельную локальную панель: безопасная область, AnchorPoint, перенос длинных строк, прокрутка и понятный возврат к игре. Точные свойства, оригинальный LocalScript и незаполненный план проверки.
Небольшая помощь, которую можно открыть и закрыть #
Представьте пустой учебный проект: игрок видит сцену и небольшую кнопку «Помощь». Нажатие открывает объяснение, кнопка «Закрыть» возвращает обзор. Это экранный интерфейс, а не подсказка возле предмета в мире. Здесь не нужны ProximityPrompt, серверная награда или проверка покупки. Мы изменяем только локальную видимость и положение текста.
Упражнение не меняет пять игр автора сайта. Читатель собирает собственную структуру в отдельном проекте Studio. Сначала запишите простой результат: помощь открывается, текст читается до конца, закрытие доступно каждым выбранным способом ввода. Красивый прямоугольник на широком мониторе ещё не доказывает эти три условия. Ниже есть начальные размеры и сценарии; результаты проверки нужно заполнить самостоятельно.
1. Постройте дерево с точными именами #
В StarterGui создайте ScreenGui HelpGui. В нём нужны TextButton HelpButton, Frame HelpPanel и обычный LocalScript HelpController. Внутри HelpButton создайте UISizeConstraint ButtonBounds. Внутри HelpPanel создайте UISizeConstraint PanelBounds, UIPadding PanelPadding, TextLabel Title, ScrollingFrame Body и три TextButton: ScrollUp, ScrollDown, CloseButton. В Body поместите TextLabel HelpText.
Не переводите эти имена вместе с видимыми надписями. Код ищет именно HelpPanel и Body, а не похожие названия. StarterGui служит исходным шаблоном; в игровом запуске интерфейс появляется в PlayerGui игрока. Поэтому смотреть только дерево режима редактирования недостаточно. При зависшем WaitForChild сравните имя и родителя, прежде чем менять размеры или переписывать событие.
2. Оставьте место системному интерфейсу #
Для HelpGui выберите ScreenInsets=CoreUISafeInsets и ClipToDeviceSafeArea=true. Включите Enabled. Для упражнения ResetOnSpawn=false сохраняет этот интерфейс при возрождении; это не сохранение прогресса между входами. Современная настройка безопасной области помогает учитывать системный интерфейс Roblox и область устройства. Не начинайте с универсального совета IgnoreGuiInset=true: он меняет поведение отступов и не решает каждую задачу.
Безопасная область не знает, где вы разместили свой таймер, карту или магазин. Она также не является автоматическим раздвиганием всех экранных элементов. Сначала используйте отдельный проект без собственной HUD, затем проверьте реальные соседние элементы будущего интерфейса. Если кнопку закрывает другой ScreenGui, изучайте порядок отображения и свои слои; уменьшение шрифта не исправляет чужое перекрытие.
3. Почему пример ставит помощь сверху по центру #
У HelpButton задайте AnchorPoint=(0.5,0), Position=(0.5,0,0,12), Size=(0.28,0,0,44). В ButtonBounds задайте MinSize=(96,44), MaxSize=(160,44). Это наша отправная точка внутри области HelpGui, а не оптимальные размеры для всех экранов. Горизонтальная координата привязана к середине контейнера, отступ сверху задан числом пикселей.
Редкую подсказку мы отделяем от нижних зон движения и прыжка на touch-экране. Верхнее нажатие может быть неудобно для частого действия, особенно на планшете. Поэтому это пример помощи, которую читают время от времени, а не новая боевая кнопка. Проверьте собственный верхний счётчик и чат. Если игрок должен открывать подсказку постоянно, пересмотрите расположение по наблюдениям реального устройства, сохраняя доступность управления.
4. Настройте панель, не растягивая её бесконечно #
У HelpPanel выберите AnchorPoint=(0.5,0.5), Position=(0.5,0,0.5,0), Size=(0.88,0,0.86,0), Visible=false. PanelBounds ограничивает MaxSize=(520,420), MinSize=(0,0). PanelPadding даёт по 12 пикселей со всех сторон. Scale отвечает за долю контейнера, Offset — за добавку в пикселях; четыре числа UDim2 нельзя считать четырьмя абсолютными координатами.
Центральный AnchorPoint удерживает центр при изменении размера. Ограничение ширины помогает не превратить короткую помощь в огромную полосу на мониторе. На узком экране панель становится меньше, поэтому её внутренности требуют отдельной проверки. Таблица содержит точные стартовые значения для оставшихся объектов. Если доступная высота слишком мала для заголовка и кнопок, измените композицию; ни UISizeConstraint, ни масштаб не гарантируют размещение в любом окне.
| Свойства объекта | Стартовые значения упражнения |
|---|---|
| HelpGui · ScreenGui | ScreenInsets=CoreUISafeInsets; ClipToDeviceSafeArea=true; Enabled=true; ResetOnSpawn=false; DisplayOrder=10; ZIndexBehavior=Sibling |
| HelpButton · TextButton | AnchorPoint=(0.5,0); Position=(0.5,0,0,12); Size=(0.28,0,0,44); Visible=true; Active=true; Selectable=true; ZIndex=2; TextSize=20; TextScaled=false; TextWrapped=true |
| ButtonBounds · UISizeConstraint | MinSize=(96,44); MaxSize=(160,44) |
| HelpPanel · Frame | AnchorPoint=(0.5,0.5); Position=(0.5,0,0.5,0); Size=(0.88,0,0.86,0); Visible=false; Active=false; Selectable=false; ZIndex=2; BackgroundColor3=(20,30,44); BackgroundTransparency=0; BorderSizePixel=0 |
| PanelBounds · UISizeConstraint | MinSize=(0,0); MaxSize=(520,420) |
| PanelPadding · UIPadding | PaddingLeft / Right / Top / Bottom = (0,12) |
| Title · TextLabel | Position=(0,0,0,0); Size=(1,0,0,28); TextSize=22; TextScaled=false; TextWrapped=false; BackgroundTransparency=1; Active=false; Selectable=false; ZIndex=3 |
| Body · ScrollingFrame | Position=(0,0,0,40); Size=(1,0,1,-96); CanvasSize=(0,0,0,0); AutomaticCanvasSize=Y; ScrollingDirection=Y; ScrollingEnabled=true; ScrollBarThickness=6; BackgroundTransparency=1; BorderSizePixel=0; Active=true; Selectable=false; ClipsDescendants=true; ZIndex=3 |
| HelpText · TextLabel | Position=(0,0,0,0); Size=(1,-12,0,0); AutomaticSize=Y; TextSize=18; TextWrapped=true; TextScaled=false; TextYAlignment=Top; BackgroundTransparency=1; Active=false; Selectable=false; ZIndex=4 |
| ScrollUp / ScrollDown / CloseButton · TextButton | AnchorPoint=(0,1); Position: (0,0,1,0) / (0.25,0,1,0) / (0.5,0,1,0); Size: (0.25,-6,0,40) / (0.25,-6,0,40) / (0.5,-6,0,40); Visible=true; Active=true; Selectable=true; TextSize=18; TextScaled=false; TextWrapped=true; ZIndex=3 |
| * | UDim2 = (XScale,XOffset,YScale,YOffset); AnchorPoint=Vector2(X,Y). Title/Body/HelpText: AnchorPoint=(0,0); Visible=true. |
| * | HelpButton/ScrollUp/ScrollDown/CloseButton: BackgroundColor3=(230,120,65); BackgroundTransparency=0; TextColor3=(20,25,30); BorderSizePixel=0; AutoButtonColor=true. |
| * | Title/HelpText: TextColor3=(245,247,250). Title.TextXAlignment=Center. HelpText.TextXAlignment=Left. HelpController.Enabled=true. |
5. Оставьте читаемый текст и отдельную прокрутку #
У HelpText используйте TextWrapped=true, TextScaled=false, TextSize=18 и AutomaticSize=Y. Ширина связана с Body, высота растёт по тексту. У Body выберите AutomaticCanvasSize=Y, CanvasSize=(0,0,0,0), ScrollingDirection=Y, ScrollingEnabled=true. Поле просмотра остаётся ограниченным; содержимое может быть выше него. Отдельные кнопки «Выше» и «Ниже» дают ещё один способ читать длинную подсказку.
Не заставляйте весь длинный абзац уменьшаться до едва заметных букв. Сначала сократите саму инструкцию: действие, ожидаемый результат, возврат. Затем проверьте длинный учебный вариант. Код не добавляет настоящее задание: текст можно заменить своим. У кнопок и заголовка оставьте короткие надписи; перенос тела не решает переполнение отдельной кнопки. Сверяйте последнюю строку, а не только красивое начало.
6. Выберите язык этого локального примера #
UI_LANGUAGE в коде принимает ru, en, de, es, zh или ar. Установите, например, "ru". Словарь меняет видимые подписи; HelpController и CloseButton остаются именами объектов. AutoLocalize=false делает выбранные строки явными. Это один настроенный язык упражнения на клиенте, а не готовый выбор языка каждого игрока в опубликованной игре.
Для арабского тело выравнивается вправо. Смешанный текст, числа, переносы и знак пунктуации всё равно проверяйте визуально. Немецкое «Schließen» и более длинная объясняющая фраза могут показать ошибку, которую не видно на коротком «Close». Пройдите все шесть вариантов в узком окне. Не расширяйте одну кнопку ценой исчезновения соседней. В настоящей локализации сохраняют смысл действия, проверяют шрифт и используют отдельную систему переводов.
7. Подключите один LocalScript #
Вставьте оригинальный код ниже в HelpController. Он получает подготовленные объекты, выбирает надписи, задаёт порядок выбора и подключает Activated. Основная операция setOpen меняет HelpPanel.Visible и HelpButton.Visible. Открытая панель скрывает кнопку открытия; закрытая показывает её снова. Здесь нет RemoteEvent, запроса к серверу или записи в DataStore.
GuiNavigationEnabled и AutoSelectGuiEnabled включены явно для отдельного упражнения. Это общие клиентские настройки навигации, поэтому в существующей игре их согласуют с уже работающими меню. Не вставляйте вторую копию обработчика ради исправления одного неверного имени. Наша панель не останавливает персонажа и не ставит серверную игру на паузу. Если нужно модальное меню с блокировкой управления, это отдельное поведение и отдельный тест.
local GuiService = game:GetService("GuiService")
local gui = script.Parent
local help = gui:WaitForChild("HelpButton")
local panel = gui:WaitForChild("HelpPanel")
local title = panel:WaitForChild("Title")
local body = panel:WaitForChild("Body")
local bodyText = body:WaitForChild("HelpText")
local up = panel:WaitForChild("ScrollUp")
local down = panel:WaitForChild("ScrollDown")
local close = panel:WaitForChild("CloseButton")
local UI_LANGUAGE = "en" -- One chosen language for this local exercise.
local labels = {
ru = {help="Помощь", title="Подсказка", up="Выше", down="Ниже", close="Закрыть", body="Это учебная панель. Прочитай подсказку и закрой её, чтобы снова видеть сцену. Здесь можно объяснить одно действие: что выбрать, какой результат ожидать и куда вернуться.\n\nЕсли текст не помещается, используй кнопки Выше и Ниже. Закрытие панели не завершает задание и не выдаёт награду."},
en = {help="Help", title="Quick help", up="Up", down="Down", close="Close", body="This is a practice panel. Read the hint and close it to see the scene again. Explain one action here: what to select, which result to expect and where to return.\n\nIf the text does not fit, use Up and Down. Closing the panel does not complete a task or grant a reward."},
de = {help="Hilfe", title="Kurze Hilfe", up="Hoch", down="Runter", close="Schließen", body="Dies ist ein Übungsfenster. Lies den Hinweis und schließe es, um die Szene wieder zu sehen. Erkläre hier eine Handlung: was auszuwählen ist, welches Ergebnis erwartet wird und wohin man zurückkehrt.\n\nWenn der Text nicht passt, nutze Hoch und Runter. Das Schließen erfüllt keine Aufgabe und vergibt keine Belohnung."},
es = {help="Ayuda", title="Ayuda breve", up="Arriba", down="Abajo", close="Cerrar", body="Este es un panel de práctica. Lee la indicación y ciérralo para volver a ver la escena. Explica una acción: qué seleccionar, qué resultado esperar y adónde regresar.\n\nSi el texto no cabe, usa Arriba y Abajo. Cerrar el panel no completa una misión ni entrega una recompensa."},
zh = {help="帮助", title="简短提示", up="上翻", down="下翻", close="关闭", body="这是练习面板。读完提示后关闭它,再次查看场景。这里可以解释一个动作:选择什么、预期结果是什么,以及之后回到哪里。\n\n如果文字显示不全,请使用上翻和下翻按钮。关闭面板不会完成任务,也不会发放奖励。"},
ar = {help="مساعدة", title="إرشاد قصير", up="أعلى", down="أسفل", close="إغلاق", body="هذه لوحة تدريب. اقرأ الإرشاد ثم أغلقها لرؤية المشهد مجدداً. اشرح فعلاً واحداً: ماذا يختار اللاعب، وما النتيجة المتوقعة، وإلى أين يعود.\n\nإذا لم يظهر النص كله، استخدم أعلى وأسفل. إغلاق اللوحة لا يكمل مهمة ولا يمنح مكافأة."},
}
local words = assert(labels[UI_LANGUAGE], "Unknown UI_LANGUAGE")
for object, key in {[help]="help", [title]="title", [up]="up", [down]="down", [close]="close", [bodyText]="body"} do
object.AutoLocalize = false
object.Text = words[key]
end
bodyText.TextXAlignment = UI_LANGUAGE == "ar" and Enum.TextXAlignment.Right or Enum.TextXAlignment.Left
GuiService.GuiNavigationEnabled = true
GuiService.AutoSelectGuiEnabled = true
help.SelectionOrder = 1
up.SelectionOrder = 2
down.SelectionOrder = 3
close.SelectionOrder = 4
up.NextSelectionRight = down
down.NextSelectionLeft = up
down.NextSelectionRight = close
close.NextSelectionLeft = down
panel.Visible = false
help.Visible = true
local function fromGamepad(input)
return input ~= nil and input.UserInputType.Name:match("^Gamepad") ~= nil
end
local function setOpen(open, controller)
local selected = GuiService.SelectedObject
panel.Visible = open
help.Visible = not open
if controller then
GuiService.SelectedObject = open and close or help
elseif selected == help or selected == up or selected == down or selected == close then
GuiService.SelectedObject = nil
end
end
local function scrollPage(direction)
local height = body.AbsoluteWindowSize.Y
local limit = math.max(0, body.AbsoluteCanvasSize.Y - height)
local nextY = math.clamp(body.CanvasPosition.Y + direction * height * 0.8, 0, limit)
body.CanvasPosition = Vector2.new(0, nextY)
end
help.Activated:Connect(function(input) setOpen(true, fromGamepad(input)) end)
close.Activated:Connect(function(input) setOpen(false, fromGamepad(input)) end)
up.Activated:Connect(function() scrollPage(-1) end)
down.Activated:Connect(function() scrollPage(1) end)8. Activated требует понятного пути к кнопке #
Activated подходит для клика мышью, экранного нажатия и активации выбранной GUI-кнопки геймпадом. Для контроллера сначала войдите в навигацию через Select, найдите выделенную «Помощь», затем нажмите и отпустите A. Нажатие A без выбранного GUI не обещает открытия. Selectable=true нужно у четырёх кнопок; фон и текст не должны перехватывать выбор.
После открытия контроллером код выбирает CloseButton. Влево можно перейти к ScrollDown, затем ScrollUp; вправо вернуться. Закрытие контроллером возвращает выбор на HelpButton. При мыши или touch мы не создаём новый фокус; если выбор оставался на нашей скрываемой кнопке, он очищается. Другие меню не должны внезапно получать новый выбор из-за обычного нажатия помощи. Это логика примера, которую ещё нужно испытать настоящим вводом.
9. Как работают кнопки чтения #
scrollPage берёт текущую высоту видимой области и смещает CanvasPosition примерно на 80 процентов этой высоты. Оставшееся перекрытие помогает найти продолжение строки. Значение ограничено от нуля до разницы между высотой содержимого и окна. Если прокрутка не нужна, предел равен нулю. Повторное нажатие не должно увести текст за конец.
Прокрутка остаётся локальной и не меняет текст или состояние задания. Мы не обещаем, что любой стик автоматически листает выбранный ScrollingFrame: отдельные кнопки дают явную цепочку выбора. На мыши можно дополнительно проверить колесо, на телефоне — движение внутри поля. После закрытия позиция чтения сохраняется до изменения этого интерфейса; код не сбрасывает CanvasPosition при каждом открытии. Если хотите возврат к началу, добавьте это как осознанное правило.
10. Сначала эмулятор, затем настоящий экран #
В Studio запустите Test/F5 с игроком. Run/F8 без персонажа не заменяет проверку игрового PlayerGui. Device Simulator полезен для размеров и ориентаций, Controller Emulator — для ранней проверки навигации. Названия меню могут быть локализованы. Сравните узкое и широкое представление, книжную и альбомную ориентации, короткий и длинный текст, открытое и закрытое состояние.
Затем проверьте телефон и обычный подключённый геймпад. На touch попробуйте идти и прыгать при закрытой помощи: кнопку не должно перекрывать управление. Откройте панель и найдите закрытие без поиска по углам. Эмулятор не измеряет удобство большого пальца на вашем устройстве и не является испытанием производительности телефона. Таблица ниже — незаполненный план; ожидания нельзя выдавать за уже наблюдавшиеся результаты.
| Сценарий | Ожидание | Устройство / версия / наблюдение |
|---|---|---|
| ПК, клик открыть и закрыть | Панель меняет видимость; новая GUI-выборка не создаётся | — |
| Телефон, узкий экран, обе ориентации | Помощь и закрытие доступны; управление не перекрыто | — |
| Каждый язык, длинный текст | Последняя строка достижима; соседние кнопки видны | — |
| Select → выбранная Help → A | Открытие, выбор Close; влево кнопки чтения, вправо возврат | — |
| Много нажатий Выше/Ниже | CanvasPosition не выходит за границы содержимого | — |
| Геймпад → мышь/touch, другой GUI | Старый выбор наших кнопок очищается; чужой выбор не присваивается | — |
| Закрытие, новое открытие, возрождение | Позиция чтения не сбрасывается этим кодом; ResetOnSpawn=false | — |
11. Исправляйте причину и записывайте границы проверки #
Если кнопки нет, проверьте Enabled, Visible, дерево PlayerGui и перекрытие. Если кнопка видна, но не работает, сравните LocalScript, имена, Active и Output. Если край текста исчез, проверьте ширину HelpText, AutomaticSize, AutomaticCanvasSize и возможность дойти до последней строки. Если геймпад молчит, сначала смотрите выделение, Selectable и GuiService.SelectedObject, а не заменяйте Activated мышиным событием.
Материал прошёл проверку структуры, XML собственных рисунков и синтаксиса Luau; отдельно проверена локальная модель переходов и ограничений прокрутки. Код не запускался в Studio, на телефоне или физическом контроллере. Сохраните версию упражнения и собственные наблюдения. Удачный результат — читаемая помощь с доступным возвратом; следующая версия может улучшать оформление, не смешивая его с серверным прогрессом.
Первоисточники
Roblox Creator Hub — Text & image buttonsScreenGui
ScreenInsets
Position and size UI objects
GuiObject
UDim2
GuiButton
GuiService
Scrolling frames
Studio testing modes