How to datastore2 more than 1 variable?

Yep still having problems. Should line 19 (DataStore2.Combine("main", "Wins", "Ωmega Coins", "Likes", "object_name", "object_position", "object_rotation", "terrain-position", "terrain_rotation", "terrain_size", "terrain_materials")) be put in the PlayerAdded event?

No; combining datastores is not player-specific. Your specific problems/errors/error messages would help.

20:53:15.407 - ServerScriptService.save_script:94: attempt to index nil with number

I was gonna say it was the same error I had before but the previous one was saying it was calling a nil value not indexing a nil value.

Continuing off this topic (it died again for the billionth time): Error when trying to do DataStore2 stuff but what I am trying to do is save all my data which is listed in DataStore2.combine in the script and firstly load the save for the bunker’s CFrame into part and also set the save to default bunker materials if the save is nil.

I get this error 20:33:16.091 - ServerScriptService.save_script:94: attempt to index nil with number when running this script


local ServerStorage = game.ServerStorage

local Workspace = game.Workspace

local Players = game.Players

local default_omega_coins = 0

local default_likes = 0

local default_wins = 0

local default_bunker_terrain_position = {CFrame.new(26.927, -33.383, -435.507), CFrame.new(26.927, 23.365, -572.788), CFrame.new(164.479, 23.365, -434.153),

CFrame.new(-110.625, 23.365, -435.236), CFrame.new(25.844, 23.365, -297.955)}

local default_bunker_terrain_size = {Vector3.new(277.27, 8.143, 277.27), Vector3.new(277.27, 108.309, 2.708),Vector3.new(2.166, 108.309, 274.562),Vector3.new(2.166, 108.309, 272.396),Vector3.new(275.104, 108.309, 2.166)}

local default_bunker_terrain_rotation = {CFrame.Angles(0,0,0), CFrame.Angles(0,0,0), CFrame.Angles(0,0,0),

CFrame.Angles(0,0,0), CFrame.Angles(0,0,0)}

local default_bunker_materials = {"Mud","Rock","Rock","Rock","Rock"}

local default_object_name = {}

local default_object_position = {}

local default_object_rotation = {}

DataStore2.Combine("main", "Wins", "Ωmega Coins", "Likes", "object_name", "object_position", "object_rotation", "terrain-position", "terrain_rotation", "terrain_size", "terrain_materials")

Players.PlayerAdded:Connect(function(plr)

winsStore = DataStore2("Wins", plr)

coinStore = DataStore2("Ωmega Coins", plr)

likesStore = DataStore2("Likes", plr)

objectnameStore = DataStore2("object_name", plr)

objectpositionStore = DataStore2("object_position", plr)

objectrotationStore = DataStore2("object_rotation", plr)

terrainpositionStore = DataStore2("terrain-position", plr)

terrainrotationStore = DataStore2("terrain_rotation", plr)

terrainsizeStore = DataStore2("terrain_size", plr)

terrainmaterialsStore = DataStore2("terrain_materials", plr)

local leaderstats = Instance.new("Folder",plr) ---leaderstats folder

leaderstats.Name = "leaderstats"

local wins = Instance.new("IntValue",leaderstats) --leaderstats

wins.Name = "Wins"

local omega_coins = Instance.new("IntValue",leaderstats)

omega_coins.Name = "Ωmega $"

local likes = Instance.new("IntValue",leaderstats)

likes.Name = "Likes"

if terrainpositionStore == nil then

terrainpositionStore = default_bunker_terrain_position

end

if terrainmaterialsStore == nil then

terrainmaterialsStore = default_bunker_materials

end

if terrainrotationStore == nil then

terrainrotationStore = default_bunker_terrain_rotation

end

if terrainsizeStore == nil then

terrainsizeStore = default_bunker_terrain_size

end

if objectnameStore == nil then

objectnameStore = default_object_name

end

if objectpositionStore == nil then

objectpositionStore = default_object_position

end

if objectrotationStore == nil then

objectrotationStore = default_object_rotation

end

if winsStore == nil then

terrainpositionStore = default_wins

end

if coinStore == nil then

coinStore = default_omega_coins

end

if likesStore == nil then

likesStore = default_likes

end

end)

function save_to_model(folder_name, target_location, CFrameoffset)

local newMap = ServerStorage.empty_map:Clone()

newMap.Name = folder_name

newMap.Parent = Workspace

local terrain = newMap.terrain:WaitForChild("cubes") -- FillBlock() is used on all parts in cubes.

