Trouble with Clothing Items when trying to Instance.new Them

Hey! I was attempting to create a Pants Class Object using Instance.new but I’m having difficulty getting it to show up. Here’s the code:

--BTW the clothing ids I'm using are temporary and I WILL be making my own
local Players = game:GetService("Players")
local LPlayer = Players.LocalPlayer

local ArmorStats = LPlayer:WaitForChild("ArmorStats")
local ArmorLevel = ArmorStats:WaitForChild("ArmorLevel")

--CHARACTER VARIABLES

local Character = LPlayer.Character
local Humanoid = Character:WaitForChild("Humanoid")
local HumanoidDescription = Humanoid:WaitForChild("HumanoidDescription")

--VARIABLES FOR DESTROYING EXISTING PANTS/SHIRTS

local FindShirt = Humanoid.Parent:FindFirstChildOfClass("Shirt")
local FindPants = Humanoid.Parent:FindFirstChildOfClass("Pants")

--SCALE MAIL

local ScaleMailShirtID = "http://www.roblox.com/asset/?id=16830394419"
local ScaleMailPantsID = "http://www.roblox.com/asset/?id=6406161274"

--LEATHER ARMOR

local LeatherShirtID = "http://www.roblox.com/asset/?id=689274616"
local LeatherPantsID = "http://www.roblox.com/asset/?id=15407496769"

--SKIRMISHER'S TUNIC

local SkirmisherTunicID = "http://www.roblox.com/asset/?id=4615264881" --The Skirmisher's Tunic is pants


ArmorLevel.Changed:Connect(function()
	
	
	if FindPants or FindShirt then
		FindShirt:Destroy()
		FindPants:Destroy()
	end
	
	
	print(LPlayer.Name .. "'s character is recieving the changes made in ArmorLevel")
	
	if ArmorLevel.Value == 1 then
		
		print(LPlayer.Name .. "'s Armor Level is " .. tostring(ArmorLevel.Value) .. " so the proper clothing is being worn")
		
		local SkirmishShirt = Instance.new("Pants")
		SkirmishShirt.Name = "SkirmisherTunic"
		SkirmishShirt.Parent = Character
		SkirmishShirt.PantsTemplate = SkirmisherTunicID
		SkirmishShirt.Color3 = Color3.new(255, 255, 255)
		
		HumanoidDescription.Pants = 4615264881
		
		print(SkirmishShirt.Name, tostring(SkirmishShirt.Color3), SkirmishShirt.Parent, SkirmishShirt.PantsTemplate)
		
	end
	
end)

I tried running the part of the code that makes the Pants item in a normal script but it didn’t work. All of my print commands work so nothing’s being skipped over. The Localscript this code is in is parented in StarterCharacterScripts, so it’s put in the character at spawn.

Any help is greatly appreciated! Thank you for reading!

1 Like

I think you need to parent it to the humanoid of the character, not the character.


edit: Also, you need to update the FindPants and FindShirt variables within the changed statement.

2 Likes

Didn’t work. Maybe something is wrong with the ID? That’s my best theory

1 Like

I believe the ID you need is separate from the clothing ID. You can get the IDs by inserting the item with the InsertService then getting the ID from the created instance.

I would recommend adding pants and shirts to a character using the humanoid description and Humanoid:ApplyDescription. That’s the intended way to add them at least.

With AddDescription, just copy the humanoid description of the player (it needs to be a new copy), set the .Shirt and .Pants properties, then apply the changes with Humanoid:ApplyDescription.

Note that this only works with properly formatted rigs, you can force the rig to be formatted properly with Humanoid:ApplyDescriptionReset (note this removes tools and stuff, and that regular character rigs are formatted properly before changes).

2 Likes

So I’d first change the HumanoidDescription and then update it with AddDescription?

1 Like

Yep. You’d get the FindFirstChildOfClass("HumanoidDescription") of the rig’s Humanoid, make a copy of the HumanoidDescription, set the .Shirt and/or .Pants properties, then call RigHumanoid:ApplyDescription(ClonedDescription).

2 Likes

It came back with an error:

17:43:04.470 Humanoid::ApplyDescription() can only be called by the backend server - Client - ConfigureArmorCharacter:61

2 Likes

Oh, that could be a problem: ApplyDescription can only be called from the server (i.e. not local scripts).

If you need to do it from the client, your original method would be better. To fix the original way, you probably need to get the correct asset IDs by using the insert service.

Edit:
You also might need to move these lines

inside the changed connection, so that each time the changed event happens it can remove the current Shirt and Pants, instead of only the first pair to ever exist.

2 Likes

How would I accomplish this? I saw that there was an InsertionHash parented to the service but I don’t know how to add it onto the asset ID, since it’s a string. Checked the Docs but oddly enough there wasn’t anything on it about the InsertionHash thing.

1 Like

You could call:

local ITEM_ID = --[The number in the URL on the website]
-- Support ctrl z (not really needed in this case since it's only adding an item)
local ChangeHistoryService = game:GetService("ChangeHistoryService")
local InsertService = game:GetService("InsertService")
local recording = ChangeHistoryService:TryBeginRecording("Adding item")
if recording then
    local newItem = InsertService:LoadAsset(ITEM_ID)
    newItem.Parent = workspace
    game:GetService("Selection"):Set({newItem})
    ChangeHistoryService:FinishRecording(recording, Enum.FinishRecordingOperation.Commit)
    
else
    warn("Failed to support ctrl z")
end

which would add the shirt/pants into workspace and select it, then in properties you could get the image id it uses.

2 Likes

InsertService can’t be used in LocalScripts :frowning_face:
Would it be better to make it a server script instead?

1 Like

This may be wrong… looks out of place. Not sure what isn’t working…
Possibly: HumanoidDescription.Pants = 4615264881 is added to the local but never applied with
Humanoid:ApplyDescription(HumanoidDescription)
could use after char load …

rs=game:GetService(“RunService”)

task.wait(0.22)
des=pls:GetHumanoidDescriptionFromUserId(LPlayer.UserId)
des.Pants = 4615264881 rs.Stepped:Wait()
Humanoid:ApplyDescription(des)

The pauses help, pretty much needed. Of course rs= is up top in the script.

3 Likes

Yeah, I made the variable’s name before I decided to switch to Pants. It shouldn’t affect anything too much to my knowledge

1 Like

I mean you can use that code in the cmd bar to get the correct IDs, then you can store the IDs in your local script.

2 Likes

Didn’t work either. Sorry for it being difficult. As for BendsSpace’s idea for putting things into the Command Bar, I’d rather have it all in one script and I’m not familiar with the command bar anyways

1 Like

The command bar lets you run code in studio. You can go to [ribbon bar] → View → Cmd bar (it’s probably a little box that looks like >_). Then, you can run the code I sent to create a Pants/Shirt instance from a catalog item ID. Then you can take the asset ID from the newly made Pants/Shirt instance and store it in your script in place of these:

1 Like

I just realized that is a server script snip.
→ SeverScript @ServerScriptService

local des,dfp,dfs,pid
dfp,dfs=4637601297,4637596615
rs=game:GetService("RunService")
local pls=game:GetService("Players")
pls.PlayerAdded:Connect(function(plr)
	plr:WaitForChild("PlayerGui")pid=plr.UserId
	plr.characterAdded:Connect(function(chr)
		repeat rs.Stepped:Wait()until plr.Character
		task.wait(0.22)des=pls:GetHumanoidDescriptionFromUserId(pid)
		des.Pants=dfp des.Shirt=dfs rs.Stepped:Wait()
		chr.Humanoid:ApplyDescription(des)
	end) 
end)

Just tested this. Puts on a shirt and pants on login/spawn.
Timing counts and I think you might have to own the items or use free ones.

Glad you found this useful, here is the rest of that snip… it’s placed right after
chr.Humanoid:ApplyDescription(des)

for _,a in pairs(chr.Humanoid:GetAccessories())do
	if a.AccessoryType~=Enum.AccessoryType.Hair and
		a.AccessoryType~=Enum.AccessoryType.Eyelash and
		a.AccessoryType~=Enum.AccessoryType.Eyebrow then
		a:Destroy()
	end
end

Removes all accessories. Considering animated faces and hair. If you also would like to do that.

After that I’ve started using: plr.PlayerGui.fade.fade.Value=true
To set a trigger to a screen fade-in, making up for the small amount of time this takes to finish.
(That is slightly visible otherwise without the cover up.) This also ended up not being needed as a normal screen fade-in is plenty of time to cover this up…

3 Likes

Just came back with ‘attempt to index nil with ‘LoadAsset’’ on line 4.

I fixed the code. It needed InsertService to be defined.

A humanoid’s description ideally isn’t meant to be modified directly. Instead, the description should be copied, modified, then applied. The description stores its changes, so it potentially won’t apply the changes if they’re already in the current description.

I suppose that works then. If ApplyDescription is called with a copy it works without needed to wait, which might be more reliable.

I just found out through testing that file [HumanoidDescription] needs to be write-in to and read with a bit of timing, other than that works as is it documented. Only routine I’ve ran across yet that need a bit of special consideration.

This seems out of place: repeat rs.Stepped:Wait()until plr.Character … but is this case working with the extra file HumanoidDescription the tested minimum for me of task.wait(0.22) is needed for that to finish updating, after plr.Character is locked in.

1 Like