Hello, so as you can see:
I currently have an outfit viewer model that is scripted perfectly, but it’s missing one thing.
I don’t understand how to make the outfit (on the left), look almost realistic and real-time with idle animations. Also possibly allowing the users, to interact with the viewport frame to move the model like 3D.
Example of what I mean:
Basically make it look like the Avatar Catalog, allowing the players to turn it around and so forth like you would when editing your avatar.
How can I possibly achieve this?
Current coding -
local NPC = nil
----------------------------------[[ VIEWPORT PORTION ]]------------------------------
-- Settings
local OFFSET = CFrame.new(0,2.5,-7)
-- Services
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
-- Objects
local ViewPort = script.Parent.ImageLabel:WaitForChild("ViewportFrame")
local Camera = Instance.new("Camera")
ViewPort.CurrentCamera = Camera
local ValidClasses = {
["MeshPart"] = true; ["Part"] = true; ["Accoutrement"] = true;
["Pants"] = true; ["Shirt"] = true;
["Humanoid"] = true;
}
local RenderObjects = table.create(25)
local function RemoveObject(Object)
local Clone = RenderObjects[Object]
if not Clone then return nil end
RenderObjects[Object] = nil
if Clone.Parent:IsA("Accoutrement") then
Clone.Parent:Destroy()
else
Clone:Destroy()
end
--print("Removed",Object)
end
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" 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
----------------------------------[[ EVENT PORTION ]]------------------------------
ShowUIEvent.OnClientEvent:Connect(function(NPCEvent)
NPC = NPCEvent
WooshSound:Play()
script.Parent.Visible = true
----------------------------------[[ VIEWPORT PORTION ]]------------------------------
RunService.Heartbeat:Connect(function()
if (not NPC:FindFirstChild("HumanoidRootPart")) or (not ViewPort.Visible) then
return nil
end
-- Update camera
Camera.CFrame = CFrame.new(NPC.HumanoidRootPart.CFrame:ToWorldSpace(OFFSET).Position, NPC.HumanoidRootPart.Position)
-- Update objects
for Original, Clone in pairs(RenderObjects) do
if Original and Original.Parent then
Clone.CFrame = Original.CFrame
else
RemoveObject(Original)
end
end
end)
local function HandleChar()
--warn("Handle char")
table.clear(RenderObjects)
ViewPort:ClearAllChildren()
local Viewmodel = Instance.new("Model")
Viewmodel.Name = "PlayerViewmodel"
Viewmodel.Parent = ViewPort
local CharObjects = NPC:GetDescendants()
for i, Object in pairs(CharObjects) do
local RenderClone = AddObject(Object)
if RenderClone then
RenderClone.Parent = Viewmodel
end
end
NPC.DescendantAdded:Connect(function(NewObject)
local RenderClone = AddObject(NewObject)
if RenderClone then
RenderClone.Parent = Viewmodel
end
end)
NPC.DescendantRemoving:Connect(function(OldObject)
RemoveObject(OldObject)
end)
end
HandleChar()
----------------------------------[[ ACCESSORIES PORTION ]]------------------------------
for _, Child in ipairs(script.Parent.ScrollingFrame:GetChildren()) do
if Child:IsA("Frame") then
Child:Destroy()
end
end
local Accessories = {}
local Backs = NPC.Humanoid:WaitForChild("HumanoidDescription").BackAccessory
local BacksTable = Backs:split(",")
for _, Back in ipairs(BacksTable) do
if Back ~= 0 then
if tonumber(Back) then
table.insert(Accessories, Back)
end
end
end
local Face = NPC.Humanoid:WaitForChild("HumanoidDescription").FaceAccessory
local FaceTable = Face:split(",")
for _, FaceAC in ipairs(FaceTable) do
if FaceAC ~= 0 then
if tonumber(FaceAC) then
table.insert(Accessories, FaceAC)
end
end
end
local Fronts = NPC.Humanoid:WaitForChild("HumanoidDescription").FrontAccessory
local FrontsTable = Fronts:split(",")
for _, Front in ipairs(FrontsTable) do
if Front ~= 0 then
if tonumber(Front) then
table.insert(Accessories, Front)
end
end
end
local Hairs = NPC.Humanoid:WaitForChild("HumanoidDescription").HairAccessory
local HairsTable = Hairs:split(",")
for _, Hair in ipairs(HairsTable) do
if Hair ~= 0 then
if tonumber(Hair) then
table.insert(Accessories, Hair)
end
end
end
local Hats = NPC.Humanoid:WaitForChild("HumanoidDescription").HatAccessory
local HatsTable = Hats:split(",")
for _, Hat in ipairs(HatsTable) do
if Hat ~= 0 then
if tonumber(Hat) then
table.insert(Accessories, Hat)
end
end
end
local Necks = NPC.Humanoid:WaitForChild("HumanoidDescription").NeckAccessory
local NecksTable = Necks:split(",")
for _, Neck in ipairs(HatsTable) do
if Neck ~= 0 then
if tonumber(Neck) then
table.insert(Accessories, Neck)
end
end
end
local Shoulders = NPC.Humanoid:WaitForChild("HumanoidDescription").ShouldersAccessory
local ShouldersTable = Shoulders:split(",")
for _, Shoulder in ipairs(ShouldersTable) do
if Shoulder ~= 0 then
if tonumber(Shoulder) then
table.insert(Accessories, Shoulder)
end
end
end
local Waists = NPC.Humanoid:WaitForChild("HumanoidDescription").WaistAccessory
local WaistsTable = Waists:split(",")
for _, Waist in ipairs(WaistsTable) do
if Waist ~= 0 then
if tonumber(Waist) then
table.insert(Accessories, Waist)
end
end
end
local Face = NPC.Humanoid:WaitForChild("HumanoidDescription").Face
if tonumber(Face) then
table.insert(Accessories, Face)
end
local Shirt = NPC.Humanoid:WaitForChild("HumanoidDescription").Shirt
if tonumber(Shirt) then
table.insert(Accessories, Shirt)
end
local Pants = NPC.Humanoid:WaitForChild("HumanoidDescription").Pants
if tonumber(Pants) then
table.insert(Accessories, Pants)
end
local GraphicTShirt = NPC.Humanoid:WaitForChild("HumanoidDescription").GraphicTShirt
if tonumber(GraphicTShirt) then
table.insert(Accessories, GraphicTShirt)
end
local AddedTable = {}
for _, ID in ipairs(Accessories) do
if ID ~= 0 then
if tonumber(ID) then
if not table.find(AddedTable, ID) then
table.insert(AddedTable, ID)
local Template = script.Template
local NewTemplate = Template:Clone()
NewTemplate.ProductIDVal.Value = ID
NewTemplate.AssetIcon.Image = "https://www.roblox.com/asset-thumbnail/image?assetId=" .. ID .. "&width=420&height=420&format=png"
NewTemplate.Parent = script.Parent.ScrollingFrame
end
end
end
end
end)