How can I create a datastore for attribute

How can I create a 2nd value by using attributes for my datastore so I can save 2 values?? The code here doesn’t work
Error I get (Dictionary is not a supported attribute type) When I click on it, it brings me to this line.

CarUnknown:SetAttribute(“Cars”, string)

game.Players.PlayerAdded:Connect(function(plr)
	
	local players = game:GetService("Players")
	local dataStore = game:GetService("DataStoreService")
	local Data = dataStore:GetDataStore("Data")
	local finder = workspace:WaitForChild(plr.Name.."'s Car")
	local NameCar = finder.CarName.Value
	
	local folder = Instance.new("Folder")
	folder.Name = "Car"
	folder.Parent = plr
	
	local CarUnknown = Instance.new("StringValue")
	CarUnknown.Name = finder.CarName.Value
	CarUnknown.Parent = plr.Car
	CarUnknown.Value = Data:GetAsync(plr.UserId) or ""   
	Data:SetAsync(plr.UserId, CarUnknown.Value)
	CarUnknown:SetAttribute("Cars", string)
	CarUnknown.Cars = Data:GetAsync(plr.UserId) or ""
	Data:SetAsync(plr.UserId, CarUnknown.Value)
	
	CarUnknown.Changed:Connect(function()
		Data:SetAsync(plr.UserId, CarUnknown.Value)
		
	end)
end)
	
	
4 Likes

Instead of saving just the Value, you can save a dictionary like so:

local Data = {
	['Car'] = Whatever,
	['Attribute'] = Whatever
}

The “Attribute” key is to be named whatever attribute you have set, if you have various attributes, just add more of the attribute indexes.

2 Likes

[Sorry for late response]
Hi, how would I save a dictionary this my first time doing a data table.
This is what I’ve tried so far.

game.Players.PlayerAdded:Connect(function(plr)

	local players = game:GetService("Players")
	local dataStore = game:GetService("DataStoreService")
	local Data = dataStore:GetDataStore("Data")
	
	local folder = Instance.new("Folder")
	folder.Name = "Car"
	folder.Parent = plr

	local CarUnknown = Instance.new("StringValue")
	CarUnknown.Name = "."
	CarUnknown.Parent = plr.Car
	local Data = {
		['Car'] = CarUnknown ,
		['Attribute'] = Data
	}

	CarUnknown.Changed:Connect(function()
		Data:SetAsync(plr.UserId, CarUnknown.Value)

	end)
end)



I still don’t have 2 values and when it tries to save it gives me this error
ServerScriptService.Data:22: attempt to call missing method ‘SetAsync’ of table

1 Like

You’re still only saving CarUnknown.Value

Data:SetAsync(plr.UserId, CarUnknown.Value)

The reason you’re getting that error is because you set the “Data” variable to the dictionary.

Also, you’re setting the attribute in the dictionary to the DataStore which won’t work.

Here’s an example of what you want to do:

local DataToSave = {
	['Car'] = CarUnknown.Value ,
	['Color'] = 'Really blue',
	-- Add more attributes as you wish
}
Data:SetAsync(plr.UserId, DataToSave)

I wouldn’t recommend saving to the DataStore every time the CarUnknown value is changed – that’ll easily exhaust the limits.

1 Like

just to be clear I am adding the data table where I added the comment [here]

