Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
✓ ANSWER ACCEPTED

I am having issue with datastore service. Ideas?

I am having trouble saving data. When I run it states "Unable to cast value to function".

local DataStoreService = game:GetService("DataStoreService")
local PointsStore = DataStoreService:GetDataStore("PointsStore")

local SaveLoop =  coroutine.create(function(plr)
	while true do
		wait(120)
		PointsStore:UpdateAsync(plr.UserId,plr.leaderstats.Points.Value)
	end
end)

game.Players.PlayerAdded:Connect(function(player)
	
	local leaderstats = Instance.new("Folder",player)
	leaderstats.Name = "leaderstats"
	
	local Points = Instance.new("IntValue",leaderstats)
	Points.Name = "Points"

	Points.Value = PointsStore:GetAsync(player.UserId.."-Points") or 0
	
	coroutine.resume(SaveLoop,player)
end)

game.Players.PlayerRemoving:Connect(function(player)
	PointsStore:UpdateAsync(player.UserId.."-Points",player.leaderstats.Points.Value)
end)

1 comment

0

Do you think you could use print statements to find where this error derives from? Also, you seem to be overusing UpdateAsync in my experience.

1 answer

✓ Accepted answer

:UpdateAsync() takes a function, not the value to update the data store with. Note that, if the passted function does not return or it returns nil, the update is cancelled. The function cannot yield either, so do not call wait() ,event:Wait(), etc

PointsStore:UpdateAsync(player.UserId .. "-Points", function(prev) -- prev is the previousvalue
	return player.leaderstats.Points.Value
end)

Also, why are you using coroutines like this? You should just move your while loop to the bottom of your script. Additionally, Instance.new's second argument is deprecated. Set all the properties of an object first, and then parent.

local Players = game:GetService("Players") -- Stay consistent! Why call :GetService() on DataStoreService and not Players? Why not have a variable for Players as well?
local DataStoreService = game:GetService("DataStoreService")
local PointsStore = DataStoreService:GetDataStore("PointsStore")

Players.PlayerAdded:Connect(function(player)
	local success, points = pcall(PointsStore.GetAsync, PointsStore, player.UserId .. "-Points") -- wrap web requests (data stores, http requests, etc) in pcalls
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = player

	local Points = Instance.new("IntValue")
	Points.Name = "Points"
	Points.Value = success and points or 0
	Points.Parent = leaderstats
end)

Players.PlayerRemoving:Connect(function(player)
	PointsStore:UpdateAsync(player.UserId .. "-Points", function(prev)
		return player.leaderstats.Points.Value
	end)
end)

game:BindToClose(function()
	--[[
		When a server is shutting down,
		it focuses only on shutting down,
		so your PlayerRemoving event listener will not be called. 
		You should save on BindToClose as well.
	--]]

	local playersInGame = Players:GetPlayers()
	
	for _, player in ipairs(playersInGame) do
		spawn(function()
			PointsStore:UpdateAsync(player.UserId .. "-Points", function(prev)
				return player.leaderstats.Points.Value
			end)
		end)
	end
end)

2 comments

0

y u not using the prev parameter

0

thanks incapaxian

This discussion is preserved as it was. New answers, comments, and votes are closed.