for i, v in pairs(default_bunker_materials) do

local part = Instance.new("Part")

part.Name = v

-- new block:

part.CFrame = terrainpositionStore[i]

part.Size = default_bunker_terrain_size[i]

part.Parent = terrain

end

end

save_to_model("MrGuyROBLOX's Dungeon", game.Workspace.maps,0,0,0) -- test function

Also can someone keep an eye on this topic for once because I have made like 5 topics on DataStore2 that have just died and I really need to get this solved now.

This makes it seem like we’re obligated to help you. We’re all for helping one another here on the DevForum, but only to our own capabilities and desires.

Another thing, you noted that the error was on line 94, but could you please point out the exact line in specific? I tried to copy and paste the code you gave us, but there seems to be variables defined before it, thus my line 94 isn’t the same as yours.

1 Like

it has nothing to do with datastore2, you should just refresh up on “How to use variables”.

your trying to apply a value to a variable that doesn’t exist.

EDIT: and datastore2 isn’t user friendly tbh (definitely not at first), if you are REALLY having this many issues then you’ll have better luck learning how Datastores work in general.

I have rewritten your script to cause less eye strain so it’s easier to work with, because there are a LOT of white spaces.

ServerStorage = game:GetService("ServerStorage")
Players = game:GetService("Players")

default_omega_coins, default_likes, default_wins = 0, 0, 0

default_bunker_terrain_position = {
	CFrame.new(26.927, -33.383, -435.507),
	CFrame.new(26.927, 23.365, -572.788),
	CFrame.new(164.479, 23.365, -434.153),
	CFrame.new(-110.625, 23.365, -435.236),
	CFrame.new(25.844, 23.365, -297.955)
}
default_bunker_terrain_size = {
	Vector3.new(277.27, 8.143, 277.27),
	Vector3.new(277.27, 108.309, 2.708),
	Vector3.new(2.166, 108.309, 274.562),
	Vector3.new(2.166, 108.309, 272.396),
	Vector3.new(275.104, 108.309, 2.166)
}
default_bunker_terrain_rotation = {
	CFrame.Angles(0, 0, 0),
	CFrame.Angles(0, 0, 0),
	CFrame.Angles(0, 0, 0),
	CFrame.Angles(0, 0, 0),
	CFrame.Angles(0, 0, 0)
}
default_bunker_materials = {
	"Mud",
	"Rock",
	"Rock",
	"Rock",
	"Rock"
}

default_object_name, default_object_position, default_object_rotation = {}, {}, {}

DataStore2.Combine("main", "Wins", "Ωmega Coins", "Likes", "object_name", "object_position", "object_rotation", "terrain-position", "terrain_rotation", "terrain_size", "terrain_materials")

Players.PlayerAdded:Connect(function(Player)
	local winsStore = DataStore2("Wins", Player) or default_wins
	local coinStore = DataStore2("Ωmega Coins", Player) or default_omega_coins
	local likesStore = DataStore2("Likes", Player) or default_likes
	
	local objectnameStore = DataStore2("object_name", Player) or default_object_name
	local objectpositionStore = DataStore2("object_position", Player) or default_object_position
	local objectrotationStore = DataStore2("object_rotation", Player) or default_object_rotation
	
	local terrainpositionStore = DataStore2("terrain-position", Player) or default_bunker_terrain_position
	local terrainrotationStore = DataStore2("terrain_rotation", Player) or default_bunker_terrain_rotation
	local terrainsizeStore = DataStore2("terrain_size", Player) or default_bunker_terrain_size
	local terrainmaterialsStore = DataStore2("terrain_materials", Player) or default_bunker_materials
	
	local leaderstats = Instance.new("Folder") do
		leaderstats.Name = "leaderstats"
	end
	local wins = Instance.new("IntValue") do
		wins.Name = "Wins"
		wins.Parent = leaderstats
	end
	local omega_coins = Instance.new("IntValue") do
		omega_coins.Name = "Ωmega $"
		omega_coins.Parent = leaderstats
	end
	local likes = Instance.new("IntValue") do
		likes.Name = "Likes"
		likes.Parent = leaderstats
	end
	leaderstats.Parent = Player
end)

