I am developing a camera system in Roblox using viewport frames. My goal is to replicate the original player’s facial animations onto a cloned player within the viewport frame. However, I am encountering difficulties in accurately transferring the facial expressions from the original player model to the cloned model displayed in the viewport frame.
This is what my modulescript looks like currently:
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local ViewportModule = {}
local function cloneObject(object)
object.Archivable = true
local clone = object:Clone()
object.Archivable = false
return clone
end
function ViewportModule.setupWorld(worldFolder, viewportFrame)
local worldModel = viewportFrame:FindFirstChild("WorldModel") or Instance.new("WorldModel")
worldModel.Name = "WorldModel"
worldModel.Parent = viewportFrame
for _, obj in ipairs(worldFolder:GetChildren()) do
local clone = cloneObject(obj)
clone.Parent = worldModel
end
end
function ViewportModule.setupCharacter(player, viewportFrame)
local worldModel = viewportFrame:WaitForChild("WorldModel")
local character = player.Character or player.CharacterAdded:Wait()
local characterClone = cloneObject(character)
characterClone.Parent = worldModel
local originalHumanoid = character:WaitForChild("Humanoid")
local cloneHumanoid = characterClone:WaitForChild("Humanoid")
local originalAnimator = originalHumanoid:WaitForChild("Animator")
local cloneAnimator = cloneHumanoid:WaitForChild("Animator")
local animationTracks = {}
local function getOrCreateAnimationTrack(animation)
if not animationTracks[animation.AnimationId] then
animationTracks[animation.AnimationId] = cloneAnimator:LoadAnimation(animation)
end
return animationTracks[animation.AnimationId]
end
local function replicateAnimations()
for _, track in ipairs(originalAnimator:GetPlayingAnimationTracks()) do
local cloneTrack = getOrCreateAnimationTrack(track.Animation)
if not cloneTrack.IsPlaying then
cloneTrack:Play(track.TimePosition)
end
cloneTrack:AdjustSpeed(track.Speed)
cloneTrack:AdjustWeight(track.WeightCurrent)
cloneTrack.TimePosition = track.TimePosition
end
for _, cloneTrack in pairs(animationTracks) do
if cloneTrack.IsPlaying then
local isPlayingOnOriginal = false
for _, originalTrack in ipairs(originalAnimator:GetPlayingAnimationTracks()) do
if originalTrack.Animation.AnimationId == cloneTrack.Animation.AnimationId then
isPlayingOnOriginal = true
break
end
end
if not isPlayingOnOriginal then
cloneTrack:Stop()
end
end
end
end
RunService.RenderStepped:Connect(function()
if character and character:FindFirstChild("HumanoidRootPart") and characterClone and characterClone:FindFirstChild("HumanoidRootPart") then
characterClone:SetPrimaryPartCFrame(character.HumanoidRootPart.CFrame)
replicateAnimations()
end
end)
return characterClone
end
function ViewportModule.setupCamera(cameraPart, viewportFrame)
local viewportCamera = Instance.new("Camera")
viewportCamera.CFrame = cameraPart.CFrame
viewportFrame.CurrentCamera = viewportCamera
return viewportCamera
end
function ViewportModule.createViewportSetup(worldFolder, player, cameraPart)
return function(viewportFrame)
ViewportModule.setupWorld(worldFolder, viewportFrame)
ViewportModule.setupCharacter(player, viewportFrame)
ViewportModule.setupCamera(cameraPart, viewportFrame)
end
end
return ViewportModule