Особняк Чуда (Продовження)

Цей курс розповість про розробку керованого навчального посібника за допомогою початкового шаблону. Крім того, ви можете використати власний проект, оскільки готову навчальну систему можна застосувати до будь-якого досвіду.
Початкове місце для цієї серії включає частини тематичної гри в парк розваг, де гравці збирають квитки за приз. Нові гравці будуть направлені до кабінок, щоб отримати квитки.

Імпортування шаблону

Відкрийте початкове місце Build It Play It - Boardwalk . На новій веб-сторінці натисніть кнопку ... і виберіть Редагувати . Якщо буде запропоновано, дозвольте своєму браузеру відкрити Roblox.
Відкриється новий екземпляр Studio з вкладкою. Перше, що ви побачите, це об’єкт TestPlayer, який імітує гравця.

Використання власного проекту

Якщо ви використовуєте власний проект, використовуйте основні дії, які виконуватимуть ваші гравці під час досвіду. Наприклад, у грі про фермерство попросіть гравців зібрати пшеницю для продажу на кіоску магазину.

Крім того, ми рекомендуємо наступне:

Імпортувати файли — імпортувати початкові об’єкти Boardwalk у робочу область проекту за допомогою інвентарю. Це включає в себе квиткові кабіни з ProximityPrompts і TestPlayer.


Дотримуйтесь курсу та адаптуйтеся - коли закінчите, замініть готові моделі на власні. Майте на увазі, що вам може знадобитися перейменувати деякі посилання на змінні в сценаріях.

Шаблон

Місце включає дві інтерактивні кабіни з ProximityPrompts, які є об’єктами, які запускають сценарії, коли гравці взаємодіють із чимось у шаблоні. Під час уроку гравці будуть взаємодіяти з кожною кабінкою, щоб збирати квитки та розвивати посібник. Зверніть увагу, що всі частини, крім кабіни та тестового гравця, заблоковані.

Балки/Промені (Beam) та кріплення

Щоб направляти гравців до кабінок за квитками, ви створите шлях за допомогою балок, як у відео нижче.

Промені — це об’єкти, які також використовуються для таких ефектів, як лазери або силові поля. Цей об’єкт малює текстуру між двома точками з настроюваними властивостями, такими як швидкість, ширина та розмір кривої.

Щоб відобразити промінь, потрібні додатки для встановлення початкової та кінцевої точок променя. Ви вставите одне прикріплення до гравця, а інше прикріплення до об’єкта воріт.

У провіднику знайдіть TestPlayer і додайте вкладення під назвою PlayerAttachment.
У розділі TestPlayer додайте Beam під назвою TutorialBeam. Майте на увазі, що промінь не буде видно, доки його початкову та кінцеву точки не буде встановлено пізніше.
Знайдіть папку TutorialGoals і розгорніть її. Під обома об’єктами InteractionPart додайте вкладення під назвою GoalAttachment.

Підключення променя (Beam)

Тепер, коли ви зробили прикріплення, настав час підключити їх до балки, щоб можна було показати текстуру.

У розділі TestPlayer виберіть TutorialBeam. У Властивості знайдіть Attachment0 . Натисніть порожнє поле праворуч від властивості. Потім у Провіднику знайдіть TestPlayer і натисніть PlayerAttachment .


У властивостях TutorialBeam встановіть Attachment1 на вкладення, яке ви створили в GoalPart1, GoalAttachment.

Регулювання променя

За замовчуванням промінь не завжди спрямований до камери. Це може призвести до ситуацій, коли гравці не зможуть побачити промінь під різними кутами. Це можна виправити, увімкнувши властивість під назвою FaceCamera.
FaceCamera вимкнено
FaceCamera увімкнено

Зробіть промінь видимим у будь-якому місці, увійшовши у властивості променя та ввімкнувши FaceCamera.
Після завершення ви побачите білий промінь між гравцем і воротами, незалежно від кута камери.

Зображення, що відображається вздовж променя, можна налаштувати, змінивши його 2D текстуру. Крім того, балки мають різноманітні візуальні параметри, такі як текстура, колір, рух, які можна змінювати.

Щоб направляти стрілки вздовж променя, як у прикладі, скопіюйте 5886559421 і вставте його у властивість балки Texture .



Власні текстури можуть бути будь-якими зображеннями, які у вас є. Дізнайтеся, як завантажити їх, у статті про керування активами .


Прямо зараз текстура стріли розтягнута. Встановіть для TextureMode значення Static , щоб стрілка повторювалася у вихідному розмірі.
Якщо стрілка вказує не в правильному напрямку, вкладення можуть бути поміняні місцями. Переконайтеся, що Attachment0 підключається до PlayerAttachment, а Attachment1 — до GoalAttachment. Крім того, якщо ви використовуєте спеціальну текстуру, вам може знадобитися віддзеркалити зображення в програмі для редагування фотографій.

