World Model Animations play but do not display in the Viewport Frame

Character model appears in the World Model and Viewport. When I play the animation and use :GetPlayingAnimationTracks() it shows that my animation is indeed playing. However, if you look at the viewport frame, the animation isn’t being rendered. Please help :slight_smile:

Video

Code

local REPLICATED_STORAGE = game:GetService("ReplicatedStorage")
local SHARED_SERVICES = REPLICATED_STORAGE:WaitForChild("Shared Services")
local SHARED_STORAGE = REPLICATED_STORAGE:WaitForChild("Shared Storage")

local CLIENT_DATA_SERVICE = require(SHARED_SERVICES["Client Data Service"])
local BRAWLBLOXIAN_TEMPLATE = SHARED_STORAGE.UI["Brawlbloxian Template"]
local CLIENT_DATA_FOLDER

repeat CLIENT_DATA_FOLDER = CLIENT_DATA_SERVICE:GetPlayerDataFolder(CLIENT) wait() until CLIENT_DATA_FOLDER

local FRAME = script.Parent

function update_frames()
	for _,v in pairs(CLIENT_DATA_FOLDER.Brawlbloxians:GetChildren()) do
		if not FRAME:FindFirstChild(v.Name) then
			local NEW_FRAME = BRAWLBLOXIAN_TEMPLATE:Clone()
			NEW_FRAME.Name = v.Name
			NEW_FRAME.Folder.Value = v
			NEW_FRAME["Brawlbloxian Name"].Text = v.Name
			NEW_FRAME.Parent = FRAME
			
			local VIEWPORT = Instance.new("ViewportFrame")
			VIEWPORT.Size = UDim2.new(0.835, 0,0.75, 0)
			VIEWPORT.Position = UDim2.new(0.078, 0,0.2, 0)
			VIEWPORT.Parent = NEW_FRAME
			VIEWPORT.BackgroundTransparency = 1
			
			local WORLD_MODEL = Instance.new("WorldModel", VIEWPORT)

			local TARGET_MODEL = v["Owned Variants"]:WaitForChild(v.Name.."_Original")
			for _,v in pairs(TARGET_MODEL:GetChildren()) do
				local cloned_part = v:Clone()
				cloned_part.Parent = WORLD_MODEL
				if v:IsA("BasePart") then
					v.Anchored = false
				end
			end
			
			WORLD_MODEL.PrimaryPart = WORLD_MODEL:WaitForChild("HumanoidRootPart")
			WORLD_MODEL:SetPrimaryPartCFrame(CFrame.new(0, 0, 0)* CFrame.fromEulerAnglesXYZ(0, math.rad(180), 0)) 
			
			local CAMERA = Instance.new("Camera", VIEWPORT)
			VIEWPORT.CurrentCamera = CAMERA
			CAMERA.CFrame = CFrame.new(0, 0 ,4.2)
			
			local ANIMATION = WORLD_MODEL.Humanoid.Animator:LoadAnimation(SHARED_STORAGE.Animations:WaitForChild("Natalie Idle 1"))
			ANIMATION:Play()
			print(WORLD_MODEL.Humanoid.Animator:GetPlayingAnimationTracks())
			
			v.ChildAdded:Connect(update_frames)
			v.ChildRemoved:Connect(update_frames)
			
			break
		end
	end
end

--CLIENT_DATA_FOLDER.Brawlbloxians.ChildAdded:Connect(update_frames)
--CLIENT_DATA_FOLDER.Brawlbloxians.ChildRemoved:Connect(update_frames)
update_frames()

Correct me if I am wrong, but you only run the update code once, this means that the parts do get transferred, but they are separated, not linked. Another thing is I do not know if that is the problem, but physics can’t be rendered inside a viewport frame, maybe animations can’t as well.

If that is the problem my workaround is to each render stepped, you update the parts inside the viewport so that it copies the player model.

1 Like

I’ve always found ViewportFrames to be really annoying when it comes to animations

I recommend using RenderStepped. Loop through all the parts of the player’s character in the ViewportFrame and have them be the same CFrame as the world model.

This is how I would do it for basic dummy rigs:

local RS = game:GetService("RunService")

