Ordinarily I can get animations to work in viewports via WorldModels, however I am having trouble getting Mood / Face animations specifically to work. Below I’ve attached two images and some code — the first image is what the rig looks like in a viewport (it is animated with an idle animation, just to confirm that animations are showing), and the second image is what the code looks like if I run it specifically on the player’s character.
As you’ll see, mood animations work on the player, but not on the rig inside of the viewport.
The viewport rig is just a Player.Character:Clone() situation, so I can confirm that the animation IDs and humanoid descriptions are equal. I’ve checked that thoroughly. The mood animation is from the Moods tutorial on the documentation.
local faceRig = faceButton.ViewportFrame.WorldModel.TemplateRig
local rigDescription = Instance.new("HumanoidDescription")
rigDescription.Head = 13692956122
rigDescription.IdleAnimation = 10725833199
-- some stuff about setting up the camera for the viewport... not important
faceRig.Humanoid:ApplyDescriptionReset(rigDescription)
I’ll again emphasize that the exact same code is being run on both the player and the viewport rig. I have even tried waiting 5 or so seconds to visibly watch the mood animation on the player model, then clone it and put it into the viewport, and while every other animation runs, the mood animation does not.
I believe the only fundamental difference is that one runs from a modulescript tied to a server script, while the other runs on a local script connected to the UI. But I don’t think that should matter.
But I needed a local script to do it. So I decided to manually set the characters idle animation and mood animation.
local c = player.Character or player.CharacterAdded:Wait()
print("character loaded locally")
c.Archivable = true
local result = c:Clone()
result.Name = "ViewportClone"
result.Parent = viewportWorldModel
local animateScript = result:FindFirstChild("Animate")
if animateScript then
-- Disable the animate script to prevent default animations
animateScript.Enabled = false
end
-- Play animations directly
local humanoid = result:FindFirstChildOfClass("Humanoid")
if humanoid then
local animator = humanoid:FindFirstChildOfClass("Animator")
if not animator then
animator = Instance.new("Animator")
animator.Parent = humanoid
end
-- Create and play the idle animation
local idleAnimation = Instance.new("Animation")
idleAnimation.AnimationId = "http://www.roblox.com/asset/?id=17172918855"
local idleAnimationTrack = animator:LoadAnimation(idleAnimation)
idleAnimationTrack:Play()
idleAnimationTrack.Looped = true
idleAnimationTrack.Priority = Enum.AnimationPriority.Idle
print("Playing idle animation on viewport character")
-- Create and play the mood animation
local moodAnimation = Instance.new("Animation")
moodAnimation.AnimationId = "http://www.roblox.com/asset/?id=7715145252"
local moodAnimationTrack = animator:LoadAnimation(moodAnimation)
moodAnimationTrack:Play()
moodAnimationTrack.Looped = true
moodAnimationTrack.Priority = Enum.AnimationPriority.Action
print("Playing mood animation on viewport character")
else
warn("No Humanoid found in character clone")
end
This limitation is similar to the problem you had in that my local script is failing to apply an animationId to a character’s mood value in their animate script. I believe this is because local scripts can’t actually play mood animations the same way a server script can.
My only other proof for this is this disclaimer in the moods documentation. It suggests that moods are controlled by an “internal script”.
I assume this internal script can only be changed with a server script. Regardless, moods are simply animations and can be played as an animation instance so long as the animate script isn’t interfering.