Struggling with a particular Animation problem

Still the same effect, and no error for some reason.

Good morning!

Move AnimationTrack:Play() to the very end, should work! :slight_smile:

1 Like

Good morning. I moved it to the end and there is still the same effect, and no error sadly.

1 Like

The method I tried in the reply was wrong. I attempted to retrieve the Keyframes from an Animation instance, but you can only do so from a KeyframeSequence!

edit: Accidentally deleted message with a reply

1 Like

Put a ServerScript inside the NPC. Define the Humanoid (script.Parent.Humanoid). Put the animation inside the script.

local Animation = Humanoid:LoadAnimation(script.Animation)
Animation:Play()

It automatically plays the animation on the NPC, replicating to ALL clients at the same time, because the NPC is animated on the server – therefor automatically replicating for everybody.
I have no clue what RemoteEvents here would be useful for, especially “onClicked()”. This is literally a few lines of code! If your animation plays and resets back to the start when it’s finished, you simply need to make the animation visually looping - if it starts on the NPC crossing arms, make it end on the NPC crossing arms again.

edit: formatting

1 Like

I remember us trying this before. I got this same error.

09:33:27.741 - GetKeyframes is not a valid member of Animation

Sorry, this GetMarkerReachedSignal() method is very new to me, so I’m trying to understand it right now just as you are. I’m quite sure this is what you need to do. Before you load the animation into the humanoid, you need to add the Marker.

local NPCevent = game:GetService("ReplicatedStorage"):WaitForChild("NPCevent")

local Humanoid = game.Workspace.RobertJr_YT:FindFirstChild("Humanoid")