function save_to_model(folder_name, target_location, CFrameoffset)
	local newMap = ServerStorage.empty_map:Clone() do
		newMap.Name = folder_name
	end
	
	local terrain = newMap.terrain:WaitForChild("cubes")
	for i, v in pairs(default_bunker_materials) do
		local Part = Instance.new("Part") do
			Part.Name = v
			Part.CFrame = terrainpositionStore[i]
			Part.Size = default_bunker_terrain_size[i]
			Part.Parent = terrain
		end
	end
	
	newMap.Parent = workspace
end

save_to_model("MrGuyROBLOX's Dungeon", game.workspace.maps, 0, 0, 0) -- test function

This isn’t necessarily a fix, it’s just much nicer to read. It is about half the size of your script.

You forgot to add at the top DataStore2 = require(game:GetService("ServerScriptService").DataStore2)

I think first off I should say that there are a few things that I’m not 100 percent sure how they work.

So I think DataStore2.Combine("main", "Wins", "Ωmega Coins", "Likes", "object_name", "object_position", "object_rotation", "terrain-position", "terrain_rotation", "terrain_size", "terrain_materials") creates a list of saveable variables listed in the brackers am I right or wrong?

I have not seen a variable defined like this before local terrainpositionStore = DataStore2("terrain-position", Player) or default_bunker_terrain_position could you explain it?

As a quick correction, the code you provided didn’t include

DataStore2 = require(game:GetService("ServerScriptService").DataStore2)

so i couldn’t do much about it, that i let that out. xd

What do you mean with ‘i have not seen a variable defined like this before …’?

1 Like

Oh oops I thought i copied the whole code my original code did have that. Yeah I have never seen variables defined with or what does or do what determines when the other value after or will be used?

oooooooh, i see XD

Explanation

if the first argument is equal to true (either a boolean set to true or an object, those always represent true) then that will be passed on.
if it is false (a boolean that is false or the object doesn’t exist), the second argument will be passed on.

I’m not the best at explaining this, but i hope you get the point. :wink:

1 Like

so would nil be equal to false and other values like 3 would be equal to true?

I have checked it to be sure and the answer is yes. A quick learner you are. :slight_smile:

1 Like

Ok thanks. I just need to confirm now that if you access data in DataStore2.Combine()
you are modifying the save data I’m really confused.

I don’t know what 'DataStore2.Combine() ’ does, because i’m not familiar with DataStore2 myself. You may have to wait a bit for a good answer from someone else. :confused:

1 Like

Ok I’m going to search the internet for DataStore2.Combine

It is explained in the docs.

Ok I have been messing around with the script and I looked at the official DataStore2 forum posts https://devforum.roblox.com/t/how-to-use-datastore2-data-store-caching-and-data-loss-prevention/136317?u=mrguyroblox and I changed a few things but it still gets nil from the DataStore2 variable even if I used :Get(--default value here)

Here is the script, I made sure to copy everything.

DataStore2 = require(game:GetService("ServerScriptService").DataStore2)
ServerStorage = game:GetService("ServerStorage")
Players = game:GetService("Players")

default_omega_coins, default_likes, default_wins = 0, 0, 0

default_bunker_terrain_position = {
	CFrame.new(26.927, -33.383, -435.507),
	CFrame.new(26.927, 23.365, -572.788),
	CFrame.new(164.479, 23.365, -434.153),
	CFrame.new(-110.625, 23.365, -435.236),
	CFrame.new(25.844, 23.365, -297.955)
}
default_bunker_terrain_size = {
	Vector3.new(277.27, 8.143, 277.27),
	Vector3.new(277.27, 108.309, 2.708),
	Vector3.new(2.166, 108.309, 274.562),
	Vector3.new(2.166, 108.309, 272.396),
	Vector3.new(275.104, 108.309, 2.166)
}
default_bunker_terrain_rotation = {
	CFrame.Angles(0, 0, 0),
	CFrame.Angles(0, 0, 0),
	CFrame.Angles(0, 0, 0),
	CFrame.Angles(0, 0, 0),
	CFrame.Angles(0, 0, 0)
}
default_bunker_materials = {
	"Mud",
	"Rock",
	"Rock",
	"Rock",
	"Rock"
}

default_object_name, default_object_position, default_object_rotation = {}, {}, {}

DataStore2.Combine("main", "Wins", "Ωmega Coins", "Likes", "object_name", "object_position", "object_rotation", "terrain-position", "terrain_rotation", "terrain_size", "terrain_materials")

