How do I make a script that adds players hats to the StarterCharacter?

I am trying to make a script that makes the player a custom startercharacter, but keeps the players accessories, similar to the game Warm Isolation.

^^Those are the Roblox accessories I have equipted, but my characters bodycolors and lack of clothing are different, hense it is a Startercharacter with my items equipted on it.

How do I go about making a script like that? where I change into a new character but keep my Roblox avatars items?

8 Likes

When a players join, you clone their accesories and save them to a folder (or anything tbh) and then when their character loads you add the accesories back into the character, now you would want to do this in a script inside of ServerScriptService

local Players = game:GetService("Players")
Players.PlayerAdded:Connect(function(plr)
local AccesoriesFolder = Instance.new("Folder")
AccesoriesFolder.Parent = workspace
local chr = plr.Character or plr.CharacterAdded:Wait()
for _, acc in chr:GetDescendants() do
if acc:IsA("Accesory") then
acc.Parent = AccesoriesFolder
end
end
wait(2)
for _, acc in AccesoriesFolder:GetDescendants() do
acc.Parent = chr
end)

5 Likes
local player = ...
local originalCharacter = player.Character
local accessories = originalCharacter.Humanoid:GetAccessories()

local customCharacter = ...:Clone()
player.Character = customCharacter

for _, accessory in accessories do
    customCharacter.Humanoid:AddAccessory(accessory)
end
4 Likes

Hey, I dont’ know if you found a working method yet, but this is what I just came up with. First I added my “StarterCharacter” into the ServerStorage. I then put a script into ServerScriptService and added the following code.

local Players = game:GetService("Players")

Players.PlayerAdded:Connect(function(player)
	print("PlayerAdded for", player.Name)
	local counter = 0

	local AccessoriesFolder = game.ReplicatedStorage:FindFirstChild("PlayerAccessories")
	if not AccessoriesFolder then
		AccessoriesFolder = Instance.new("Folder")
		AccessoriesFolder.Name = "PlayerAccessories"
		AccessoriesFolder.Parent = game.ReplicatedStorage
	end

	-- Try to locate the "StarterCharacter" object in ServerStorage
	local defaultStarterCharacter = game.ServerStorage:FindFirstChild("StarterCharacter")

	if defaultStarterCharacter then
		print("Found StarterCharacter in ServerStorage for", player.Name)

		player.CharacterAdded:Connect(function(character)
			print("CharacterAdded for", player.Name)

			wait(1)  -- Wait for a short time to ensure accessories are loaded

			local humanoid = character:FindFirstChild("Humanoid")
			if humanoid then
				print("Humanoid found for", player.Name)
				-- Move the player's existing hats to the folder
				if counter < 1 then
					for _, accessory in ipairs(humanoid:GetAccessories()) do
						accessory.Parent = AccessoriesFolder
						counter += 1
						print(counter)
					end
				else
					return
				end
			end

		end)
	end
	
	
	wait(5)
	local clonedCharacter = defaultStarterCharacter:Clone()
	clonedCharacter.Parent = game.StarterPlayer
	for _, accessory in ipairs(AccessoriesFolder:GetChildren()) do
		accessory.Parent = game.StarterPlayer:WaitForChild("StarterCharacter")
	end
	player:LoadCharacter()
	AccessoriesFolder:Destroy()
end)

Change it to meet your needs. It’s also not the best, but its what worked for me. Hopefully this helps!

2 Likes

This only applies to singleplayer
If another player joins, the first player that join’s accessories will be applied to the next player and so on. And in the end, all the player will have the same accessories as the first player

1 Like

I made a script that ended up working, it copies hair and head accessories, and it works for server and client
image
(Proof of the script)
So here it is!

2 Likes

wow it looks pretty convincing, ill be sure to test it

What you have is pretty close to what should be used. However, there are flaws with how your code is setup. You should really be using a pattern like this:

local Players = game:GetService("Players")

local function onCharacterAdded(character: Model)
	local humanoid = character:FindFirstChildOfClass("Humanoid")
	local player = Players:GetPlayerFromCharacter(character)
	
	local success, result = pcall(Players.GetCharacterAppearanceAsync, Players, player.UserId)
	
	if not success then
		warn(`Failed to acquire accessories because '{result}'`)
		return
	end
	
	for _,descendant in result:GetDescendants() do
		if descendant:IsA("Accessory") then
			humanoid:AddAccessory(descendant)
		end
	end
end

local function onPlayerAdded(player: Player)	
	local character = player.Character
	if character then
		task.spawn(onCharacterAdded, character)
	end
	
	player.CharacterAdded:Connect(onCharacterAdded)
end

for _,player in Players:GetPlayers() do
	task.spawn(onPlayerAdded, player)
end

Players.PlayerAdded:Connect(onPlayerAdded)

To put it simply, you have unnecessary connections created and there’s potential for onCharacterAdded to never be ran for players that joined before the script first ran, which would be a race condition.

1 Like

Thanks for noticing, but the script before worked fine

hey yeah ik this is a late feedback but i was actually finding a script that loads accessories that have mesh part handles. The script loads the handle as base parts like an r6 rig. just so you know, r15 rigs automatically change the handles to mesh parts. The problem is, i do not know how to use playerAvatarType when using GetCharacterAppearanceAsync

i got a working script
script

I dont know how this topic still isnt solved but thanks for the script! Was looking everywhere for answers!

dude i have a working script like right on top