How Can I Effectively and Accurately Handle WalkSpeed in My Game?

You can write your topic however you want, but you need to answer these questions:

  1. I’m currently working on an anime combat game

  2. What is the issue? Include screenshots / videos if possible!
    My issue is that there are multiple scripts, and sources affecting the humanoid WalkSpeed, which causes the restoration and or setting of the walkspeed overwrite each other. For example, I have two attacks, After being hit by attack #1 I’d be stunned for 4 seconds, after the 4 seconds I set my walkspeed to 16. After being hit by attack #2 I’d be stunned for 2 seconds and returned to the base speed after those 2 seconds. The problem arises when I’m hit by attack #1, and then hit by attack number #2. Instead of waiting 4 seconds, attack #2 will overwrite attack #1 and return to the base speed before the first attacks 4 seconds. There are also other things like sprinting, blocking, and crouching. I want to manage all this with a module but I don’t know how to go about it.

  3. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
    I’ve been searching through the forum for a few days now, I keep finding shortcut-like solutions that wouldn’t work long-term or just very specific solutions that don’t apply to me. I did find two modules but they weren’t explained well.

Example:

local duration1 = 4
local duration2 = 2
local BaseSpeed = 16

local function attack1()
humanoid.WalkSpeed = 4
wait(duration1)
humanoid.WalkSpeed = BaseSpeed
end

local function attack2()
humanoid.WalkSpeed = 4
wait(duration2)
humanoid.WalkSpeed = BaseSpeed
end

attack1()
wait(1)
attack2()


--Attack 2 will return the walkspeed to BaseSpeed before the 4 second duration from Attack 1

I’d like someone to explain how I can implement this into my game. I might have worded this weirdly so If you have any questions let me know.

Maybe you could make a Boolean variable for both attack1 and 2 etc…

Set them both to false and when the attack1 function runs set it to true then wait “duration” then set it to false

Then in attack2 function check if attack1used is true then return but if its not then run the attack2 code

But im not good at scripting at all just an idea

2 Likes

This could work but the thing is that there are other factors in the game that affect walkspeed like sprinting, blocking, etc. I forgot to mention that so I’ll edit the post, I think the ideal method of handling walkspeed would be to make a module script that I can use for all sources of walkspeed changes, I just need help figuring out how I’d go about doing that.

Ohh yea but I’m sure u can check if they are sprinting or blocking while ur doing the attack function but maybe use a module like i said im not very good at scriptinf

1 Like

What I usually do is connect a PreRender (aka RenderStepped) event from RunService and do every check on the client. I know it’s not the safest method, but things like walkspeed and character movement should be handled on the client because of responsiveness, especially for combat games that involve a lot of movement.

Bit outdated but could give you a general idea on how to make it work

1 Like

I think this will suffice for now, I know there is a more efficient way to do it but until I grow in terms of scripting knowledge this should be good. This is what I did.

This local script fires events to pass on True or False values depending on if the player is walking

uis.InputBegan:Connect(function(input,gpe)
	if input.KeyCode == Enum.KeyCode.LeftShift then
		mE:FireServer('Sprint', true)
		if not character:FindFirstChild('Stunned') and humanoid.MoveDirection.Magnitude > 0 and player.canRun.Value == true then
			runAnimTrack:Play()
		end
	end
	if input.KeyCode == Enum.KeyCode.LeftControl then
		mE:FireServer('Crouch', true)
	end
end)

uis.InputEnded:Connect(function(input,gpe)
	if input.KeyCode == Enum.KeyCode.LeftShift then
		mE:FireServer('Sprint', false)
		runAnimTrack:Stop()
	end
	if input.KeyCode == Enum.KeyCode.LeftControl then
		mE:FireServer('Crouch', false)
	end
end)

I used RenderStepped as suggested to check the attributes that are set by the server.

runService.RenderStepped:Connect(function()
	if character:GetAttribute('Running') == true then
		--print('Running')
		humanoid.WalkSpeed = character.Attributes.SprintSpeed.Value
	elseif character:GetAttribute('Walking') == true then
	--	print('Walking')
		humanoid.WalkSpeed = character.Attributes.BaseSpeed.Value
	elseif character:GetAttribute('Punching') == true and character:GetAttribute('Stunned') == false and character:GetAttribute('Running') == false then
		humanoid.WalkSpeed = character.Attributes.BaseSpeed.Value/2	
	--	print('Punching')
	elseif character:GetAttribute('Stunned') then
		humanoid.WalkSpeed = 0
	elseif player.isBlocking.Value  then
		humanoid.WalkSpeed = baseSpeed/2.5
	end
	
end)

The issue with overlapping should be solved with the checking using renderstepped. Thank you for the suggestion! I was thinking of using this but I didn’t think it would work as intended. If there are any practices I could utilize or improve upon in my code, please also let me know. Im also not sure if I should just handle this on the server since it requires events anyway.

you shouldnt be using renderstepped, just use events or a module script…

The only other suggestion I can give you is to make sure you setup every walkspeed with the correct priority. So if stun walkspeed should be prioritized over running (which i’m guessing would be the case), make sure to put the stun if before the running if.

local walkspeed = character.Attributes.BaseSpeed.Value; -- we use a variable that is set to the base speed the character would have if none of the checks we do are true
if character:GetAttribute("Stunned") == true then -- since stunning completely stops the character, it should be prioritized so we don't perform needless checks later
  walkspeed = 0;
elseif player.IsBlocking.Value then -- blocking seems to be the next slowest walkspeed, so we put it just under stunning
  walkspeed = baseSpeed / 2.5;
elseif character:GetAttribute("Punching") == true then -- same logic for punching
  walkspeed /= 2;
elseif character:GetAttribute("Running") == true then
  walkspeed = character.Attributes.SprintSpeed.Value;
end;

humanoid.WalkSpeed = walkspeed;

This is how i’d do it personally but it changes on a case by case basis.

Why not? It’s clean and reliable. If he used events he’d have to connect so many of them (running/blocking/punching/etc) for every attribute/value that he needs to check and then check for the same parameters everytime. The code would get too long, while with RenderStepped you ensure the player has the correct speed every frame.

1 Like

Using events would take too long/be too messy and module scripts are probably what I will use later on if I need to but using runservice also kills two birds with one stone, the player walkspeed is now protected by this since the players speed is virtually what it needs to be at all times.

Yes, I already added priority to multiple states and it has been running as intended! Thanks for the help.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.