How to Save and Load character's custom avatar with DataStore and/or Serialization?

  1. What do you want to achieve? Keep it simple and clear!

I’m using serialization and DataStores to try and load and save the player’s custom avatar.


  1. What is the issue? Include screenshots / videos if possible!

– I have a fully working character customization system, except it won’t save or load. Right now, I’m just trying to get it to save the hairs, just for now.
image_2024-03-15_013147555

  1. What solutions have you tried so far? Did you look for solutions on the Developer Hub?

– I’ve looked on: YouTube, the DevForum, hell, even tried ChatGPT to help me out. Nothing is working.

1 Like

Did you use print to check if the data would print out when you joined and leaved? Also add a pcall for setasync

It does print out when the player joins and leaves, and also prints when the data is being saved or loaded. I added a pcall to my module script here:

local AvatarModule = {}

function AvatarModule.saveAvatar(player)
	print("Saving avatar for player:", player.Name)
	local datastore = game:GetService("DataStoreService"):GetDataStore("PlayerAvatars")

	local avatarData = {}

	local char = player.Character
	if char then
		for _, item in ipairs(char:GetChildren()) do
			table.insert(avatarData, item:GetFullName()) -- Store the full name of each item
		end
	end

	local success, serializedData = pcall(game:GetService("HttpService").JSONEncode, avatarData)
	if success then
		datastore:SetAsync(player.UserId, serializedData)
	else
		print("Error serializing avatar data for player:", player.Name)
	end
end


-- Function to load and apply player's avatar
function AvatarModule.loadAndApplyAvatar(player)
	print("Loading and applying avatar for player:", player.Name)
	local datastore = game:GetService("DataStoreService"):GetDataStore("PlayerAvatars")
	local success, serializedData = pcall(datastore.GetAsync, datastore, player.UserId)

	if success and serializedData then
		local success, avatarData = pcall(game:GetService("HttpService").JSONDecode, serializedData)
		if success then
			local avatarModel = Instance.new("Model")
			avatarModel.Name = "Avatar"
			for _, itemName in ipairs(avatarData) do
				local item = game:GetService("Workspace"):FindFirstChild(itemName)
				if item then
					item:Clone().Parent = avatarModel
				end
			end
			avatarModel.Parent = game.Workspace
		else
			print("Error decoding avatar data for player:", player.Name)
		end
	else
		print("Error loading avatar data for player:", player.Name)
	end
end


return AvatarModule

I decided it’d be easier to try and save and load the player’s avatar alltogether than try and save the skintone, clothing, hair, etc. 1 by 1, but again, still not working.

1 Like

I meant for you to add a pcall for SetAsync, always add pcalls to functions that have Async.

So, if everything prints, is your problem loading the avatar or is it storing the data in the current server?

The data stores just fine - it’s just the avatar that won’t load

Normally you would use a colon, which passes the service itself as a parameter automatically. In this case, you need to pass it manually.
pcall(game:GetService("HttpService").JSONEncode, game:GetService("HttpService"), avatarData)

local AvatarModule = {}

function AvatarModule.saveAvatar(player)
	print("Saving avatar for player:", player.Name)
	local datastore = game:GetService("DataStoreService"):GetDataStore("PlayerAvatars")

	local avatarData = {}

	local char = player.Character
	if char then
		for _, item in ipairs(char:GetChildren()) do
			table.insert(avatarData, item:GetFullName()) -- Store the full name of each item
		end
	end

	local success, serializedData = pcall(game:GetService("HttpService").JSONEncode, game:GetService("HttpService"), avatarData)
	if success then
		datastore:SetAsync(player.UserId, serializedData)
	else
		print("Error serializing avatar data for player:", player.Name)
	end
end


function AvatarModule.loadAndApplyAvatar(player)
	print("Loading and applying avatar for player:", player.Name)
	local datastore = game:GetService("DataStoreService"):GetDataStore("PlayerAvatars")
	local success, serializedData = pcall(datastore.GetAsync, datastore, player.UserId)

	if success and serializedData then
		local success, avatarData = pcall(game:GetService("HttpService").JSONDecode, game:GetService("HttpService"), serializedData)
		if success then
			local avatarModel = Instance.new("Model")
			avatarModel.Name = "Avatar"

			local char = player.Character
			if char then
				for _, itemName in ipairs(avatarData) do
					local item = game:GetService("Workspace"):FindFirstChild(itemName)
					if item then
						item:Clone().Parent = avatarModel
					else
						warn("Item", itemName, "not found for player:", player.Name)
					end
				end

				-- Cleans up previous avatar model
				local oldAvatar = game.Workspace:FindFirstChild(player.Name .. "_Avatar")
				if oldAvatar then
					oldAvatar:Destroy()
				end

				-- Sets new avatar model in workspace
				avatarModel.Name = player.Name .. "_Avatar"
				avatarModel.Parent = game.Workspace
			else
				warn("Player", player.Name, "has no character.")
			end
		else
			print("Error decoding avatar data for player:", player.Name)
		end
	else
		print("Error loading avatar data for player:", player.Name)
	end
end


return AvatarModule

added some adjustments to theloadandapply function + added the line of code you suggested, heres the issue now:


everything “saves and loads”, except it says this now:

etc…