local function onRemoteFiredFromServer() -- Function for when remote is fired at client
    local Animation = Instance.new("Animation")
    Animation.AnimationId = "http://www.roblox.com/asset/?id=4820283660"

     local success = pcall(function()
         keyframes = KeyframeSequence:GetKeyframeSequenceAsync(Animation) -- proper method to retrieve the KeyframeSequence
     end)

    if success then
        keyframeTable = keyframes:GetKeyframes() -- creates a table containing the keyframes
    
        local lastframe = keyframeTable[#keyframes] -- identifies the last frame

        local marker = Instance.new("KeyframeMarker") -- creates the marker
        marker.Name = "ReachedLastFrame"
        lastframe:AddMarker(marker) -- parents the marker to the last keyframe
    

        local AnimationTrack = Humanoid:LoadAnimation(Animation) -- Now we load the AnimationTrack after the Marker has been added


        local function reachedLastFrame()
            AnimationTrack:AdjustSpeed(0)
        end


        local onLastFrame = AnimationTrack:GetMarkerReachedSignal("ReachedLastFrame")
        onLastFrame:Connect(reachedLastFrame)
    end
end


NPCevent.OnClientEvent:Connect(onRemoteFiredFromServer) -- Will call onRemoteFired() when the remote is fired from the server

Phew. There was a lot of learning for me through the process of writing this. Really hope this works!

1 Like

No it’s completely fine, I’m just shocked your willing to help me this far. Your the best.

I tried it and got an error, but maybe because these two words are underlined?

1 Like

I’m more than happy to help you out. Once we have this all figured out, I’ll create a community tutorial to make sure there’s some better documentation out there haha.
Alright, here’s what we need to do:

Add the single line

local keyframeTable

Before the pcall function.

Then add

local KeyframeSequence = game:GetService("KeyframeSequenceProvider")

to the top of the script.

I’ve said it a thousand times, but that should be all fixed!

1 Like

Agh, yet again another error. This one I haven’t seen before yet.

10:01:52.359 - Players.RobertJr_YT.PlayerGui.Visuals:18: attempt to get length of global 'keyframes' (a nil value)

EDIT: The error happened on this line.

local lastframe = keyframeTable[#keyframes] -- identifies the last frame

I forgot to change #keyframes to #keyframeTable. That’s all it is

edit: a letter

1 Like

Gargh! This is very frustrating. I changed it and I still get another error.

10:05:19.034 - Players.RobertJr_YT.PlayerGui.Visuals:18: attempt to get length of upvalue 'keyframeTable' (a nil value)

Guess what buster, we’re gonna count the items in the table ourselves!

local NPCevent = game:GetService("ReplicatedStorage"):WaitForChild("NPCevent")

local Humanoid = game.Workspace.RobertJr_YT:FindFirstChild("Humanoid")



local function onRemoteFiredFromServer() -- Function for when remote is fired at client
    local Animation = Instance.new("Animation")
    Animation.AnimationId = "http://www.roblox.com/asset/?id=4820283660"

     local success = pcall(function()
         keyframes = KeyframeSequence:GetKeyframeSequenceAsync(Animation) -- proper method to retrieve the KeyframeSequence
     end)

    if success then
        keyframeTable = keyframes:GetKeyframes() -- creates a table containing the keyframes

        local count = 0
        for _ in pairs(keyframeTable) do count = count + 1 end -- Iterates through every item and adds 1 to the counter.

    
        local lastframe = keyframeTable[count] -- identifies the last frame

        local marker = Instance.new("KeyframeMarker") -- creates the marker
        marker.Name = "ReachedLastFrame"
        lastframe:AddMarker(marker) -- parents the marker to the last keyframe
    

        local AnimationTrack = Humanoid:LoadAnimation(Animation) -- Now we load the AnimationTrack after the Marker has been added


        local function reachedLastFrame()
            AnimationTrack:AdjustSpeed(0)
        end


        local onLastFrame = AnimationTrack:GetMarkerReachedSignal("ReachedLastFrame")
        onLastFrame:Connect(reachedLastFrame)
    end
end


NPCevent.OnClientEvent:Connect(onRemoteFiredFromServer) -- Will call onRemoteFired() when the remote is fired from the server
1 Like

Yet again, there is no effect and no error. I wish I’m able to script to this level so I can at least help a bit. :stuck_out_tongue:

The current script in its form:

local NPCevent = game:GetService("ReplicatedStorage"):WaitForChild("NPCevent")
local Humanoid = game.Workspace.RobertJr_YT:FindFirstChild("Humanoid")
local keyframeTable
local KeyframeSequence = game:GetService("KeyframeSequenceProvider")

local function onRemoteFiredFromServer() -- Function for when remote is fired at client
    local Animation = Instance.new("Animation")
    Animation.AnimationId = "http://www.roblox.com/asset/?id=4820283660"

     local success = pcall(function()
         keyframes = KeyframeSequence:GetKeyframeSequenceAsync(Animation) -- proper method to retrieve the KeyframeSequence
     end)

    if success then
        keyframeTable = keyframes:GetKeyframes() -- creates a table containing the keyframes

        local count = 0
        for _ in pairs(keyframeTable) do count = count + 1 end -- Iterates through every item and adds 1 to the counter.

    
        local lastframe = keyframeTable[count] -- identifies the last frame

        local marker = Instance.new("KeyframeMarker") -- creates the marker
        marker.Name = "ReachedLastFrame"
        lastframe:AddMarker(marker) -- parents the marker to the last keyframe
    

        local AnimationTrack = Humanoid:LoadAnimation(Animation) -- Now we load the AnimationTrack after the Marker has been added


        local function reachedLastFrame()
            AnimationTrack:AdjustSpeed(0)
        end


        local onLastFrame = AnimationTrack:GetMarkerReachedSignal("ReachedLastFrame")
        onLastFrame:Connect(reachedLastFrame)
    end
end


NPCevent.OnClientEvent:Connect(onRemoteFiredFromServer) -- Will call onRemoteFired() when the remote is fired from the server

Why don’t you just play the animation on the server? Like @xLawOut suggested?

We’re trying to get the animation to freeze/stop on the final frame so the NPC doesn’t teleport back to the start of the animation.

EDIT: I was already working with @Spraden on this we are basically almost through with a solution. I didn’t much take into account on what he said since there would be no point redoing the script.

That can still be done on the server.

Edit: Actually, this can be done on the client. When you play an animation on the client, it automatically replicates to all other clients.

Something that just occurred to me:

Detect when it stops, Play() it again, but as you play it, then set AnimationTrack.TimePosition and do AnimationTrack:AdjustSpeed(0).

I believe our problem earlier may have been we didn’t play it again. Unfortunately it’s kind of hacky, and the one we’re trying now is much less so.

Try out what I typed above while I research more and try to figure out what’s messing us up!

1 Like

Animation’s should be done on the client because it makes the work flow easier, and it makes more sense to do the client’s visuals on the client.

They (Animations) replicate to the server which replicates to all other peers. Why would harder when you can work smarter.

2 Likes

Yep, I just made that edit. :joy: