Saver. Маленькая заметка. Сохранение и загрузка данных

Для первой игры использовал собственные решения, чтоб прочувствовать на кончиках. Затем пошел искать готовое расширения и нашел Saver.

Saver - библиотека для сохранения и загрузки сохраненных данных в проектах Defold

Ключевые функции для новичка:

  • удобный API относительно собственного костыльного решения и куча доп функций в придачу)))
  • автосохранение каждые n секунд
  • можно хранить данные в lua и json

И куча других классных функций: GitHub - Insality/defold-saver: Defold Save File Manager · GitHub

добавляем зависимость и создаем базовый скрипт

Добавляем расширение: game.project → project → dependencies → плюсик и добавляем строчку.

https://github.com/Insality/defold-saver/archive/refs/tags/5.zip

создаем скрипт и привязываем к го

# ASSETS 
- создать game.script

# OUTLINE
- создать go
- правая кнопка мыши по go, add component file и добавляем game.script

базовое применение

local saver = require("saver.saver")

local function save(self)
	-- делаем что-то с данными STATE, убираем ID/форматируем
	print('произошел вызов функции!')
end

local STATE = {}

function init(self)
	-- инициализация расширения
	saver.init({
		save_name = "game.lua", -- название файла, можно выбрать JSON game.json или автоматический выбор или lua
		save_folder = "DEFOLD", -- путь /Users/USER_NAME/Library/Application Support/DEFOLD/game.lua
		utosave_timer = 7, -- автосохранение в секунду
	})
	-- Биндим состояние: свяжет + перезапишет поле STATE
	saver.bind_save_state("game", STATE)

	-- путь до файла в файловой системе
	local res= saver.get_save_path("game.lua")
	print(res)

	-- если у вас особые данные, требующие отформатирования перед использвоанием
	-- например, храним данные в JSON, а у вас таблица с ID гошек
	-- в JSON нельзя хранить ID
	-- и поэтому парсим перед сохранением таблицу, удаляя ID 
	saver.before_save_callback = function() 
		save(self)
	end

	-- есть get/set
	-- не сохранятся вместе со STATE
	-- предположу, что нужен для данных, 
	-- не требующих сохранения, но удобно иметь доступ к переменным во всем приложении
	saver.set_value("name","alice")
	print(saver.get_value("name")) -- alice

	-- если не хочется ждать автосохранения, можно сохранять сразу
	saver.save_game_state()
	-- получить весь слепок для отладки:
	pprint(saver.get_game_state())
end

как проверить пустое ли хранилище

local function is_empty_table(t)
	return type(t) == "table" and next(t) == nil
end
if is_empty_table(STATE) == true then
	-- если таблица пустая
else 
	-- STATE с даннными
end

как я использовал

local STORE = {}
-- можно сохранять данные в переменные
local function restore_from_save(self)
	self.current    = STATE.current or 1
	self.score      = STATE.score or 0
end

-- сохраняем в STATE из локальных переменных
local function save(self)
	STATE.current           = self.current
	STATE.score             = self.score 
end

return _dump_board_to_save

local function is_empty_table(t)
	return type(t) == "table" and next(t) == nil
end

function init(self)
	-- инициализируем
	restore_from_save(self)
	saver.init({
		save_name = "game.lua",
	})
	-- Биндим состояние:= свяжет + перезапишет поле STATE
	saver.bind_save_state("game", STATE)
	
	if is_empty_table(STATE) == true then
		-- если таблица пустая
		-- можем настроить переменные допустим
		self.current = 1
		self.maxCurrent = 10
	else 
		-- делаем данными STATE переменные в self.current, self.score
		-- зачем? если имеется длинная цепочка данных
		-- чтоб каждый раз не менять STATE.current и тд
		-- и не дергать сохранение
		-- мы делаем их локальными
		restore_from_save(self)
	end
	
	-- сохраняем в STATE из локальных переменных
	save(self)
end

а как вы делаете сохранение в играх?

2 Likes

Я ещё ни разу не делал сохранения в играх, воспользуюсь твоей заметкой на днях!

Спасибо, что делишься знанием и опытом!