How to apply jacket accessory to ViewPort character model?

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

Apply any jacket accessory to a live viewport of a character with correct placement.

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

When applied directly to a viewport model vs what happens if I keep the model in workspace

image

The character erratically flings away to the 7 galaxies, but only locally, not replicated to other clients since the viewport model is created by a localscript. This wouldn’t happen if I didn’t introduce a wait() time, but introducing wait is necessary, because the accessories take time to apply properly. (I know that is simply strange, but instantly applying them and throwing the model into UI does the same thing as the previous picture shows)

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

Tried applying the accessories inside of the viewport, they mess up. Tried parenting accessories to the viewport character, they still mess up. The closest to a fix I got is setting the wait() the shortest possible and setting the CFrame of the target character back to its original position. This however does not work if the local client lags a little, causing the character to fling on any lower performance system.

The current code (half of it stolen from somewhere online):

FIRST FUNCTION TO RUN – here I made jackets go into a table to be applied later, as they were the problem. All other accessories are replicated immediately.

local function HandleChar()
	--warn("Handle char")

	table.clear(RenderObjects)
	ViewPort:ClearAllChildren()

	local Viewmodel = Instance.new("Model")
	Viewmodel.Name = "PlayerViewmodel"
	--Viewmodel.Parent = ViewPort
	Viewmodel.Parent = workspace.Temp
	local CharObjects = Character:GetDescendants()
	local accessoryTable = {}
	for i, Object in pairs(CharObjects) do
		if Object:IsA("Accessory") then
			if Object.AccessoryType == Enum.AccessoryType.Jacket then
				print("jacket found")
				table.insert(accessoryTable, Object)
			else
				local RenderClone = AddObject(Object)
				if RenderClone then
					RenderClone.Parent = Viewmodel
				end
			end
		elseif Object.Parent:IsA("Accessory") then
			if Object.Parent.AccessoryType ~= Enum.AccessoryType.Jacket then
				local RenderClone = AddObject(Object)
				if RenderClone then
					RenderClone.Parent = Viewmodel
				end
			end
		else
			local RenderClone = AddObject(Object)
			if RenderClone then
				RenderClone.Parent = Viewmodel
			end
		end
	end
	
	for i1, m1 in pairs(accessoryTable) do
		local newAcc = m1:Clone()
		--Viewmodel:FindFirstChild(m1.Name):Destroy()
		Viewmodel:FindFirstChild("Humanoid"):AddAccessory(newAcc)
	end
	Character.DescendantAdded:Connect(function(NewObject)
		local RenderClone = AddObject(NewObject)
		if RenderClone then
			RenderClone.Parent = Viewmodel
		end
	end)
	
	if Character:FindFirstChild("Humanoid") and #accessoryTable > 0 then
		local currLoc = Character.HumanoidRootPart.CFrame
		Viewmodel.PrimaryPart = Viewmodel:FindFirstChild("HumanoidRootPart")
		Viewmodel.PrimaryPart:PivotTo(workspace.VIEWPORTPLACE.CFrame)
		wait()
		Viewmodel.Parent = ViewPort
		Character.HumanoidRootPart.CFrame = currLoc
	end
	
	Viewmodel.Parent = ViewPort
	Character.DescendantRemoving:Connect(function(OldObject)
		RemoveObject(OldObject)
	end)
end

SECOND FUNCTION TO RUN

local ValidClasses = {
	["MeshPart"] = true; ["Part"] = true; ["Accoutrement"] = true;
	["Pants"] = true; ["Shirt"] = true;
	["Humanoid"] = true; ["BasePart"] = true;
}
local function AddObject(Object)
	if not ValidClasses[Object.ClassName] then
		return nil
	end

	-- Create clone, regardless of Archivable
	local a = Object.Archivable
	Object.Archivable = true
	local RenderClone = Object:Clone()
	Object.Archivable = a

	if Object.ClassName == "MeshPart" or Object.ClassName == "Part" or Object.ClassName == "BasePart" then
		RenderObjects[Object] = RenderClone
	elseif Object:IsA("Accoutrement") then
		RenderObjects[Object.Handle] = RenderClone.Handle

	elseif Object.ClassName == "Humanoid" then
		--Disable all states. We only want it for clothing wrapping.
		RenderClone:SetStateEnabled(Enum.HumanoidStateType.FallingDown,			false)
		RenderClone:SetStateEnabled(Enum.HumanoidStateType.Running,				false)
		RenderClone:SetStateEnabled(Enum.HumanoidStateType.RunningNoPhysics,	false)
		RenderClone:SetStateEnabled(Enum.HumanoidStateType.Climbing,			false)
		RenderClone:SetStateEnabled(Enum.HumanoidStateType.StrafingNoPhysics,	false)
		RenderClone:SetStateEnabled(Enum.HumanoidStateType.Ragdoll,				false)
		RenderClone:SetStateEnabled(Enum.HumanoidStateType.GettingUp,			false)
		RenderClone:SetStateEnabled(Enum.HumanoidStateType.Jumping,				false)
		RenderClone:SetStateEnabled(Enum.HumanoidStateType.Landed,				false)
		RenderClone:SetStateEnabled(Enum.HumanoidStateType.Flying,				false)
		RenderClone:SetStateEnabled(Enum.HumanoidStateType.Freefall,			false)
		RenderClone:SetStateEnabled(Enum.HumanoidStateType.Seated,				false)
		RenderClone:SetStateEnabled(Enum.HumanoidStateType.PlatformStanding,	false)
		RenderClone:SetStateEnabled(Enum.HumanoidStateType.Dead,				false)
		RenderClone:SetStateEnabled(Enum.HumanoidStateType.Swimming,			false)
		RenderClone:SetStateEnabled(Enum.HumanoidStateType.Physics,				false)
		RenderClone.DisplayDistanceType = Enum.HumanoidDisplayDistanceType.None
	end

	--print("Added",Object)

	return RenderClone
end

I have fixed it, and for anyone else who is using Heartbeat updated Viewports, here is the solution:

“RunService.Heartbeat:Connect(function()
if updating == false then”

Make sure you have a condition that checks if you are cloning or modifying a character model, so that your update function won’t mess with it until you have finished cloning/modifying a target viewport character in workspace. If you’re experiencing issues of this kind, feel free to message me and I may be able to help you.

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