ViewPortFrame Character Animation

So I’ve noticed that you can’t animate character models within a ViewPortFrame.
Doing some research, I found a post about updating Motor6D with Transform.

My problem is that my script doesn’t seem to work.

c = Character model in ViewPortFrame
proxyAnim = Table containing actual player character’s Motor6 instances

	for _,v in pairs(proxyAnim) do
		c:FindFirstChild(v.Name,true).Transform = v.Transform
until dead

I’ve printed both values and it outputs that it’s updating, but the character model in the ViewPortFrame isn’t changing nor are its Motor6 instances. But even changing them manually doesn’t seem to do anything in Studio. Does this no longer work or am I doing something wrong?

If this is no longer possible, I plan on simply updating all of the BasePart CFrames.


Insert a WorldModel into the ViewportFrame and then parent the character model to it, then you can animate it just fine.


I just tried that and it doesn’t seem to make any difference? Is there something extra that I need to do to enable it?

1 Like

Did you attempt to play any animations on the character clone? You can’t just copy the character and hope that the duplicate automatically plays animations matching the actual character.

The gif below was set up using a ViewPortFrame and a WorldModel.


I copied the idle animation from my character in Studio and loaded that directly into the clone’s humanoid and played it. Nothing seems to have happened.

Can you provide an image of your setup in the explorer as well as the code you wrote?

In-Game PlayerGui:


function ang(x,y,z) return CFrame.Angles(math.rad(x),math.rad(y),math.rad(z)) end
local P = game:GetService('Players')
local p = P.LocalPlayer
local port = script.Parent:WaitForChild('Port')
local cam ='Camera',script)
local anim = script:WaitForChild('Animation1')
port.CurrentCamera = cam
if not p.Character then p.CharacterAdded:Wait() end
local c ='Model')
for _,v in pairs(p.Character:GetChildren()) do
	if not v:IsA('BaseScript') then
		v:Clone().Parent = c
c.Parent = port:WaitForChild('World')
cam.CFrame = c.HumanoidRootPart.CFrame*ang(0,180,0)*,0,5)
local idle = c.Humanoid:LoadAnimation(anim)
idle.Looped = true

(I know there are some parts that can be improved, but I’m just doing this for testing right now.)

You’re cloning the parts of the character and putting them in a new model - there’s no humanoid to load an animation to. There also wouldn’t be any joints. (Edit: Misread “BaseScript” as “BasePart”)

Set the Archivable property of the actual character to true (it’s false by default) and then you can just call :Clone() on the player’s character.


There actually is a Humanoid as shown here:

But your Archivable solution worked anyways. Thank you

1 Like

That’s my bad, misread “BaseScript” here as “BasePart” and thought it was just cloning the parts.

1 Like

:sandwich: I’d like to clarify how to make this work

  1. This is the hierarchy you need to have:

  2. It’s important that your model is placed inside a WorldModel, inside your ViewportFrame.

  3. To play your animation, you need to use a Script.

UPDATE: I’d just like to update and clarify that a local script will work too :point_up: :slight_smile:

  1. Inside the script you load your animationID and play your animation.

Here’s an example-script:

repeat wait() until script.Parent

local anim = script.Animation
local track = script.Parent.Humanoid.Animator:LoadAnimation(anim)
track.Looped = true

I hope this will help anyone in the future that is having trouble.


Hey, I tried this solution but it doesn’t work for me!
I’m using a module and a remote event to make this work.
I’m essentially using the exact same code as you and all the animation checks pass, am I doing something wrong?

Did you also use a WorldModel? Also I think a LocalScript should probably be used instead.

Yeah, I can send a picture of the hierachy if you want, as well as more info on the code. I tried both a local and server script but neither work :frowning:

Could it be because the viewport frame is being cloned in on the client?

That’s unlikely to matter, but yes, showing your code and hierarchy would help.

Okay, hope this helps :slight_smile:

Module Hierachy

Module Code;

-- Everything else is cut to save space
function emoteV.Get(emoteName)
	local oldNPC = template:WaitForChild("R6"):WaitForChild("NPC")
	local newTemp = template:Clone()
	local hum = oldNPC:FindFirstChild("Humanoid")
	local animator = hum:FindFirstChild("Animator")
	if emoteFolder:FindFirstChild(emoteName) then
		if newTemp and oldNPC and hum and animator then
			local emote = emoteFolder:FindFirstChild(emoteName)
			oldNPC.Parent = workspace
			local emoteTrack = animator:LoadAnimation(emote)
			oldNPC.Parent = newTemp
			emoteTrack.Looped = true
			return newTemp

Gui Hierachy;

Gui Local Code for getting viewport (everything else is irrelevant);

local function setupEmotes()
	for i, frame in emoteFolder:GetChildren() do
		if frame.EmoteName.Text then
			if not frame:FindFirstChild("tempViewport") then
				local viewport = viewportMod.Get(frame.EmoteName.Text)
				viewport.Size = goodSize
				viewport.Position = goodPos
				viewport.Parent = frame

Lmk if you need anything more

I’m a bit confused on what you’re doing here with the oldNPC and newTemp thing. It looks like you’re cloning the old template, then moving the old NPC to the the cloned temp, which already has an NPC as well? I’m also just confused on the purpose of doing all of this in the first place.

Sorry, the code is a bit messy due to constantly trying new solutions.

I am trying to make an emote wheel where the player can see the animations / emotes they have selected before actually playing them.

I also just realized this line was wrong

local oldNPC = template:WaitForChild("R6"):WaitForChild("NPC")

So I fixed it to get the var from the cloned template but no luck.

Here is what the wheel looks like when opened in game;

So why not just clone the template from each one, and then animate the NPC inside of each template for each one?

That’s what I’m trying to do, but it’s not working. Do you mean cloning the template inside of each button?

Also, one of the main issues was that Animation.IsPlaying was still printing true