Trying to access character values in data saving

Hello! I am currently working on an RPG game. I’m trying to get the data to save when the player leaves, but some of the values I need to save are attributes on the player’s character. Every time I attempt to do this, it always returns the character as nil. I’m not exactly sure what I should do to fix this and still achieve what I’m trying to do.

local function SaveData(player, wiped, died)
	local CT = CombatTable[player.Name]
	
	local Character = player.Character
	
	local key = "player_" .. player.UserId
	
	if CT.InCombat then
		wiped = true
		print(player.Name .. " combat logged.")
	end
	
	if wiped then
		StatTable[player.UserId] = {
			Lives = 3,
			Health = 100,
			MaxHealth = 100,
			Experience = 0,
			Level = 1,
			Passives = {},
			Odens = 0,
			TalentPoints = 0,
			MaxPosture = 60
		}
		CharacterTable[player.UserId] = {
			Appearance = {},
			CurrentQuests = {},
			CompletedQuests = {},
			Items = {},
			Location = {workspace.Thing.CFrame:GetComponents()},
			Class = nil,
			DawnMark = nil,
			Area = nil,
		}
	else
		StatTable[player.UserId] = {
			Lives = Character:GetAttribute("Lives"),
			Health = Character:GetAttribute("SpecialHealth"),
			MaxHealth = 100 + GetHealthBonus(Character),
			Experience = Character:GetAttribute("Experience"),
			Level = Character:GetAttribute("Level"),
			Passives = {},
			Odens = Character:GetAttribute("Odens"),
			TalentPoints = Character:GetAttribute("TalentPoints"),
			MaxPosture = Character:GetAttribute("MaxPosture")
		}
		CharacterTable[player.UserId] = {
			Appearance = {},
			CurrentQuests = {},
			CompletedQuests = {},
			Items = {},
			Location = {Character.HumanoidRootPart.CFrame:GetComponents()},
			Class = nil,
			DawnMark = Character:GetAttribute("DawnMark"),
			Area = Character:GetAttribute("Area")
		}
	end
	
	if died then
		CharacterTable[player.UserId].Location = {workspace.OtherThing.CFrame:GetComponents()}
	end
	
	--print("Data saving...")
	
	local SetSuccess, errorMessage = pcall(function()
		StatData:SetAsync(player.UserId, StatTable[player.UserId])
		CharacterData:SetAsync(player.UserId, CharacterTable[player.UserId])
	end)
	if not SetSuccess then
		print("Data was unable to save.")
		warn(errorMessage)
	else
	--	print("Successfully saved data!")
	end
end

This is currently my data saving function and I use it like this:

Players.PlayerRemoving:Connect(function(player)
	SaveData(player)
end)

Any ideas?

Is all of the data being saved, or just the location?

it saves all of the data listed above, but it returns nil every time with the “Character:GetAttribute(blank)” as well as the CT.InCombat check. I tried printing the character.Name and it printed “Attempt to index nil with Name” meaning the character is somehow not being obtained

Is it possible the Workspace.SignalBehavior property is set to Deferred? Try setting it to Immediate if it isn’t.

Workspace was set to deferred, but switching it to immediate caused every other script in my game to break completely. I made some of the ones that weren’t working wait until the game was loaded but that didn’t fix them either.

The problem that’s happening is that if I do something like this:
image
It does this:

I should also say that the data saves fine when the data saves before the player leaves, like when they die and it saves their new data. When it doesn’t save and it spits out this error is when the player leaves.

this issue might be related to how you’re accessing the character’s attributes. Instead of Character:GetAttribute("Lives"), try using player.Character.Humanoid.MaxHealth.Value or player.Character.Humanoid.Health.Value. Also, ensure that the CharacterTable and StatTable are properly defined and accessible in the scope of your function.

There should be no issue trying to get the attribute off the player. I have a save system that does what you are asking.

What I think is going on is, your are attempting to access the player, but the player is no longer available (from leaving the server or w/e) so it returns nil.

Make sure you call the getattribute method on an actual client object, and make sure that object is valid.

That’s actually not the issue, I can print any of the player values, such as their name, display name, etc, but their CHARACTER is what is returning nil. Also, the attributes I have set are set on the players character, not the actual player. I already tried switching attributes to the player instead of the character, which works fine for the most part, but I still can’t access the character’s position in the world to save their location.

Game.workspace:findfirstchild(your name)

Is your model instance in the game world.

Game.players:findfirstchild(your name) is the ‘client’ version of your character.

Edit: when I say client, I don’t mean anything client sided

So maybe do an workspace.onchildremoved event, and then if it’s a player, save/retrieve data from their in game model. (Assuming this is what you meant by data on the char model). I could be misinterpreting how your are saving attributes.

I tried this and it seemed to work at first, but when I tried to access the player, it broke. It’s like it won’t let me access whichever one I don’t use, either the player or the character, when I need to access both.

I have resolved the issue myself. I just decided to implement an autosave system instead. Thanks a lot anyways to everyone who tried to help!

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.