Need help optimizing this starter character

For this, I want to have a custom player character, but wanted to keep their hats. In this I have the custom character nested in the ServerStorage that has a script in the ServerScriptService. This works by creating a folder in replicated, moving the accessories into the folder, then cloning and parenting the startercharacter into the starterplayer. After that I move the hats again into the character. This is the 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)

This (in my opinion) shouldn’t take this many step, but I don’t know what else to do. This also takes about 5 seconds because I have to make sure the character is loaded before it fires.

You don’t even have to store accessories in a folder (unless you use custom characters), all you have to do is just load them into character directly something like this:

    local PID = Player.UserId
    local PlayerAppearance = game.Players:GetCharacterAppearanceAsync(PID)
    task.wait()
    for PlayerAccessories, Accessories in pairs(PlayerAppearance:GetChildren()) do
         if Accessories:IsA("Accessory") then
                Accessories.Parent = Character
                task.wait()
         end
    end
    PlayerAppearance:Destroy()

1 Like
local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local StarterPlayer = game:GetService("StarterPlayer")

local defaultStarterCharacter = ServerStorage:FindFirstChild("StarterCharacter")
if not defaultStarterCharacter then
	error("StarterCharacter not found in ServerStorage")
end
defaultStarterCharacter.Parent = StarterPlayer

Players.PlayerAdded:Connect(function(player)
	local playerUserId = player.UserId
	local characterAppearance = Players:GetCharacterAppearanceAsync(playerUserId)

	if not player.Character then
		player.CharacterAdded:Wait()
	end

	for _, accessory in characterAppearance:GetChildren() do
		if accessory:IsA("Accessory") then
			accessory.Parent = player.Character
		end
	end

	characterAppearance:Destroy()
end)

However I would just put the StarterCharacter directly under StarterPlayer so you could simplify to

local Players = game:GetService("Players")

Players.PlayerAdded:Connect(function(player)
	local playerUserId = player.UserId
	local characterAppearance = Players:GetCharacterAppearanceAsync(playerUserId)

	if not player.Character then
		player.CharacterAdded:Wait()
	end

	for _, accessory in characterAppearance:GetChildren() do
		if accessory:IsA("Accessory") then
			accessory.Parent = player.Character
		end
	end

	characterAppearance:Destroy()
end)

Instead of wait(5) to make sure the character accessories have loaded, you can use Player.CharacterAppearanceLoaded. But you should look at the above replies as well.