Player Character Animations in ViewportFrame WorldModel

Perfect day, developers.

I am trying to play a player’s character’s live animations in a WorldModel parented to a ViewportFrame, meaning that, for example, when a player emotes, that emote can be seen in the ViewportFrame.

However, I am relying on Roblox’s default animation system. And, because of this, the animations overlap, rather than an animation stopping so that another can play. This looks fine in Workspace, but it looks like the animations are competing with each other in the WorldModel.

I figured out that the problem was because of animations overlapping by outputting the current animations playing when a player emotes, and stopping the idle animation. When I did this, the emote played perfectly. But, if I stop the idle animation and the emote stops, then the idle animation will no longer play.

I am probably going to use a clone of the character and not the actual character itself, then copy the animations that are playing from the original character to the duplicate. But, alone, that still wouldn’t fix the problem of the animations overlapping. Will someone please give me some ideas?

P.S. Parenting the Players.LocalPlayer’s character to the WorldModel works fine. Using another player’s character is when the animations mess up.

3 Likes

I would probably just make a clone of the character and copy and run the player’s active animation with the same speed. And rather actually running I would just set it’s animation position to whatever the localplayer character one.

I’m not sure if that would be a solution for you however I am just thinking it on the go. Theoretically it should work XD

1 Like

I understand you, and thank you. However, even if I did play the active animation(s) on the dummy and adjust the position and all of that, there would be more than one animation playing: possibly the emote and the idle animation. Which means that the animations would still be competing in the ViewportFrame.

And I don’t think it would be possible for me to stop the idle animation and play it after the emote finishes, because what happens if the player decides to play another emote before that one finishes? I say this because here is the code I envisioned:

animator.AnimationPlayed:Connect(function(animationTrack)
    local animationsOnHold = {}
    for _, playingTrack in animator:GetPlayingAnimationTracks() do
        if playingTrack ~= animationTrack then
            playingTrack:Stop()
            table.insert(animationsOnHold, playingTrack)
        end
    end

    animationTrack.Stopped:Wait()
    for _, trackOnHold in animationsOnHold do
        trackOnHold:Play()
    end
end)

or

    local animationOnHold = nil
    for _, playingTrack in animator:GetPlayingAnimationTracks() do
        if playingTrack ~= animationTrack then
            playingTrack:Stop()
            animationOnHold  = playingTrack
            break -- May or may not be necessary.
        end
    end

    animationTrack.Stopped:Wait()
    animationOnHold:Play()

This code would may not work as entended.
(It didn’t work. :frowning:)

I meant like you would run the Animation and the AnimationSpeed would be set to 0. You would just change the Animation’s TimeLine and that’s all.

I’ve tried replicating that system of yours since there was a game called Entry Point from a long time ago. It had such small avatar that was satisfying to watch at the bottom left corner to watch.

1 Like

OK. This is a snippet of the code I used, trying to follow what you said:

local function replicateTrackToDummy(track: AnimationTrack)
    local duplicateTrack = dummyAnimator:LoadAnimation(track.Animation)
    duplicateTrack:AdjustSpeed(0)
    duplicateTrack:Play()

    track:GetPropertyChangedSignal("TimePosition"):Connect(function()
        duplicateTrack.TimePosition = track.TimePosition
    end)

    track.Ended:Connect(function()
        duplicateTrack:Stop()
    end)
end

for _, track: AnimationTrack in originalAnimator:GetPlayingAnimationTracks() do
    replicateTrackToDummy(track)
end

originalAnimator.AnimationPlayed:Connect(replicatedTrackToDummy)

GetPropertyChangedSignal("TimePosition") doesn’t seem to work for AnimationTracks, though. So, I tried just adjusting the position and letting the animation play normally. But, some of the emotes still don’t play correctly, the movement animations don’t play correctly, and the idle animations are fine:

local function replicateTrackToDummy(track: AnimationTrack)
	local duplicateTrack = dummyAnimator:LoadAnimation(track.Animation)
	duplicateTrack.TimePosition = animationTrack.TimePosition
	duplicateTrack:Play()

	track.Stopped:Connect(function()
	    duplicateTrack:Stop()
	end)
end

Any ideas?

And, again, for some reason this problem only occurs when trying to view someone else’s character or a dummy, not your own.

I came up with a solution. I created a duplicate of the player’s character, copied the current-playing animations and the animations played afterward over to the character duplicate, and set the AnimationTracks’ Priority properties to Enum.AnimationPriority.Action:

duplicateTrack.Priority = Enum.AnimationPriority.Action

Not quite sure about the logic, and I don’t know if this is the most efficient way to solve the problem, but the issue was related to more than one animation playing at once. I’m assuming that this is a WorldModel bug that needs to be fixed, since the animations weren’t acting weird in Workspace.

Thanks for the help, @HighFoxyplayz11!

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.