Struggling with a particular Animation problem

  1. Change keyframes[#keyframes - 1] to keyframes[#keyframes]
  2. You don’t need the remote event. You should run this code on the server and every client will see it!

I think it’s because you were using this: "http://www.roblox.com/asset/?id=4820283660". I used this: "rbxassetid://4820283660".

2 Likes

I changed that and it still only prints 1 and 2 to the Console.

The code:

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"
		print("1")
		local success = pcall(function()
		print("2")
		keyframes = KeyframeSequence:GetKeyframeSequenceAsync(4820283660) -- proper method to retrieve the KeyframeSequence
		end)
	
		if success then
		keyframeTable = keyframes:GetKeyframes() -- creates a table containing the keyframes
		print("3")
		local count = 0
		for _ in pairs(keyframeTable) do count = count + 1 end -- Iterates through every item and adds 1 to the counter.
		
		print("4")
		local lastFrame = keyframes[#keyframes] -- identifies the last frame
		print("5")
		local marker = Instance.new("KeyframeMarker") -- creates the marker
		marker.Name = "ReachedLastFrame"
		lastFrame:AddMarker(marker) -- parents the marker to the last keyframe
		print("6")
			
		local AnimationTrack = Humanoid:LoadAnimation(Animation) -- Now we load the AnimationTrack after the Marker has been added
		
		print("7")
		local function reachedLastFrame()
		print("8")
		AnimationTrack:AdjustSpeed(0)
		print("9")
		end
		
		print("10")
		local onLastFrame = AnimationTrack:GetMarkerReachedSignal("ReachedLastFrame")
		onLastFrame:Connect(reachedLastFrame)
		Animation:Play()
	end
end


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

You should try running my code on the server!

1 Like

Sorry I’m working with two codes here. It gets very confusing working back and fourth between two people.

Currently this is the main code I’ve been using:

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 = "rbxassetid://4820283660"
		print("1")
		local success = pcall(function()
		print("2")
		keyframes = KeyframeSequence:GetKeyframeSequenceAsync(4820283660) -- proper method to retrieve the KeyframeSequence
		end)
	
		if success then
		keyframeTable = keyframes:GetKeyframes() -- creates a table containing the keyframes
		print("3")
		local count = 0
		for _ in pairs(keyframeTable) do count = count + 1 end -- Iterates through every item and adds 1 to the counter.
		
		print("4")
		local lastFrame = keyframes[#keyframes] -- identifies the last frame
		print("5")
		local marker = Instance.new("KeyframeMarker") -- creates the marker
		marker.Name = "ReachedLastFrame"
		lastFrame:AddMarker(marker) -- parents the marker to the last keyframe
		print("6")
			
		local AnimationTrack = Humanoid:LoadAnimation(Animation) -- Now we load the AnimationTrack after the Marker has been added
		
		print("7")
		local function reachedLastFrame()
		print("8")
		AnimationTrack:AdjustSpeed(0)
		print("9")
		end
		
		print("10")
		local onLastFrame = AnimationTrack:GetMarkerReachedSignal("ReachedLastFrame")
		onLastFrame:Connect(reachedLastFrame)
		
		Animation:Play()
	end
end


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

EDIT: I did multiple changes with statements you guys made above with the code. Still only prints in the Console 1 and 2.

Did my code work?

[30 characters]

1 Like

I’ll give it a shot again after @Spraden replies.

I suggest you try my code while waiting for @Spraden

So, how’s it going?

[30 characters]

1 Like

Haven’t tried it yet, but I guess I’ll do it now. I gotta save @Spraden’s code for the time being to test yours.

1 Like

Doesn’t work. The animation runs, but doesn’t stop on the final frame like it’s supposed to.

Your updated code:

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

local function onRemoteFiredFromServer() -- Call this function when you want to play the animation
    local Animation = Instance.new("Animation")
    Animation.AnimationId = "rbxassetid://4820283660"

    local success, err = pcall(function()
        keyframeSequence = KeyframeSequence:GetKeyframeSequenceAsync(Animation.AnimationId) 
    end)

    if success then
        local keyframes = keyframeSequence:GetKeyframes()
        local lastFrame = keyframes[#keyframes]

        local marker = Instance.new("KeyframeMarker"); marker.Name = "ReachedLastFrame"
        lastFrame:AddMarker(marker)

        local animTrack = Humanoid:LoadAnimation(Animation)

        animTrack:GetMarkerReachedSignal("ReachedLastFrame"):Connect(function()
            animTrack:AdjustSpeed(0)
        end)

        animTrack:Play()
    end
end

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

I found some weird documentation… this got a hell of a lot more complicated! :smiley:

local NPCevent = game:GetService("ReplicatedStorage"):WaitForChild("NPCevent")
local Character = workspace:WaitForChild("RobertJr_YT")
local Humanoid = Character.Humanoid or Character:WaitForChild("Humanoid")
local KeyframeSequence = game:GetService("KeyframeSequenceProvider")

local function onRemoteFiredFromServer()
    local Animation = Instance.new("Animation")
    Animation.AnimationId = "rbxassetid://4820283660"

    keyframeSequence = KeyframeSequence:GetKeyframeSequenceAsync(Animation.AnimationId) 

    local newKeyframeSequence = Instance.new("KeyframeSequence"); keyframeSequence.Loop = false; keyframeSequence.Priority = Enum.AnimationPriority.Action

    local keyframes = {}

    for _, keyframe in pairs(keyframeSequence:GetKeyframes()) do
        table.insert(keyframes, #keyframes + 1, keyframe)
        newKeyframeSequence:AddKeyframe(keyframe)
    end

    lastframe = keyframes[#keyframes]
    
   
    local marker = Instance.new("KeyframeMarker"); marker.Name = "ReachedLastFrame"
    lastframe:AddMarker(marker)

  
    
    local hashId = KeyframeSequenceProvider:RegisterKeyframeSequence(newKeyframeSequence) 

    if hashId then 
        local newAnimation = Instance.new("Animation")
    	newAnimation.AnimationId = hashId
    	local newAnimationTrack = Humanoid:LoadAnimation(newAnimation)
           
         newAnimationTrack:GetMarkerReachedSignal("ReachedLastFrame"):Connect(function()
             newAnimationTrack:AdjustSpeed(0)
        end)

        newAnimationTrack:Play()
    end
end

NPCevent.OnClientEvent:Connect(onRemoteFiredFromServer)

Jeez. So in the Keyframe documentation I found you can create a temporary animation. Using this we are able to edit the keyframes then place them inside a new KeyframeSequence which can generate a HashId for an animation that is only locally accessible and not published to Roblox. We can then use that new animation to load onto the NPC.

1 Like
local Character = game.Workspace.RobertJr_YT
local Humanoid = Character.Humanoid or Character:WaitForChild("Humanoid")
local stopTime = 0.1 -- The amount of time to be subtracted from the animation before freezing

local function playAnimation() -- Call this function when you want to play the animation
    local Animation = Instance.new("Animation")
    Animation.AnimationId = "rbxassetid://4820283660"

    local animTrack = Humanoid:LoadAnimation(Animation)
    local animLength = animTrack.Length

    animTrack:Play()

    wait(animLength - stopTime)

    animTrack:AdjustSpeed(0)
end

playAnimation()

Yet again with this solution, it does run the animation, but still teleports back to the start. I had to edit some things in the script though to make some underlined words go away.

Code:

local NPCevent = game:GetService("ReplicatedStorage"):WaitForChild("NPCevent")
local Character = workspace:WaitForChild("RobertJr_YT")
local Humanoid = Character.Humanoid or Character:WaitForChild("Humanoid")
local KeyframeSequenceProvider = game:GetService("KeyframeSequenceProvider")

local function onRemoteFiredFromServer()
    local Animation = Instance.new("Animation")
    Animation.AnimationId = "rbxassetid://4820283660"

    local KeyframeSequence = KeyframeSequenceProvider:GetKeyframeSequenceAsync(Animation.AnimationId) 

    local newKeyframeSequence = Instance.new("KeyframeSequence"); KeyframeSequence.Loop = false; KeyframeSequence.Priority = Enum.AnimationPriority.Action

    local keyframes = {}

    for _, keyframe in pairs(KeyframeSequence:GetKeyframes()) do
        table.insert(keyframes, #keyframes + 1, keyframe)
        newKeyframeSequence:AddKeyframe(keyframe)
    end

    local lastframe = keyframes[#keyframes]
    
   
    local marker = Instance.new("KeyframeMarker"); marker.Name = "ReachedLastFrame"
    lastframe:AddMarker(marker)

  
    
    local hashId = KeyframeSequenceProvider:RegisterKeyframeSequence(newKeyframeSequence) 

    if hashId then 
        local newAnimation = Instance.new("Animation")
    	newAnimation.AnimationId = hashId
    	local newAnimationTrack = Humanoid:LoadAnimation(newAnimation)
           
         newAnimationTrack:GetMarkerReachedSignal("ReachedLastFrame"):Connect(function()
             newAnimationTrack:AdjustSpeed(0)
        end)

        newAnimationTrack:Play()
    end
end

NPCevent.OnClientEvent:Connect(onRemoteFiredFromServer)

I still don’t understand why a remote event is necessary. Can you explain?

Now especially it is a must. You can’t create or use a HashId for an animation on the server.

Honestly, I’m really happy that it played the animation first go. Add a print() to the function connected to GetMarkerReachedSignal() so we can see if the function is ran.

It works, however like I said again it stops too soon.

Then change the stopTime variable to a lower value.

Did it work for you?

[30 characters]