One way to change the walk/run animation is to constantly play an animation while the player is moving using the Humanoid.Running
event, this however does not always register while the character is moving. I also have to perform a lot of checks.
Humanoid.Running
humanoid.Running:Connect(function(speed)
if speed == 0 then return end
local state = humanoid:GetState()
if state == Enum.HumanoidStateType.FallingDown then return end
if state == Enum.HumanoidStateType.Dead then return end
if state == Enum.HumanoidStateType.Climbing then return end
if state == Enum.HumanoidStateType.Swimming then return end
if not equipped then return end
if moveAnim.IsPlaying then return end
moveAnim:Play()
end)
The other way is to use ContextActionService but it achieves the same thing as Humanoid.Running
ContextActionService PlayerActions binding
local CAS = game:GetService("ContextActionService")
local function moveAnimate()
local state = humanoid:GetState()
if state == Enum.HumanoidStateType.FallingDown then return end
if state == Enum.HumanoidStateType.Dead then return end
if state == Enum.HumanoidStateType.Climbing then return end
if state == Enum.HumanoidStateType.Swimming then return end
if not equipped then return end
if moveAnim.IsPlaying then return end
print("Playing movement")
moveAnim:Play()
end
local playerActions = Enum.PlayerActions:GetEnumItems()
table.remove(playerActions, table.find(playerActions, Enum.PlayerActions.CharacterJump))
CAS:BindAction("bindToMovements", moveAnimate, false, unpack(playerActions))
--[[CAS:BindAction("bindToJump", function()
if not moveAnim.IsPlaying then return end
moveAnim:Stop()
end, false, Enum.PlayerActions.CharacterJump)]]
So I’ve tried to make a loop that would check speed but the problem is that it will be buggy when other core animations should play like jumping & falling down:
Loop approach
-- equipped variable is toggled on/off using the Equipped/Unequipped events
local currentSpeed = 0
humanoid.Running:Connect(function(speed)
if not equipped then return end
local state = humanoid:GetState()
if state == Enum.HumanoidStateType.FallingDown then speed = 0 end
if state == Enum.HumanoidStateType.Dead then speed = 0 end
if state == Enum.HumanoidStateType.Climbing then speed = 0 end
if state == Enum.HumanoidStateType.Swimming then speed = 0 end
currentSpeed = speed
end)
while true do
if equipped and not moveAnim.IsPlaying then
if currentSpeed ~= 0 then
moveAnim:Play()
else
moveAnim:Stop()
end
elseif not equipped and moveAnim.IsPlaying then
moveAnim:Stop()
script.Parent.Equipped:Wait()
end
game:GetService("RunService").Heartbeat:Wait()
end
I am also aware of an approach to directly change the local animation script to new values and back but I don’t think every player will have the same default animation for movement so I tried this:
Animation Run Animation ID Change Approach
local currentWalkAnimation = char:WaitForChild("Animate"):WaitForChild("run"):FindFirstChildOfClass("Animation")
local defaultWalkId = currentWalkAnimation.AnimationId
local walking = false
humanoid.Running:Connect(function(speed)
if not equipped then return end
local state = humanoid:GetState()
if state == Enum.HumanoidStateType.FallingDown then speed = 0 end
if state == Enum.HumanoidStateType.Dead then speed = 0 end
if state == Enum.HumanoidStateType.Climbing then speed = 0 end
if state == Enum.HumanoidStateType.Swimming then speed = 0 end
if speed == 0 and walking == true then
walking = false
currentWalkAnimation.AnimationId = defaultWalkId
elseif speed ~= 0 and walking == false then
walking = true
currentWalkAnimation.AnimationId = "rbxassetid://5143593784"
end
end)
However, the legs became buggy even though every other problem was fixed, so I am not sure how to fix this. This is what it should look like.
Is there a reliable way to do custom walk/run animation through tool equip? Changing the default animation script won’t be reliable because I have to change back to default and tool walk animation on equip and unequip.
EDIT: Animation settings here below:
Animation settings
- Priority: Action
- Looped: False