← Все практические скрипты
Задания · Продвинутый · 35 мин

Задание от NPC: соберите 5 кристаллов

NPC выдаёт задание, считает находки и награждает монетами.

Иллюстрация: Задание от NPC: соберите 5 кристаллов
🎯 Что получится

NPC запускает личное задание игрока. Каждый кристалл засчитывается один раз; за пять кристаллов выдаётся 30 монет. Другие игроки могут собирать те же кристаллы.

1. Подготовьте объект

Где разместить: Обычный Script в ServerScriptService

В Workspace создайте Folder QuestCrystals и поместите туда пять или более отдельных Part. Установите Anchored = true, CanTouch = true и CanCollide = false.
Создайте модель NPC с Humanoid и Head (через Rig Builder), назовите её QuestNPC.
В ServerScriptService создайте Script QuestCrystalsServer, а в StarterPlayer → StarterPlayerScripts создайте LocalScript QuestCrystalsClient. Вставьте каждый блок кода в соответствующий файл.
Добавьте одну систему leaderstats.Coins (например, из практики сохранения монет).
В Play поговорите с NPC через E, коснитесь пяти разных кристаллов и вернитесь. Сообщения появятся на экране игрока.

Карта файлов в Explorer

Это пути для скриптов из блоков кода ниже. Остальные объекты создайте по инструкции.

├── ServerScriptService
│   └── QuestCrystalsServer (Script)
└── StarterPlayer
    └── StarterPlayerScripts
        └── QuestCrystalsClient (LocalScript)

2. Вставьте код

ServerScriptService/QuestCrystalsServer (Script)
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local crystals = workspace:WaitForChild("QuestCrystals")
local npc = workspace:WaitForChild("QuestNPC")
local head = npc:WaitForChild("Head")
local prompt = head:FindFirstChildOfClass("ProximityPrompt") or Instance.new("ProximityPrompt")
prompt.ActionText = "Взять / сдать задание"
prompt.ObjectText = "Хранитель кристаллов"
prompt.MaxActivationDistance = 10
prompt.Parent = head
local event = ReplicatedStorage:FindFirstChild("IgroQuestNotice") or Instance.new("RemoteEvent")
event.Name = "IgroQuestNotice"
event.Parent = ReplicatedStorage
local TARGET, REWARD = 5, 30
local states = {}
local function stateFor(player)
    if not states[player] then states[player] = {active = false, count = 0, seen = {}} end
    return states[player]
end
local function notice(player, message)
    event:FireClient(player, message)
end
prompt.Triggered:Connect(function(player)
    local state = stateFor(player)
    if not state.active then
        state.active, state.count, state.seen = true, 0, {}
        notice(player, "Задание: соберите " .. TARGET .. " разных кристаллов!")
    elseif state.count >= TARGET then
        local stats = player:FindFirstChild("leaderstats")
        local coins = stats and stats:FindFirstChild("Coins")
        if not coins then
            notice(player, "Задание выполнено, но для награды нужен leaderstats.Coins. Вернитесь позже!")
            return -- Сохраняем выполненное задание, пока нет Coins.
        end
        coins.Value += REWARD
        state.active, state.count, state.seen = false, 0, {}
        notice(player, "Отлично! Вы получили " .. REWARD .. " монет!")
    else
        notice(player, "Собрано: " .. state.count .. " из " .. TARGET)
    end
end)
local function connectCrystal(part)
    if not part:IsA("BasePart") then return end
    part.Touched:Connect(function(hit)
        local character = hit:FindFirstAncestorOfClass("Model")
        local player = character and Players:GetPlayerFromCharacter(character)
        local humanoid = character and character:FindFirstChildOfClass("Humanoid")
        if not player or not humanoid or humanoid.Health <= 0 then return end
        local state = stateFor(player)
        if not state.active or state.seen[part] or state.count >= TARGET then return end
        state.seen[part] = true
        state.count += 1
        notice(player, "Кристаллы: " .. state.count .. "/" .. TARGET)
    end)
end
for _, child in ipairs(crystals:GetChildren()) do connectCrystal(child) end
crystals.ChildAdded:Connect(connectCrystal)
Players.PlayerRemoving:Connect(function(player) states[player] = nil end)
StarterPlayer/StarterPlayerScripts/QuestCrystalsClient (LocalScript)
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local player = Players.LocalPlayer
local event = ReplicatedStorage:WaitForChild("IgroQuestNotice")
local gui = Instance.new("ScreenGui")
gui.Name = "IgroQuestMessages"
gui.ResetOnSpawn = false
gui.Parent = player:WaitForChild("PlayerGui")
local label = Instance.new("TextLabel")
label.Size = UDim2.fromScale(0.75, 0.13)
label.Position = UDim2.fromScale(0.125, 0.18)
label.BackgroundColor3 = Color3.fromRGB(24, 45, 65)
label.TextColor3 = Color3.fromRGB(255, 255, 255)
label.TextScaled = true
label.TextWrapped = true
label.Visible = false
label.Parent = gui
local serial = 0
event.OnClientEvent:Connect(function(message)
    serial += 1
    local current = serial
    label.Text = tostring(message)
    label.Visible = true
    task.delay(4, function()
        if current == serial then label.Visible = false end
    end)
end)

3. Проверьте в игре

Нажмите Play в Roblox Studio и проверьте действие механики. Если механика не работает, откройте окно Output и проверьте тип скрипта, его расположение и названия объектов.

Ваш прогресс

Когда проверите механику в Roblox Studio, отметьте практику как выполненную. Отметка хранится только в этом браузере, не в личном кабинете.

Если объединяете несколько скриптов

Добавляйте механики по одной и проверяйте окно Output. Не создавайте несколько одинаковых систем монет или интерфейсов; скрипты, меняющие WalkSpeed, прыжок или освещение, могут влиять друг на друга.

⭐ Три шага к собственной игре
1. Повторите и измените

Измените цель TARGET с 5 на 3 и награду REWARD с 30 на 50.

2. Улучшите

Добавьте ещё пять кристаллов и разместите их на разных высотах.

3. Придумайте своё

Придумайте три зоны поиска с разной сложностью и наградами.

4. Проверьте себя

Почему прогресс сбора кристаллов нужно хранить отдельно для каждого игрока?

🛠 Если не работает

В Workspace должны быть QuestNPC с Head и папка QuestCrystals с деталями. Для монет необходим урок «Сохранение монет». Сообщения показываются в Output, а не в игровом интерфейсе.