Змінюйте такі властивості променя, як Color, LightEmission і TextureSpeed, щоб створювати щось, що привертає увагу та виглядає привабливим. Нижче наведено лише один приклад.

Поради щодо вибору кольору

Колір — це одна з можливостей для покращення досвіду користувача вперше. Наприклад, контрастні або насичені кольори привертають більше уваги, завдяки чому гравцям легше інформувати, куди дивитися на екрані.

Крім того, під час проектування враховуйте доступність для ваших гравців. Деяким гравцям може бути важко побачити певні комбінації кольорів, тому важливо, щоб кольори подобалися найширшій аудиторії.

Використання частинок для дій

Після завершення стрілок гравці, які вперше грають у гру, можуть прослідкувати шлях до своєї мети, що зробить їх початковий вступ більш зрозумілим і зменшить ймовірність того, що вони заблукають і вийдуть. Щоб ще більше покращити досвід користувача, повідомте гравцям, що вони успішно виконали своє завдання, за допомогою привабливого ефекту частинок.

У наведеному нижче прикладі щоразу, коли гравці взаємодіють із кабінками, з’являється святковий вибух частинок у формі квитка.

Надання кількох форм зворотного зв’язку також є ще одним способом покращення взаємодії з гравцем. Гравець із вимкненим звуком або той, хто має проблеми зі слухом, може більше покладатися на візуальні сигнали. Інші гравці можуть мати слабкий зір і приділяти більше уваги звуку.

Створення частинок

При створенні частки її потрібно вставити в деталь або прикріплення. У цьому прикладі ви помістите частинки в об’єкт TestPlayer, який використовувався раніше.

У TestPlayer створіть ParticleEmitter під назвою Burst . Частинки за замовчуванням почнуть випромінювати об’єкт TestPlayer. Ви налаштуєте випромінювач, щоб створити ефект вибуху.

Приклад показано нижче.

Частинки повинні бути названі точно, оскільки сценарій шукатиме назву пізніше.
  1. У властивостях частинки Burst знайдіть Texture . Скопіюйте та вставте один із наведених нижче ідентифікаторів текстури або скористайтеся власним у поле текстури та натисніть Enter.

  2. 6772766862
    6772766551
    5857851618
    6803084085
    6772783963
    6703369286
    6749057157
    6772766413
    Якщо використовувати текстуру квитка, вона виглядатиме, як показано нижче.
    Власні текстури можуть бути будь-якими зображеннями, які у вас є. Дізнайтеся, як завантажити їх, у статті про керування активами .

    У властивостях TestPlayer знайдіть і змініть властивості «Колір» і «Розмір» на такі, що відповідають вашому досвіду.

  3. Приклад показано нижче.

Створення ефекту серії

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

Розповсюдження частинок

ParticleEmitter надсилає частинки вздовж двох площин, керованих властивістю SpreadAngle .Щоб змусити частинки розлітатися в усіх напрямках, як у прикладі, встановіть для SpreadAngle X і Y значення 360.

Різні властивості пакету

Після додавання рекомендованих значень частинки будуть виглядати так, ніби вони швидко вириваються з плеєра, як феєрверк.
Щоб отримати вибуховий рух, установіть ці властивості для наступних властивостей, щоб частинки вибухали, а потім швидко зникали.
ВласністьЗначенняОбґрунтування
LightEmission
(Світловепромінювання)
0,4Додає слабке сяйво. Зауважте, що максимум становить 1.
Drag (Перетягнути)8Більший опір змушує частинки швидко втрачати швидкість.
Lifetime   (Час життя)0,6, 1Змушує частинки існувати від 0,6 до 1 секунди.
Rate (Оцінка)50Скільки частинок випускається за секунду.
Speed (Швидкість)40З якою швидкістю рухаються частинки під час першого випромінювання.
Спробуйте додати кілька випадкових чисел, щоб частинки менш повторювалися. Деякі властивості, як-от Lifetime та Rotation, додають рандомізацію, допускаючи мінімальне та максимальне значення.

Нарешті, частка має відтворюватися лише тоді, коли сценарій (який ви побачите в наступному розділі) скаже їй це. Знайдіть властивість Enabled і вимкніть її.

Ця сторінка охоплює лише кілька властивостей. Щоб дізнатися більше, перегляньте довідкову статтю про випромінювачі частинок

Зберігання променя та частинок

Перш ніж додавати скрипти, промінь і частинки потрібно перемістити туди, де скрипти зможуть робити їх копії за потреби.

Якщо ви використовуєте власний проект, вам може знадобитися замінити значення в деяких сценарних змінних, щоб вони відповідали вашим об’єктам.