local worldChar = workspace.Character -- the world model
local viewportChar = viewportFrame.Character -- viewport model
local viewportParts = {}
RS.RenderStepped:Connect(function()
    if #viewportParts <= 0 then
        for _, obj in pairs(viewportChar:GetChildren()) do
            if obj:IsA("BasePart") or obj:IsA("MeshPart") or obj:IsA("UnionOperation") then
                table.insert(viewportParts, obj)
            end
        end
    end
    -- assuming both models are clones, they should have the same exact parts
    for _, part in pairs(viewportParts) do
        part.CFrame = worldChar[part.Name].CFrame
    end
end)

Once this is done, all you have to do is play an animation on the world character and the viewport character will just copy it

1 Like

* You need to place your model inside a World Model to play animation in it

Never mind realized you were using a World Model

1 Like

Thanks for replying. The update code only runs once for the sake of testing. The parts are transferred from an existing model to a World Model. I’ve had this work before with previous code, but now it’s not fuctioning. This is it in action yesterday without cloning parts from a model in storage.

I transferred all the parts into the world model from an existing model so I’m not sure why it isn’t working.

Thanks for the reply. Do you know if this is ressource consuming? Also I’d like to use world models because I know it can work I just want to figure out how.

Maybe it transfers before the animation, if you are saying the old script worked, maybe you also need to execute the animation of the viewport model separately

1 Like

Not if this is the only Viewport, and if you remove that after it isn’t needed anymore

1 Like

I’m not sure why it wasn’t working before, but after some messing around, I got it to work. I cloned the model into the viewport frame and then cloned each child rather than cloning each part individually from the existing model. Here’s the code if anyone needs help in the future.

function update_frames()
	for _,v in pairs(CLIENT_DATA_FOLDER.Brawlbloxians:GetChildren()) do
		if not FRAME:FindFirstChild(v.Name) then
			local NEW_FRAME = BRAWLBLOXIAN_TEMPLATE:Clone()
			NEW_FRAME.Name = v.Name
			NEW_FRAME.Folder.Value = v
			NEW_FRAME["Brawlbloxian Name"].Text = v.Name
			NEW_FRAME.Parent = FRAME
			
			local VIEWPORT = Instance.new("ViewportFrame")
			VIEWPORT.Size = UDim2.new(0.835, 0,0.75, 0)
			VIEWPORT.Position = UDim2.new(0.078, 0,0.2, 0)
			VIEWPORT.Parent = NEW_FRAME
			VIEWPORT.BackgroundTransparency = 1
			
			local WORLD_MODEL = Instance.new("WorldModel", VIEWPORT)

			local TARGET_MODEL = v["Owned Variants"]:WaitForChild(v.Name.."_Original"):Clone()
			TARGET_MODEL.Parent = WORLD_MODEL
			for _,v in pairs(TARGET_MODEL:GetChildren()) do
				v.Parent = WORLD_MODEL
			end
			TARGET_MODEL:Destroy()
			
			WORLD_MODEL.PrimaryPart = WORLD_MODEL:WaitForChild("HumanoidRootPart")
			WORLD_MODEL:SetPrimaryPartCFrame(CFrame.new(0, 0, 0)* CFrame.fromEulerAnglesXYZ(0, math.rad(180), 0)) 
			
			local CAMERA = Instance.new("Camera", VIEWPORT)
			VIEWPORT.CurrentCamera = CAMERA
			CAMERA.CFrame = CFrame.new(0, 0 ,4.2)
			
			local ANIMATION = WORLD_MODEL.Humanoid.Animator:LoadAnimation(SHARED_STORAGE.Animations:WaitForChild("Natalie Idle 1"))
			ANIMATION:Play()
			print(WORLD_MODEL.Humanoid.Animator:GetPlayingAnimationTracks())
			
			v.ChildAdded:Connect(update_frames)
			v.ChildRemoved:Connect(update_frames)
			
			break
		end
	end
end

--CLIENT_DATA_FOLDER.Brawlbloxians.ChildAdded:Connect(update_frames)
--CLIENT_DATA_FOLDER.Brawlbloxians.ChildRemoved:Connect(update_frames)
update_frames()
1 Like

I think I know why, but this is just speculation. Something similar happens with object values

So when you clone the entire thing, the environment stays the same. In the object value example, if the object value is a part for example, if you clone the entire environment it will clone the object value pointing to that new part. If you clone the object value separately it will point to the old value (the old part), since all of them weren’t made in the same time, in the same environment.

My guess is that cloning each thing individually made so that the animation pointed to the old parts or simply stopped working, since they weren’t all cloned in the same environment.

1 Like