So, I have my system which clones the player’s model into a viewport frame. However, the hats on the character that is in the ViewportFrame(ViewportFrameCharacter), are being glitchy. I put the ViewportFrame Character model in workspace to see if the hats would still glitch out; however, the hats were normally placed. Does anyone have any clue on why this occurs?
local RunService = game:GetService('RunService')
local Players = game:GetService("Players")
local player = Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character:WaitForChild("Humanoid")
local viewportFrame = script.Parent
local viewportFrameCamera = Instance.new("Camera")
local viewportFrameCharacter = Instance.new("Model") -- frame character
local viewportProxyCharacter = Instance.new("Model") -- proxy
local anims = script.animations
local part = workspace.Part
local sword = script.Parent.sword
local idleAnim
viewportFrame.CurrentCamera = viewportFrameCamera
viewportFrameCamera.Parent = viewportFrame
viewportFrameCharacter.Name = player.Name
viewportProxyCharacter.Parent = workspace
viewportProxyCharacter.Name = player.Name
wait(2)
for _,v in pairs(character:GetChildren()) do
v:Clone().Parent = viewportFrameCharacter
v:Clone().Parent = viewportProxyCharacter
end
viewportFrameCharacter.PrimaryPart = viewportFrameCharacter.HumanoidRootPart
viewportProxyCharacter.PrimaryPart = viewportProxyCharacter.HumanoidRootPart
local proxyHumanoid = viewportProxyCharacter:FindFirstChild("Humanoid")
idleAnim = proxyHumanoid:LoadAnimation(anims.idle)
idleAnim:Play()
sword:Clone().Parent = viewportFrameCharacter
sword:Clone().Parent = viewportProxyCharacter
viewportProxyCharacter:MoveTo(part.Position)
viewportFrameCharacter.Parent = viewportFrame
RunService:BindToRenderStep("UpdateVPCharacter", Enum.RenderPriority.Last.Value, function()
viewportFrameCamera.CFrame = viewportFrameCharacter.HumanoidRootPart.CFrame*CFrame.new(0,0,-5.5,0,1,0,0)
local realCharacter = viewportProxyCharacter
if realCharacter then
for _, descendant in pairs(viewportFrameCharacter:GetDescendants()) do
if descendant:IsA("BasePart") then
local realMotor = realCharacter:FindFirstChild(descendant.Name, true)
if realMotor then
--print(typeof(descendant) ,typeof( realMotor))
-- print(typeof(descendant.CFrame) ,typeof( realMotor.CFrame))
descendant.CFrame = realMotor.CFrame
end
end
end
end
end)
It’s possible that there are some instances in your character with the same name, which could mean you’re setting the wrong CFrame. Instead of finding the parts in the other character using its name, you could create a table where each key is the viewportProxyCharacter’s part, and the value is the viewportFrameCharacter’s part. Then, instead of looping through the model, you would loop through the table and set the value’s CFrame to the key’s CFrame.
It’s what @slo_w mentioned, as part names of hats are usually named Handles, and having more than one hat will set all the other hats to the same CFrame. The above methods works too but if you prefer to stick with what you wrote you can include this:
local RunService = game:GetService('RunService')
local Players = game:GetService("Players")
local player = Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character:WaitForChild("Humanoid")
local viewportFrame = script.Parent
local viewportFrameCamera = Instance.new("Camera")
local viewportProxyCharacter = Instance.new("Model")
local anims = script.animations
local part = workspace.Part
local sword = script.Parent.sword
local idleAnim
viewportFrame.CurrentCamera = viewportFrameCamera
viewportFrameCamera.Parent = viewportFrame
viewportProxyCharacter.Parent = workspace
viewportProxyCharacter.Name = player.Name
wait(2)
for _,v in pairs(character:GetChildren()) do
v:Clone().Parent = viewportProxyCharacter
end
viewportProxyCharacter.PrimaryPart = viewportProxyCharacter.HumanoidRootPart
local proxyHumanoid = viewportProxyCharacter:FindFirstChild("Humanoid")
idleAnim = proxyHumanoid:LoadAnimation(anims.idle)
idleAnim:Play()
sword:Clone().Parent = viewportProxyCharacter
viewportProxyCharacter:MoveTo(part.Position)
for _, descendant in pairs(viewportProxyCharacter:GetDescendants()) do -- added to rename handle hat parts
if descendant:IsA("BasePart") and descendant.Parent:IsA("Accoutrement") then
descendant.Name = descendant.Name..descendant.Parent.Name
wait()
end
end
local viewportFrameCharacter = viewportProxyCharacter:Clone()
viewportFrameCharacter.Parent = viewportFrame
RunService:BindToRenderStep("UpdateVPCharacter", Enum.RenderPriority.Last.Value, function()
viewportFrameCamera.CFrame = viewportFrameCharacter.HumanoidRootPart.CFrame*CFrame.new(0,0,-5.5,0,1,0,0)
local realCharacter = viewportProxyCharacter
if realCharacter then
for _, descendant in pairs(viewportFrameCharacter:GetDescendants()) do
if descendant:IsA("BasePart") then
local realMotor = realCharacter:FindFirstChild(descendant.Name, true)
if realMotor then
descendant.CFrame = realMotor.CFrame
end
end
end
end
end)
That should fix the hats.
Edit: What now happens is just before the viewportFrameCharacter is created and sent to the Viewport, I included in a loop to check for accessories and to include their accessory name along with the original handle part to prevent duplicate handles being found when you search and update any baseparts.