local CarUnknown = Instance.new("StringValue")
	CarUnknown.Name = "."
	CarUnknown.Parent = plr.Car
	local Data = {--here

Or do I remove these parts and just create a data table??

local CarUnknown = Instance.new("StringValue")
	CarUnknown.Name = "."
	CarUnknown.Parent = plr.Car

Tad confused on what you’re asking but you’ll still need to keep the lines where you create the folder, value, and such if you want those to exist? Creating that dictionary won’t create instances.

2 Likes

Ok, I edited my script and I am still not getting the attribute.


Also here is my updated script


game.Players.PlayerAdded:Connect(function(plr)

	local players = game:GetService("Players")
	local dataStore = game:GetService("DataStoreService")
	local Data = dataStore:GetDataStore("Data")
	
	local folder = Instance.new("Folder")
	folder.Name = "Car"
	folder.Parent = plr

	local CarUnknown = Instance.new("StringValue")
	CarUnknown.Name = "CarVals"
	CarUnknown.Parent = plr.Car
	local DataManger = {
		['CarName'] = CarUnknown.Value ,
		['Cost'] = "$$"
	}
	CarUnknown.Changed:Connect(function()
		Data:SetAsync(plr.UserId, CarUnknown.Value)
		Data:SetAsync(plr.UserId, DataManger)
		

	end)
end)

Okay, I’m confused on what you’re looking for. Are you wanting it to create attributes / set the values for attributes of an instance?

Also, in the code you provided, remove that 1st SetAsync() line.

2 Likes

I am wanting to create a second string value using attributes in the same string value I created.

local CarUnknown = Instance.new(“StringValue”)

With this I am wanting to save both values then

1 Like

Is the intent to create an attribute for CarVals or just create another StringValue and skip creating an attribute? If you create another StringValue, it’s not going to put an attribute for CarVals unless you also have it set to create an attribute and there’s no reason to have both another StringValue and an attribute that both are the same thing — that’s redundant.

1 Like

I am wanting to create another value but in the same value I created. Which I thought this can be done using attributes.
Screen Shot 2023-07-23 at 6.52.53 AM
Then I was wanting to use datastore to save what’s in the 2nd value.
Hopefully this helps explain

Aah… Okay, to do that, you can do something like this:

game.Players.PlayerAdded:Connect(function(plr)
	local Players = game:GetService("Players")
	local DataStoreService = game:GetService("DataStoreService")
	local DataStore = DataStoreService:GetDataStore('Data')
	local Data = DataStore:GetAsync(plr.UserId)

	local folder = Instance.new("Folder")
	folder.Name = "Car"
	folder.Parent = plr

	local CarUnknown = Instance.new("StringValue")
	CarUnknown.Name = "CarVals"
	CarUnknown.Parent = plr.Car
	
	if not Data then
		local DefaultData = {
			['CarName'] = 'Alfa Romeo',
			['Color'] = 'Really blue',
			['Cost'] = 500,
			-- Add more attributes
		}
		for i,v in pairs(DefaultData) do
			CarUnknown:SetAttribute(i,v)
		end
	else
		for i,v in pairs(Data) do
			CarUnknown:SetAttribute(i,v)
		end
	end
	
	
	CarUnknown.Changed:Connect(function() -- I would advise against saving every time this changes, it will use up a lot of the request limit
		local DataToSave = CarUnknown:GetAttributes()
		DataStore:SetAsync(plr.UserId, DataToSave)
	end)
end)
2 Likes

it almost works. It creates the attributes but it won’t save the values. I also did change this

CarUnknown.Changed:Connect(function()

to
this

Players.PlayerRemoving:Connect(function()
local DataToSave = CarUnknown:GetAttributes()
DataStore:SetAsync(plr.UserId, DataToSave)

1 Like

Okay, paste the full code now. From what you posted above, if you pasted the full code, there’s a few issues.

  • There’s no end
  • You don’t capture the player so where it tries to SetAsync, it’ll attempt to index UserId from nil
3 Likes
game.Players.PlayerAdded:Connect(function(plr)
	local Players = game:GetService("Players")
	local DataStoreService = game:GetService("DataStoreService")
	local DataStore = DataStoreService:GetDataStore('Data')
	local Data = DataStore:GetAsync(plr.UserId)

	local folder = Instance.new("Folder")
	folder.Name = "Car"
	folder.Parent = plr

	local CarUnknown = Instance.new("StringValue")
	CarUnknown.Name = "CarVals"
	CarUnknown.Parent = plr.Car

	if not Data then
		local DefaultData = {
			['CarName'] = 'Acura RDX',
			['LicensePlate'] = '',
			['Cost'] = 26000 ,
			-- Add more attributes
		}
		for i,v in pairs(DefaultData) do
			CarUnknown:SetAttribute(i,v)
		end
	else
		for i,v in pairs(Data) do
			CarUnknown:SetAttribute(i,v)
		end
	end


	Players.PlayerRemoving:Connect(function() -- I would advise against saving every time this changes, it will use up a lot of the request limit
		local DataToSave = CarUnknown:GetAttributes()
		DataStore:SetAsync(plr.UserId, DataToSave)
	end)
end)
2 Likes
local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local DataStore = DataStoreService:GetDataStore('Data')

Players.PlayerAdded:Connect(function(plr)
	local Data = DataStore:GetAsync(plr.UserId)
	local folder = Instance.new("Folder")
	folder.Name = "Car"
	folder.Parent = plr

	local CarUnknown = Instance.new("StringValue")
	CarUnknown.Name = "CarVals"
	CarUnknown.Parent = plr.Car

	if not Data then
		local DefaultData = {
			['CarName'] = 'Acura RDX',
			['LicensePlate'] = '',
			['Cost'] = 26000 ,
			-- Add more attributes
		}
		for i,v in pairs(DefaultData) do
			CarUnknown:SetAttribute(i,v)
		end
	else
		for i,v in pairs(Data) do
			CarUnknown:SetAttribute(i,v)
		end
	end
end)

Players.PlayerRemoving:Connect(function(plr)
	local CarUnknown = plr:WaitForChild('CarUnknown')
	local DataToSave = CarUnknown:GetAttributes()
	DataStore:SetAsync(plr.UserId, DataToSave)
end)

Try that instead. A couple issues with how you did PlayerRemoving:

  • You didn’t pass plr in the ()'s
  • I wouldn’t advise putting PlayerRemoving inside PlayerAdded otherwise each time a player joins, it will create a new connection listening to the PlayerRemoving event.
3 Likes

Still isn’t saving I put prints around the script and this area I am not getting any prints from.

Players.PlayerRemoving:Connect(function(plr)
	print("leaves")--I do get this print
	local CarUnknown = plr:WaitForChild('CarUnknown')
	print("waits")
	local DataToSave = CarUnknown:GetAttributes()
	print("data")
	DataStore:SetAsync(plr.UserId, DataToSave)
	print("stores")
end)

I do not receive any of the prints except for leaves

2 Likes

Okay, yeah, you’d be better off doing this:

local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local DataStore = DataStoreService:GetDataStore('Data')
local PlayerData = {}

Players.PlayerAdded:Connect(function(plr)
	local Data = DataStore:GetAsync(plr.UserId)
	
	if not PlayerData[plr.Name] then
		PlayerData[plr.Name] = {
			Data = {},
			Connections = {},
		}
	end
	
	local folder = Instance.new("Folder")
	folder.Name = "Car"
	folder.Parent = plr

	local CarUnknown = Instance.new("StringValue")
	CarUnknown.Name = "CarVals"
	CarUnknown.Parent = plr.Car

	if not Data then
		local DefaultData = {
			['CarName'] = 'Acura RDX',
			['LicensePlate'] = '',
			['Cost'] = 26000 ,
			-- Add more attributes
		}
		for i,v in pairs(DefaultData) do
			CarUnknown:SetAttribute(i,v)
			PlayerData[plr.Name].Data[i] = v
			table.insert(PlayerData[plr.Name].Connections,
				CarUnknown:GetAttributeChangedSignal(i):Connect(function()
					PlayerData[plr.Name].Data[i] = CarUnknown:GetAttribute(i)
				end)
			)
		end
	else
		for i,v in pairs(Data) do
			CarUnknown:SetAttribute(i,v)
			PlayerData[plr.Name].Data[i] = v
			table.insert(PlayerData[plr.Name].Connections,
				CarUnknown:GetAttributeChangedSignal(i):Connect(function()
					PlayerData[plr.Name].Data[i] = CarUnknown:GetAttribute(i)
				end)
			)
		end
	end
	
	table.insert(PlayerData[plr.Name].Connections,
		CarUnknown.AttributeChanged:Connect(function(att)
			PlayerData[plr.Name].Data[att] = CarUnknown:GetAttribute(att)
		end)
	)
end)

Players.PlayerRemoving:Connect(function(plr)
	if PlayerData[plr.Name] then
		DataStore:SetAsync(plr.UserId, PlayerData[plr.Name].Data)
		for i,v in ipairs(PlayerData[plr.Name].Connections) do
			v:Disconnect()
		end
		PlayerData[plr.Name].Connections = {}
		PlayerData[plr.Name] = nil
	end
end)

This will allow for any changes made to the attributes to be automatically updated in the Data dictionary as well as if you add any new attributes on run-time, it’ll automatically add them to be saved. :slight_smile:

2 Likes

Hi, there the data still won’t save I added more prints

local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local DataStore = DataStoreService:GetDataStore('Data')
local PlayerData = {}
print("Local")
Players.PlayerAdded:Connect(function(plr)
	local Data = DataStore:GetAsync(plr.UserId)
	if not PlayerData[plr.Name] then
		PlayerData[plr.Name] = {
			Data = {},
			Connections = {},
		}
		print("Playeradded")
	end

	local folder = Instance.new("Folder")
	folder.Name = "Car"
	folder.Parent = plr

	local CarUnknown = Instance.new("StringValue")
	CarUnknown.Name = "CarVals"
	CarUnknown.Parent = plr.Car
	print("New")
	if not Data then
		local DefaultData = {
			['CarName'] = 'Acura RDX', 
			['LicensePlate'] = '',
			['Cost'] = "26000" ,
			-- Add more attributes
		}
		print("Data")
		for i,v in pairs(DefaultData) do
			CarUnknown:SetAttribute(i,v)
			PlayerData[plr.Name].Data[i] = v
			table.insert(PlayerData[plr.Name].Connections,
				CarUnknown:GetAttributeChangedSignal(i):Connect(function()
					PlayerData[plr.Name].Data[i] = CarUnknown:GetAttribute(i)
					print("For")
				end)
			)
		end
	else
		for i,v in pairs(Data) do
			CarUnknown:SetAttribute(i,v)
			PlayerData[plr.Name].Data[i] = v
			table.insert(PlayerData[plr.Name].Connections,
				CarUnknown:GetAttributeChangedSignal(i):Connect(function()
					PlayerData[plr.Name].Data[i] = CarUnknown:GetAttribute(i)
					print("I")
				end)
			)
		end
	end

	table.insert(PlayerData[plr.Name].Connections,
		CarUnknown.AttributeChanged:Connect(function(att)
			PlayerData[plr.Name].Data[att] = CarUnknown:GetAttribute(att)
			print("Table")
		end)
	)
end)

Players.PlayerRemoving:Connect(function(plr)
	if PlayerData[plr.Name] then
		DataStore:SetAsync(plr.UserId, PlayerData[plr.Name].Data)
		for i,v in ipairs(PlayerData[plr.Name].Connections) do
			v:Disconnect()
		end
		PlayerData[plr.Name].Connections = {}
		PlayerData[plr.Name] = nil
		print("Leaving")--not getting print
	end
end)

leaving I am not getting that print when I leave

1 Like

Are you trying this in studio? If so, you have to have “Allow studio access to API services” enabled to save data.

Also is this in a LocalScript? It has to be a server script for utilizing DataStoreService to work.

1 Like