Roblox UGC developers want to go above and beyond with their designs for the catalog but they’re restricted to using low quality textures unless they decide that R6 textures will just have to take the L.
Noticing this issue I made a script for R6 developers to use so UGC developers can have the highest quality items in your games as well as R15, as opposed to the blurry mess you might be used to.
My brief explanation is that it’s a simply hacky method that just takes a hat and cframes it on the character rather than loading it normally through the character. High quality items just can’t be made on R6 characters because of the way those character models are rendered so until Roblox does something to fix that (if they do), the high quality UGC items will be restricted to R15 experiences (without this script).
local InsertService = game:GetService("InsertService")
local AccessoryCache = {}
function LoadAccessory(id, Humanoid, c, AccessoryType)
local t = c:FindFirstChild("Torso")
if t and id then
if AccessoryCache[id] then
local NewAccessory = AccessoryCache[id]:Clone()
NewAccessory.Parent = c
local AttachmentType = NewAccessory:FindFirstChildOfClass("Attachment").Name
local AttachmentOnBody = c:FindFirstChild(AttachmentType, true)
local AttachmentPart = AttachmentOnBody.Parent
local Weld = Instance.new("WeldConstraint", NewAccessory)
Weld.Part0 = NewAccessory
NewAccessory.CFrame = AttachmentOnBody.WorldCFrame * NewAccessory[AttachmentType].CFrame:Inverse()
Weld.Part1 = AttachmentPart
else
local NewAccessory = InsertService:LoadAsset(id):GetChildren()[1].Handle
if NewAccessory then
NewAccessory.CanCollide = false
NewAccessory.CanQuery = false
NewAccessory.CanTouch = false
NewAccessory.Massless = true
NewAccessory.Name = "Accessory"
AccessoryCache[id] = NewAccessory:Clone()
NewAccessory.Parent = c
local AttachmentType = NewAccessory:FindFirstChildOfClass("Attachment").Name
local AttachmentOnBody = c:FindFirstChild(AttachmentType, true)
local AttachmentPart = AttachmentOnBody.Parent
local Weld = Instance.new("WeldConstraint", NewAccessory)
Weld.Part0 = NewAccessory
NewAccessory.CFrame = AttachmentOnBody.WorldCFrame * NewAccessory[AttachmentType].CFrame:Inverse()
Weld.Part1 = AttachmentPart
end
end
end
end
function CharacterSetup(c)
local Humanoid = c:WaitForChild("Humanoid")
if Humanoid and Humanoid.RigType ~= Enum.HumanoidRigType.R15 then
local GHD = Humanoid:GetAppliedDescription()
Humanoid:RemoveAccessories()
if GHD then
if tostring(GHD.BackAccessory) ~= nil then for _,id in pairs(string.split(GHD.BackAccessory, ",")) do LoadAccessory(tonumber(id), Humanoid, c) end end
if tostring(GHD.FaceAccessory) ~= nil then for _,id in pairs(string.split(GHD.FaceAccessory, ",")) do LoadAccessory(tonumber(id), Humanoid, c) end end
if tostring(GHD.FrontAccessory) ~= nil then for _,id in pairs(string.split(GHD.FrontAccessory, ",")) do LoadAccessory(tonumber(id), Humanoid, c) end end
if tostring(GHD.HairAccessory) ~= nil then for _,id in pairs(string.split(GHD.HairAccessory, ",")) do LoadAccessory(tonumber(id), Humanoid, c) end end
if tostring(GHD.HatAccessory) ~= nil then for _,id in pairs(string.split(GHD.HatAccessory, ",")) do LoadAccessory(tonumber(id), Humanoid, c) end end
if tostring(GHD.NeckAccessory) ~= nil then for _,id in pairs(string.split(GHD.NeckAccessory, ",")) do LoadAccessory(tonumber(id), Humanoid, c) end end
if tostring(GHD.ShouldersAccessory) ~= nil then for _,id in pairs(string.split(GHD.ShouldersAccessory, ",")) do LoadAccessory(tonumber(id), Humanoid, c) end end
if tostring(GHD.WaistAccessory) ~= nil then for _,id in pairs(string.split(GHD.WaistAccessory, ",")) do LoadAccessory(tonumber(id), Humanoid, c) end end
end
end
end
function PlayerSetup(p)
p.CharacterAppearanceLoaded:Connect(function(c)
CharacterSetup(c)
end)
end
for _,p in pairs(game.Players:GetPlayers()) do task.spawn(function() PlayerSetup(p) end) end
game.Players.PlayerAdded:Connect(function(p) task.spawn(function() PlayerSetup(p) end) end)
You can also grab it as a model here.