How to store vehicles in roblox datastore

You can write your topic however you want, but you need to answer these questions:

  1. What do you want to achieve? To store vehicles in datastore

  2. What is the issue? When I have example 2 vehicles to save it always load one so I believe problem is in game.Players.PlayerAdded section

  3. What solutions have you tried so far? I’ve tried looking but found nothing

local data = game:GetService("DataStoreService") local coll = data:GetDataStore("HIDDEN")

game.Players.PlayerAdded:Connect(function(plr)
	local a = Instance.new("Folder",plr)
	a.Name = "CarLeaderstats"
	local b = coll:GetAsync(plr.UserId)
	for i,v in pairs(b) do
		local instance = Instance.new("StringValue",a)
		instance.Name = i
		instance.Value = v
	end
end)

game.Players.PlayerRemoving:Connect(function(plr)
	local a = plr:WaitForChild("CarLeaderstats")
	for _,v in pairs(a:GetChildren()) do
		local it = {}
		it[v.Name] = v.Value;
		coll:SetAsync(plr.UserId,it)
	end
end)

What is the v value? It would be easier if you named your variables according to what they are.

If that v value isn’t needed, try switching your code with this and test it:

--//Services
local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")

--//Variables
local CarDataStore = DataStoreService:GetDataStore("CarDataStore")

--//Functions
local function OnPlayerRemoving(player)
	local carStorage = player:FindFirstChild("CarStorage")
	
	if not carStorage then
		return
	end
	
	local dataTable = {}
	
	for i, carValue in ipairs(carStorage:GetChildren()) do
		table.insert(dataTable, carValue.Name)
	end
	
	local success, errorMessage = pcall(CarDataStore.SetAsync, CarDataStore, player.UserId, dataTable)
	
	if not success then
		warn(errorMessage)
	end
end

Players.PlayerAdded:Connect(function(player)
	local carData = Instance.new("Folder")
	carData.Name = "CarData"
	carData.Parent = player

	local data = CarDataStore:GetAsync(player.UserId) or {}
	
	for i, carName in ipairs(data) do
		local carValue = Instance.new("StringValue")
		carValue.Name = carName
		carValue.Parent = player
	end
end)

Players.PlayerRemoving:Connect(OnPlayerRemoving)

game:BindToClose(function()
	for i, player in ipairs(Players:GetPlayers()) do
		task.spawn(OnPlayerRemoving, player)
	end
end)

carValue.Parent = carData?

I think you can remove the ipairs.


The code should have been solved in the previous post. However, the reason why your code won’t work is because you are saving two cars to the same datastore key, like this:

  • Save Car 1 to 646511225
  • Save Car 2 to 646511225

The value of 646511225, or the userId, becomes overwritten every time you write to it. However, it seems like a table is created here:

the issue is that it is defined in the loop, so the value will be overwritten. To potentially fix this, you can place the SetAsync function and the local it = {} outside of the loop. SetAsync will go after the loop, and the variable will go before.

Now, after that issue is fixed, your code should work fine. However, it isn’t the most optimized. Here’s some problem areas:

You are not indexing a dictionary. ipairs or nothing should be used instead.

The 2nd parameter to the Instance.new constructor negatively impacts performance. You should parent the instance after setting all the properties to it.

Should be wrapped in a pcall or xpcall so you can potentially retry this operation if it fails.

Hiding data store names is not necessary. No security risks are imposed by doing so.

Don’t worry, you are safe either way.

Due to these optimization issues, I recommend the above solution, since it not only provides the fixes I described, but also includes the optimizations I mentioned.


Though, I do have one question. Why is this task.spawn?

The only problem I see with using task.spawn is that it will not yield the BindToClose callback, therefore closing the game with potential data changes being processed. If this is the case and data loss does occur, a simple fix is to verify the data by checking it with GetAsync. For me, at least, this has proven to prevent 90% of data loss, while 10% were older cached versions of the data store (due to the internal 6-second cache timer in DataStoreService).


With your current system, I think you should refactor this to a more general approach, so you could potentially save other items with the same data store, which will be more efficient than using a separate one.

Wich v value you mean? The one in padded or premoved?

I figured it out after spending 3 hours looking at the code and thinking

local data = game:GetService("DataStoreService") local coll = data:GetDataStore("HIDDEN")

game.Players.PlayerAdded:Connect(function(plr)
	local a = Instance.new("Folder",plr)
	a.Name = "CarLeaderstats"
	local b = coll:GetAsync(plr.UserId)
	for i,v in pairs(b) do
		local instance = Instance.new("StringValue")
		instance.Parent = a
		instance.Name = i
		instance.Value = v
	end
end)

game.Players.PlayerRemoving:Connect(function(plr)
	local a = plr:WaitForChild("CarLeaderstats")
	local it = {}
	for _,v in pairs(a:GetChildren()) do
		it[v.Name] = v.Value;
	end
	coll:SetAsync(plr.UserId,it)
end)