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

Сохранение монет между входами

Создайте Coins в таблице игроков и сохраните значение через DataStoreService.

Иллюстрация: Сохранение монет между входами
🎯 Что получится

У каждого игрока появляются Coins. При возвращении значение загружается из DataStore; изменения периодически сохраняются и при выходе тоже.

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

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

Опубликуйте отдельную тестовую игру Roblox (File → Publish to Roblox). В Studio включите Game Settings → Security → Enable Studio Access to API Services только для тестовой игры.
В ServerScriptService создайте ОДИН обычный Script с кодом. Удалите другие скрипты, которые создают leaderstats.Coins или сохраняют те же монеты.
Запустите Play, дождитесь появления Coins в таблице игроков, соберите монеты, выйдите и зайдите снова. Проверьте сообщения в Output при временной недоступности DataStore.
Эта учебная реализация повторяет загрузку и запись до трёх раз, не выдаёт 0 при ошибке загрузки и не запускает параллельные сохранения одного игрока на сервере.
ВАЖНО: для публичной многосерверной игры необходима отдельная система блокировки сессий. Без неё два сервера могут перезаписать прогресс друг друга.

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

Script
-- Единственный Script монет в ServerScriptService
local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local store = DataStoreService:GetDataStore("IgroCoins_v1")
local AUTOSAVE = 60
local loaded, saving = {}, {}

local function tryLoad(key)
    for attempt = 1, 3 do
        local ok, value = pcall(function() return store:GetAsync(key) end)
        if ok then return true, value end
        warn("Загрузка монет: попытка " .. attempt .. " не удалась: " .. tostring(value))
        if attempt < 3 then task.wait(attempt * 2) end
    end
    return false, nil
end

local function save(player)
    if not loaded[player] then return false end
    -- Не допускаем одновременной записи для одного игрока на этом сервере.
    while saving[player] do task.wait(0.1) end
    saving[player] = true
    local stats = player:FindFirstChild("leaderstats")
    local coins = stats and stats:FindFirstChild("Coins")
    if not coins then saving[player] = nil; return false end
    local value = math.clamp(math.floor(coins.Value), 0, 2000000000)
    local key = "coins_" .. player.UserId
    local success = false
    for attempt = 1, 3 do
        local ok, err = pcall(function()
            store:UpdateAsync(key, function(_old) return value end)
        end)
        if ok then success = true; break end
        warn("Сохранение монет: попытка " .. attempt .. ": " .. tostring(err))
        if attempt < 3 then task.wait(attempt * 2) end
    end
    saving[player] = nil
    return success
end

Players.PlayerAdded:Connect(function(player)
    local ok, value = tryLoad("coins_" .. player.UserId)
    if not ok then
        player:Kick("Не удалось загрузить монеты. Попробуйте войти позже.")
        return -- Нельзя заменять неизвестное сохранение нулём.
    end
    if not player.Parent then return end
    local stats = Instance.new("Folder")
    stats.Name = "leaderstats"
    local coins = Instance.new("IntValue")
    coins.Name = "Coins"
    coins.Value = typeof(value) == "number" and math.clamp(math.floor(value), 0, 2000000000) or 0
    coins.Parent = stats
    stats.Parent = player
    loaded[player] = true
end)

Players.PlayerRemoving:Connect(function(player)
    save(player)
    loaded[player] = nil
end)

task.spawn(function()
    while true do
        task.wait(AUTOSAVE)
        for _, player in ipairs(Players:GetPlayers()) do
            task.spawn(save, player)
        end
    end
end)

game:BindToClose(function()
    local pending = 0
    for _, player in ipairs(Players:GetPlayers()) do
        pending += 1
        task.spawn(function()
            save(player)
            pending -= 1
        end)
    end
    local started = os.clock()
    while pending > 0 and os.clock() - started < 25 do task.wait(0.2) end
end)

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

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

Ваш прогресс

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

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

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

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

Измените AUTOSAVE на 90 секунд и проверьте, что монеты сохраняются.

2. Улучшите

Добавьте награду за найденный сундук из соседней практики.

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

Создайте три игровых достижения, оплачиваемых монетами.

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

Какой сервис Roblox используют для сохранения монет между посещениями?

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

Если монеты не загружаются, проверьте публикацию игры и API Services в Studio. При ошибке загрузки игрок отключается, чтобы случайно не перезаписать накопления нулём. Не запускайте два скрипта сохранения с одним ключом DataStore. Для многосерверного релиза нужен session locking.