Running System depending on tool

I know there are already other posts about shift to run. But hear me out, I want to set a custom running animation and a custom walking animation. The running/walking animation will depend on the user’s weapon. Right now I only scripted a custom running script but it doesn’t change depending on the tool yet. I wanna know two things, is it fine my approach on a custom running animation and how should I set the different walking animations and running animations depending on the tool that is active. Keep in mind I wanna make the transition between animations very smooth. Thank you !

local UserInputService = game:GetService("UserInputService")
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local runSpeed = 30
local walkSpeed = 16

local runKey = Enum.KeyCode.LeftControl

local animationsFolder = ReplicatedStorage:WaitForChild("Animations"):WaitForChild("Fist")
local runAnimation = animationsFolder:WaitForChild("Run")
local Data = ReplicatedStorage:WaitForChild("Remotes"):WaitForChild("Data")

local player = Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character:FindFirstChildOfClass("Humanoid")

local runAnimationTrack = humanoid:LoadAnimation(runAnimation)
runAnimationTrack.Priority = Enum.AnimationPriority.Action4

local wantsToRun = false
local lockRunningState = false
local isMoving = false

local function toggleRunning()
	if character:GetAttribute("IsStunned") or character:GetAttribute("IsPunching") or character:GetAttribute("IsBlocking") then return end
	wantsToRun = not wantsToRun
	if isMoving then
		humanoid.WalkSpeed = wantsToRun and runSpeed or walkSpeed
		character:SetAttribute("IsRunning", wantsToRun)

		if not wantsToRun then
			runAnimationTrack:Stop()
		else
			runAnimationTrack:Play()
		end
	end
end

local function monitorMovementAndState()
	local function checkAndPlayRunAnimation()
		if character:GetAttribute("IsPunching") then
			if runAnimationTrack.IsPlaying then
				runAnimationTrack:Stop()
			end
			return
		end

		isMoving = humanoid.MoveDirection.Magnitude > 0

		if wantsToRun and isMoving and humanoid.FloorMaterial ~= Enum.Material.Air then
			if not runAnimationTrack.IsPlaying then
				runAnimationTrack:Play()
				character:SetAttribute("IsRunning", true)
			end
		elseif not isMoving or not wantsToRun then
			if runAnimationTrack.IsPlaying then
				runAnimationTrack:Stop()
				character:SetAttribute("IsRunning", false)
			end
		end

		if wantsToRun and isMoving then
			humanoid.WalkSpeed = runSpeed
		else
			humanoid.WalkSpeed = walkSpeed
		end
	end

	humanoid.Running:Connect(function(speed)
		checkAndPlayRunAnimation()
	end)

	humanoid.StateChanged:Connect(function(oldState, newState)
		if newState == Enum.HumanoidStateType.Landed then
			checkAndPlayRunAnimation()
		end
	end)
end


local function init()
	character = player.Character or player.CharacterAdded:Wait()
	humanoid = character:FindFirstChildOfClass("Humanoid")
	runAnimationTrack = humanoid:LoadAnimation(runAnimation)

	character:SetAttribute("IsRunning", false)
	character:SetAttribute("IsPunching", false)

	monitorMovementAndState()

	character:GetAttributeChangedSignal("IsPunching"):Connect(function()
		if character:GetAttribute("IsPunching") then
			runAnimationTrack:Stop()
			humanoid.WalkSpeed = walkSpeed
			character:SetAttribute("IsRunning", false)
		end
	end)

	UserInputService.InputBegan:Connect(function(input, gameProcessed)
		if gameProcessed then return end
		if input.KeyCode == runKey then
			toggleRunning()
		end
	end)
end

player.CharacterAdded:Connect(function(char)
	character = char
	init()
end)

init()

Data.OnClientEvent:Connect(function(data)
	if data.action == "updateRunningState" then
		character:SetAttribute("IsRunning", false)
		lockRunningState = false
	elseif data.action == "StopRunning" then
		wantsToRun = false
		humanoid.WalkSpeed = walkSpeed
		runAnimationTrack:Stop()
		character:SetAttribute("IsRunning", false)
	end
end)

character:GetAttributeChangedSignal("IsPunching"):Connect(function()
	if character:GetAttribute("IsPunching") then
		wantsToRun = false
		humanoid.WalkSpeed = walkSpeed
		runAnimationTrack:Stop()
		character:SetAttribute("IsRunning", false)
	end
end)```

As for “how to set the different walking animations and running animations depending on the tool that is active?”. This is probably the most straight forward way to detect when a player is holding the tool actively.

Context: This script is located as a child of the tool so script.Parent = tool

-- For detecting when the tool is equipped
script.Parent.Equipped:Connect(function()
	print("Player is holding the tool")
end)

-- For detecting when the tool has been unequipped
script.Parent.Unequipped:Connect(function()
	print("Player has unequipped the tool")
end)

Based on this, within each function, you can do whatever you’d like, like trigger an event that modify’s the walking/running animation, and such. You should be able to use this info to connect your custom script but let me know if you need further assistance.

1 Like

Alright, thanks but I was more wondering if my approach to create a running system is fine. It seems kinda weird to have to script 100 lines just to make a running system. Is it considered normal what I did with the code? Is there a more optimized way or doing it?

This needs to be moved to init(), because it won’t work after respawn.

Yes

Your code is clean, don’t look for microoptimisations unless there’s a huge problem with the performance of it (there isn’t)

You’d be surprised!