How to put player character in animation end position?

Hi, how do I put the player character’s position in the place my animation ended?

Script:

local isPlay = false

game.Players.PlayerAdded:Connect(function(player)
	player.CharacterAdded:Connect(function()
		wait(3)
		local siu = Instance.new("Animation", player.Character)
		local cheer = Instance.new("Animation", player.Character)
		local slide = Instance.new("Animation", player.Character)

		siu.AnimationId = "rbxassetid://12228840392"
		cheer.AnimationId = "rbxassetid://507770677"
		slide.AnimationId = "rbxassetid://12275929514"
		
		local siuanim = player.Character:FindFirstChild("Humanoid"):WaitForChild("Animator"):LoadAnimation(siu)
		local cheeranim = player.Character:FindFirstChild("Humanoid"):WaitForChild("Animator"):LoadAnimation(cheer)
		local slideanim = player.Character:FindFirstChild("Humanoid"):WaitForChild("Animator"):LoadAnimation(slide)


		game.ReplicatedStorage.Events.SiuFired.OnServerEvent:Connect(function(player)
			if isPlay then return end
			isPlay = true
			siuanim.Priority = Enum.AnimationPriority.Action4
			siuanim:Play()
			siuanim.Ended:Wait()
			
			isPlay = false
		end)

		game.ReplicatedStorage.Events.CheerFired.OnServerEvent:Connect(function(player)
			if isPlay then return end
			isPlay = true
			cheeranim.Priority = Enum.AnimationPriority.Action4
			cheeranim:Play()
			cheeranim.Ended:Wait()
			
			isPlay = false
		end)
		game.ReplicatedStorage.Slide.OnServerEvent:Connect(function(player)
			if isPlay then return end
			isPlay = true
			slideanim.Priority = Enum.AnimationPriority.Action4
			slideanim:Play()
			wait(slideanim.Length - 0.01)
			
			slideanim.Ended:Wait()
			
			isPlay = false
		end)
	end)
end)

You mean, in the Pose that the character has at the end of your animation? (Like “with arms wide open”) ?

Or you mean, your animation is moving the LowerTorso part to a different position (like walking away from the center point of the animation) ?

I guess its the second one.
I would try to do it by using a KeyframeMarker inside your animation. That event can be readed while the animation is running.

The idea would be, fire the KeyframeMarker when the animation is about to finish, one keyframe before it ends maybe or at the very end, and you listen that event in the script, changing the HRP position of the player to the LowerTorso position readed when the KeyframeMarker was fired (using a slight offset of HRP vs LowerTorso positions)

You would use the Animation:GetMarkerReachedSignal("KeyframeMarkerName) to listen the KeyEvent in your script
GetMarkerReachedSignal()

2 Likes

Good idea, but how do I add one to a certain keyframe?

Open your animation in the Studio avatar animator, select the keyframe, right click, then click the “add animation event here”

It will ask you for the name of the mark event, and a secondary parameter to send if you wish, its not mandatory

1 Like

A slight problem you might encounter with the method above is the relativity animations have to the HumanoidRootPart. This is dependent on your animations, both ways can be used

Let’s say you have a walking animation, when the animation is finished you position the HumanoidRootPart to the LowerTorso’s position. You will see that the character gets pushed forward because it’s returning to the original position (Humanoid Root Part), since it’s not automatically snapped.

Image from Gyazo


A solution I found was to, instead use the actual Keyframes in the animation to determine when to teleport the HumanoidRootPart. As you can see below, the last Keyframe that does anything is named EndKeyFrame which indicated when to start teleporting.

The Keyframe after is the additional Keyframe, which is set to the original position of the LowerTorso which will help us snap in place.

How to rename a Keyframe:

Image from Gyazo

My Animation:

Image from Gyazo


Once added, you need to connect a function to read when a Keyframe is reached. After that you just need to position the Character or HumanoidRootPart.

local LoadedTrack = -- Loaded animation track
	local connection = LoadedTrack.KeyframeReached:Connect(function(keyName)
		if keyName == "EndKeyFrame" then
			Character:MoveTo(Character.LowerTorso.Position + Vector3.new(0, Character.LowerTorso.Size.Y * 2, 0))
            -- Adjust position based on LowerTorso size, smooths out snap
		end
	end)

LoadedTrack.Ended:Connect(function()
     connection:Disconnect() -- Cleanup connection
end)

Result (Not noticeable in-game) :

Image from Gyazo

1 Like

Where should I put this?

I’m guessing where I originally activate the animation from? can be a button

It has to be attached to the loaded AnimationTrack, what you would call :Play() on.

AnimationTrack:Play()

-- Add it here
1 Like

Everything seems to be working, but one thing: When it ends, it slides my avatar back, and then it teleports it, is there a way to not make it slide back and then teleport, but make it teleport earlier, so that doesnt happen?

The best possible result requires that your EndKeyFrame be as close as possible to the last Keyframe in your animation. If it’s still sliding in that case, you may need to play around with the other method using AnimationTrack.TimePosition and AnimationTrack.Length.

image

1 Like

Its as close as possible, what do you mean with the other options?

This is what it’s doing right now:

The harsh reality is that animations simply aren’t meant to be used this way. You can try and find some sort of bandaid fix, such as teleporting the player a frame before the animation ends, but you should just use physics to move the HumanoidRootPart.

Using some sort of physic constraint, and not the animation, to apply velocity to the HumanoidRootPart would be the most ideal and proper solution here.

I see your connecting remote events inside of CharacterAdded. This is a terrible idea, as everytime the player respawns, it will be connected again. It also doesn’t check if the player calling the remote. You need to either move it out of PlayerAdded, or check if the caller is the player you want, and you’ll have to disconnect old connections when unused.

I think a good approach would be, not changing the position of the character during the animation, the animation should keep the player in the origin position, and perform the movement of the character using a MoverConstraint or BodyMover, as you stated.

The animation of @DanielosthebestYTAlt , seems like a dash, then the dash should be done by scripts, and the animation should not change the LowerTorso position

Yes, It’s meant to be a sliding tackle.

You do the sliding animation, tackle the player and continue walking right after

Yup, I think you should edit the animation, and do not change the position of the player, just the sliding tackle animation at the origin point of the character. Then by scripts you should apply the “dash”, in that way the animation plays, the character actually does the dash in server.

Its a soccer game, would be better to handle that sliding tackle without depending on where is the character during the animation, otherwise, it will complicate other systems (like stealing the ball when theres is contact with it during the sliding)

I apologise if I’m asking for too much, but could you maybe provide me with a script for the moving?

I’m relatively new to scripting, that’s why.

1 Like

I would love to, but I never made a dash system before, I can think on a couple of approaches on how to achieve it, but I dont have that experience, so any of those ideas would be the best one and I dont know which one is.

As @NodeSupport and me think, applying the “dash” to the player probably should be done using MoverConstrains, BodyMovers (a little depracated) or another way like just CFraming

Here’s some topics on how to use them:

this question has already been answered

1 Like

No, I’ve already tried that. Just froze my character, did exactly what the person did.