У ReplicatedStorage створіть нову папку під назвою PlayerTutorial . Перемістіть TutorialBeam із TestPlayer у нову папку.
У ServerStorage створіть папку під назвою TutorialParticles. Перемістіть частинку Burst із TestPlayer у цю папку.

Після переміщення променя та емітера частинок TestPlayer більше не потрібен. Видаліть TestPlayer, оскільки скрипт працюватиме з реальними гравцями після завершення.

Створення подій

Кожного разу, коли гравці взаємодіють із метою, сценарій навчального посібника повинен знати про це, щоб він міг оновлювати прогрес цього гравця та створювати ефект частинок. Щоб інформувати сценарії, сигнали можна надсилати за допомогою подій .

У ReplicatedStorage > PlayerTutorial створіть два об’єкти RemoteEvent . Назвіть їх NextGoal і TutorialEnd .

Додавання сценаріїв

Три сценарії, наведені нижче, шукатимуть створені раніше об’єкти емітер частинок і промінь і керуватимуть навчальною системою.

У ReplicatedStorage > PlayerTutorial > створіть новий ModuleScript під назвою TutorialManager.Замініть стандартний код, скопіювавши та вставивши весь код нижче.

local TutorialManager = {}

local ReplicatedStorage = game:GetService("ReplicatedStorage")

local tutorialFolder = ReplicatedStorage:WaitForChild("PlayerTutorial")
local TutorialEndEvent = tutorialFolder:WaitForChild("TutorialEnd")
local NextGoalEvent = tutorialFolder:WaitForChild("NextGoal")

-- Note Goal parts must be ordered in the table, or else Goal order may be different in-game
local goalParts = {
 workspace.TutorialGoals.GoalPart1,
 workspace.TutorialGoals.GoalPart2
}

local function checkTutorialEnd(player, goalParts)
 local currentIndex = player:WaitForChild("GoalProgress")
 return currentIndex.Value >= #goalParts
end

local function finishTutorial(player)
 local playerBeam = player.Character.HumanoidRootPart:FindFirstChildOfClass("Beam")
 playerBeam:Destroy()

 print(player.Name .. " finished the tutorial")

 -- Placeholder for further code. E.g. if you wanted to send messages to the server to do other tasks

end

function TutorialManager.interactGoal(player)
 NextGoalEvent:FireServer()
end

function TutorialManager.getTutorialGoals()
 return goalParts
end

function TutorialManager.nextGoal(player, goalParts)
 if checkTutorialEnd(player, goalParts) then
   finishTutorial(player)
 else
   -- Increment the player's Goal tracker
   local currentGoalIndex = player:WaitForChild("GoalProgress")
   currentGoalIndex.Value += 1
 end
end

-- Creates an int value to locally track player's progress through the tutorial Goals
function TutorialManager.setupPlayerProgress(player)
 local currentGoalProgress = Instance.new("IntValue")
 currentGoalProgress.Name = "GoalProgress"
 currentGoalProgress.Value = 1
 currentGoalProgress.Parent = player
end

return TutorialManager

Цей скрипт запускає код для керування прогресом гравця в підручнику. Сюди входять такі завдання, як запуск коду для взаємодії з цілями або те, що відбувається після завершення навчального посібника.

У ServerScriptService створіть новий сценарій під назвою TutorialParticles.Вставте код нижче.

local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerStorage = game:GetService("ServerStorage")

local tutorialFolder = ReplicatedStorage:WaitForChild("PlayerTutorial")
local NextGoalEvent = tutorialFolder:WaitForChild("NextGoal")

local EMIT_RATE = 50

local function playParticleBurst(player)
  local character = player.Character or player.CharacterAdded:Wait()
  local humanoidRootPart = character:WaitForChild("HumanoidRootPart")
  local particleAttachment = humanoidRootPart:WaitForChild("ParticleAttachment")

  -- Go through particles on the attachment and play them according to the type of particle
  for _, particle in particleAttachment:GetChildren() do
    if particle:IsA("ParticleEmitter") then
      particle:Emit(EMIT_RATE)
    end
  end
end

local function setupPlayerParticles(player)
  player.CharacterAdded:Connect(function(character)
    local humanoidRootPart = character:WaitForChild("HumanoidRootPart")
    local playerParticleAttachment = Instance.new("Attachment")
    playerParticleAttachment.Name = "ParticleAttachment"
    playerParticleAttachment.Parent = humanoidRootPart

    -- Clone particles in the folder, even if there are more than one and attach to player
    for _, emitter in ServerStorage.TutorialParticles:GetChildren() do
      emitter:Clone().Parent = playerParticleAttachment
    end
  end)
end

Players.PlayerAdded:Connect(setupPlayerParticles)
NextGoalEvent.OnServerEvent:Connect(playParticleBurst)

Цей сценарій відтворює вибухову частинку щоразу, коли гравці взаємодіють із цілями. Існує також змінна під назвою EMIT_RATE, яка визначає, скільки частинок породжується під час взаємодії.

У StarterPlayer > StarterPlayerScripts створіть новий LocalScript під назвою TutorialScript .

Потім вставте сценарій нижче. Цей сценарій створює та керує променем, який використовується для спрямування гравців.

local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local tutorialFolder = ReplicatedStorage:WaitForChild("PlayerTutorial")
local TutorialManager = require(tutorialFolder:WaitForChild("TutorialManager"))
local TutorialEndEvent = tutorialFolder:WaitForChild("TutorialEnd")

local player = Players.LocalPlayer
local goalParts = TutorialManager.getTutorialGoals()
local playerBeam = nil
local goalIndex = nil

local function getTargetAttachment()
  local currentTarget = goalParts[goalIndex.Value]
  local interactionPart = currentTarget:FindFirstChild("InteractionPart")
  local attachment = interactionPart and interactionPart:FindFirstChildOfClass("Attachment")

  if not attachment then
    attachment = Instance.new("Attachment")
    attachment.Name = "BeamAttachment"
    attachment.Parent = currentTarget
  end

  return attachment
end

local function updateBeamTarget()
  playerBeam = player.Character.HumanoidRootPart:FindFirstChildOfClass("Beam")

  local targetBeamAttachment = getTargetAttachment()

  if targetBeamAttachment then
    playerBeam.Attachment1 = targetBeamAttachment
  else
    warn("Attachment not found in a goal. Check that goals have attachments or they're included under the InteractionPart")
  end
end

local function setupGoals()
  for _, part in goalParts do
    local interactionPart = part:FindFirstChild("InteractionPart")
    local proximityPrompt = interactionPart and interactionPart:FindFirstChild("ProximityPrompt")

    if proximityPrompt then
      proximityPrompt.Triggered:Connect(function(player)
        proximityPrompt.Enabled = false
        TutorialManager.nextGoal(player, goalParts)
        TutorialManager.interactGoal(player)
      end)
    else
      warn("Proximity prompt not included in goal. Add one to each goal part under the InteractionPart")
    end
  end
end

local function createBeamForCharacter(character)
  local humanoidRootPart = character:WaitForChild("HumanoidRootPart")
  local playerBeamAttachment = Instance.new("Attachment")
  local beamTemplate = tutorialFolder:WaitForChild("TutorialBeam")

  if not beamTemplate then
    warn("Tutorial Beam not found in ReplicatedStorage")
  end

  playerBeamAttachment.Name = "BeamAttachment"
  playerBeamAttachment.Parent = humanoidRootPart

  local targetBeamAttachment = getTargetAttachment()

  playerBeam = beamTemplate:Clone()
  playerBeam.Attachment0 = playerBeamAttachment
  playerBeam.Attachment1 = targetBeamAttachment
  playerBeam.Parent = humanoidRootPart
  playerBeam.Enabled = true
end

local function setupPlayer()
  setupGoals()
  TutorialManager.setupPlayerProgress(player)
  goalIndex = player:WaitForChild("GoalProgress")

  player.CharacterAdded:Connect(createBeamForCharacter)
  if player.Character then
    createBeamForCharacter(player.Character)
  end
end

setupPlayer()
goalIndex.Changed:Connect(updateBeamTarget)

Відтворіть проект, щоб перевірити сценарії. Переходьте від кабінки до кабінки, використовуючи функцію взаємодії, щоб перевірити, чи працює код.

Поради щодо усунення несправностей

Проблема: частинки відтворюються, коли починається гра. Перейдіть до ServerStorage > Tutorial Particles > Burst. Позначте «Увімкнено», щоб вимкнено.

Проблема: попередження в компіляторі, як-от "нескінченний вихід". Оскільки сценарій шукає певні об’єкти в певних місцях, можливо, частину названо неправильно. Ще раз переконайтеся, що назва та розташування кожної частини в грі збігаються з посібником.

Переваги

Такі події, як TutorialEnd, можна використовувати для запуску інших сценаріїв. Наприклад, ви можете нагороджувати гравців спеціальним предметом, коли ця подія запускається.
Сценарій TutorialParticles може відтворювати кілька частинок одночасно. Ви можете додати більше частинок у ServerStorage/TutorialParticles для більш складних ефектів.

Обмеження

Прогрес гравця в посібнику не є постійним, тобто вам доведеться закодувати певний спосіб збереження цього прогресу. Щоб отримати вказівки, перегляньте статтю: Збереження даних.