Players.PlayerAdded:Connect(function(Player)
	winsStore = DataStore2("Wins", Player)
	coinStore = DataStore2("Ωmega Coins", Player)
	likesStore = DataStore2("Likes", Player)
	
	objectnameStore = DataStore2("object_name", Player)
	objectpositionStore = DataStore2("object_position", Player)
	objectrotationStore = DataStore2("object_rotation", Player)
	
	terrainpositionStore = DataStore2("terrain-position", Player)
	terrainrotationStore = DataStore2("terrain_rotation", Player)
	terrainsizeStore = DataStore2("terrain_size", Player)
	terrainmaterialsStore = DataStore2("terrain_materials", Player)
	
	local leaderstats = Instance.new("Folder") do
		leaderstats.Name = "leaderstats"
	end
	local wins = Instance.new("IntValue") do
		wins.Name = "Wins"
		wins.Parent = leaderstats
	end
	local omega_coins = Instance.new("IntValue") do
		omega_coins.Name = "Ωmega $"
		omega_coins.Parent = leaderstats
	end
	local likes = Instance.new("IntValue") do
		likes.Name = "Likes"
		likes.Parent = leaderstats
	end
	leaderstats.Parent = Player
end)

function save_to_model(folder_name, target_location, CFrameoffset, pos,size,rot,mat)
	local newMap = ServerStorage.empty_map:Clone() do
		newMap.Name = folder_name
	end
	
	local terrain = newMap.terrain:WaitForChild("cubes")
	for i, v in pairs(terrainmaterialsStore:Get(default_bunker_materials)) do
		local Part = Instance.new("Part") do
			Part.Name = v
			Part.CFrame = pos[i]
			Part.Size = size[i]
			Part.Parent = terrain
		end
	end
	
	newMap.Parent = target_location
end

save_to_model("MrGuyROBLOX's Dungeon", game.Workspace.maps, 0, 0, 0, terrainpositionStore:Get(default_bunker_terrain_position), terrainsizeStore:Get(default_bunker_terrain_size), terrainrotationStore:Get(default_bunker_terrain_rotation,terrainmaterialsStore)) -- test function -- Line 90

script breaks at line 90 because it gets nil from :Get() even though if the value is nil it SHOULD use the value in the brackets.

Btw it says datastore “main” was not saved but it also says it was saved at the same time.

11:41:47.172 - Data store main was not saved as it was not updated.

player left, saved main

The main error message: 11:41:43.770 - ServerScriptService.save_script:90: attempt to index nil with ‘Get’

A couple small mistakes here.

Making the Datastore2 instances global doesn’t help. Why? Because they’re declared in Players.PlayerAdded:Connect(), which means they’re only defined when a player joins. So without a player joining yet, since this is a server Script, line 90 will run with terrainpositionStore as nil because it’s not declared yet.

If you intend to do this for every player, as I said earlier, even if you’re just testing, you ought to put it in the same scope as you declared the variables, where Players.PlayerAdded:Connect() is if you’re planning to do this for every player. That way you can actually wait until the player actually joins and the variables are actually declared before you use them.

Basic Debugging Tips

What the error message says and what line it is on really helps. This isn’t only for when letting your helpers on DevForum find your error, but they also help when you find your error yourself.

Keyword: index. To index something is to get something out of a table using a key. When I say table, you should already know that a table is a one-in-all, all-in-one data structure for Lua. This means that they aren’t only dictionaries, but they are also instances such as Datastore2 instances.

Keyword instance. An instance is an individual object of a class made with Object-Oriented Programming (OOP). I recommend you check out the OOP paradigm in Lua. Datastore2 uses it and it’s very useful to you, too. (not necessarily for this particular issue you’re working on)

As for your actual error, calling a function on an instance is also getting something out of a table. Tables can store functions, just like Datastore2’s class. So when calling a function on the Datastore2 instance, you’re indexing it with the function. You’re indexing nil with the function, Get(). This is how I knew that the datastore was nil and this is how you’ll know in the future, as well. If you look a little further to see where you declared them, you’ll find the code where you declared the variables does not run until someone joins.

Another note, since you made them global variables, then keep in mind that all players share the same variables so if you plan on using those Datastore2 instances outside of the PlayerAdded:Connect() (which I don’t recommend), then you’ll have to remember this.

A Note About Serialization

I said in one of those first posts I wrote for you on this issue that you need to serialize and deserialize certain objects, remember? I also wrote some functions as a demonstration to you how you might serialize and deserialize some bunker objects. If you forgot, please reread my old posts about serialization and deserialization as you can’t store anything with CFrames or Vector3s inside datastores - you need to serialize them, first, as I showed you in my demonstration.