RemoteEvent not working properly

I’m trying to learn and understand RemoteEvents, however not only does the localscript stop running after the RemoteEvent fires (resulting in the localscript not functioning properly), the results of the script on the server don’t replicate to the client. As I understand it, all server changes are supposed to automatically be sent to all clients.

Local:

while task.wait() do
	if sprinting then
		if stamina > 0 then
		for _, keyCode in pairs(movementKeys) do
			if uis:IsKeyDown(keyCode) then
					stamDecrease:FireServer(stamina, 0.25, humanoid, sprintSpeed)
				end
			end
		else
			humanoid.WalkSpeed = regularSpeed
		end
	else
		if stamina < maxStamina then
			stamina += 0.025
		end
		humanoid.WalkSpeed = regularSpeed
	end
	plr.PlayerGui.Interface.bg.Bar:TweenSize(UDim2.new(stamina / maxStamina, 0, -1, 0), Enum.EasingDirection.In, Enum.EasingStyle.Linear, 0)
	game.Players.LocalPlayer.valHolder.stamCurrent.Value = stamina
end

Server:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local stamDecrease = ReplicatedStorage:WaitForChild("stamDecrease")

local function onStamIncrease(player, stamina, decrease, humanoid, sprintSpeed)
	print(player.Name .. " fired the RemoteEvent")
	stamina -= decrease
	print(stamina)
	humanoid.WalkSpeed = sprintSpeed
	player.valHolder.stamCurrent.Value = stamina
end

stamDecrease.OnServerEvent:Connect(onStamIncrease)

Server sided print:
image

Local view of the value:
image

Is there something missing for it to work properly?

3 Likes

Hey!

I suspect the line of the client:

game.Players.LocalPlayer.valHolder.stamCurrent.Value = stamina

of preventing the server value to replicate (or maybe it does but you cannot see it because it will be erased every RunService.Heartbeat)

Have a nice day

2 Likes

you were correct :smiley:
Although as you can see the stamina is still stuck on 9.75 instead of going down towards 0, and the sprint still doesn’t work after 1st loopthrough. Do you know why this is the case?

1 Like

Hey,
You are sending a stamina value to the server, but you don’t seem to decrease it on the client side.

As for the loop breaking, I don’t think I am able to help you as I don’t have enough informations.

while task.wait() do
	if sprinting then
		if stamina > 0 then
		for _, keyCode in pairs(movementKeys) do
			if uis:IsKeyDown(keyCode) then
					stamDecrease:FireServer(stamina, 0.25, humanoid, sprintSpeed)
                    stamina -= 0.25
				end
			end
		else
			humanoid.WalkSpeed = regularSpeed
		end
	else
		if stamina < maxStamina then
			stamina += 0.025
		end
		humanoid.WalkSpeed = regularSpeed
	end
	plr.PlayerGui.Interface.bg.Bar:TweenSize(UDim2.new(stamina / maxStamina, 0, -1, 0), Enum.EasingDirection.In, Enum.EasingStyle.Linear, 0)
end
2 Likes

what information would you need?
Adding the stamina decrease on server makes it even more broken and it starts glitching out D:

I need the following:

  • Is the stamina variable always updated with game.Players.LocalPlayer.valHolder.stamCurrent.Value ?

(I’ll certainly be able to help you tomorrow but no longer this evening because it’s really late for me)

1 Like

sure you can answer later. It is only updated in what I have given yes. The rest of the script related to sprinting and animations work. So it’s just that loop that’s bugging.

Hi there, for me, this should work,

Client:

while task.wait() do
	if sprinting then
		if stamina > 0 then
			for _, keyCode in pairs(movementKeys) do
				if uis:IsKeyDown(keyCode) then
					stamDecrease:FireServer(stamina, 0.25, humanoid, sprintSpeed)
					stamina -= 0.25
				end
			end
		else
			humanoid.WalkSpeed = regularSpeed
		end
	else
		if stamina < maxStamina then
			stamina += 0.025
		end
		humanoid.WalkSpeed = regularSpeed
	end
	plr.PlayerGui.Interface.bg.Bar:TweenSize(UDim2.new(stamina / maxStamina, 0, -1, 0), Enum.EasingDirection.In, Enum.EasingStyle.Linear, 0)
end

The server code is untouched, it’s the one from the very beginning.

1 Like

this makes it very glitchy as you can see

I would suspect task.wait() of being too fast, try with a 0.2 delay.

it’s not glittching anymore but it still is completely broken. Here are the issues I noticed:

  1. The stamina doesn’t regenerate before clicking shift (it’s like it’s regenerating in the background or something)
  2. The sprint no longer works after doing it once

Interestingly enough the bar moves correctly, but it doesn’t show the correct stamina in either the player’s numberValue instance or the display on the bar.

The sprint no longer works after doing it once

I suspect that the code that controls if we are allowed to set sprinting to true is using the value game.Players.LocalPlayer.valHolder.stamCurrent instead of using the variable stamina. (This is the only explanation I could have for this)

The stamina doesn’t regenerate before clicking shift (it’s like it’s regenerating in the background or something)

Maybe you forgot to add code that sets sprinting to false when shift is released ?

It happends after adding the remotevent and/or adding the -0.25 stamina local…
I can show you the scripts to give a better overview.

Local

local char = script.Parent
local humanoid = char:WaitForChild("Humanoid")
local plr = game.Players.LocalPlayer
local uis = game:GetService("UserInputService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local stamDecrease = ReplicatedStorage:WaitForChild("stamDecrease")
	
local movementKeys = {
	Enum.KeyCode.W,
	Enum.KeyCode.S,
	Enum.KeyCode.D,
	Enum.KeyCode.A
}

local sprintKey = Enum.KeyCode.LeftShift
local WalkAnim = script.Parent.CharacterAimations:WaitForChild("Walk")
local walkAnimTrack = humanoid.Animator:LoadAnimation(WalkAnim)

local uis = game:GetService("UserInputService")
local label = game.Players.LocalPlayer.PlayerGui.Interface.bg.TextLabel

local maxStamina = game.Players.LocalPlayer.valHolder.stamMax.Value
local stamina = game.Players.LocalPlayer.valHolder.stamCurrent.Value
label.Text = ""..stamina.."/"..maxStamina..""

local sprinting = false
local sprintSpeed = 30
local regularSpeed = 15

function startSprint()
	sprinting = true
end

function stopSprint()
	sprinting = false
end

function checkKey(key, isTyping, doSprint)
	local player = game:GetService("Players").LocalPlayer
	local character = player.Character or player.CharacterAdded:Wait()
	local humanoid = character:WaitForChild("Humanoid")
	if not isTyping then
		if key.KeyCode == sprintKey then
			if doSprint then
				startSprint()
			else
				stopSprint()
			end
		end
	end
end

uis.InputBegan:Connect(function(key, isTyping)
	checkKey(key, isTyping, true)
end)

uis.InputEnded:Connect(function(key, isTyping)
	checkKey(key, isTyping, false)
end)

while task.wait(0.01) do
	if sprinting then
		if stamina > 0 then
			for _, keyCode in pairs(movementKeys) do
				if uis:IsKeyDown(keyCode) then
					stamDecrease:FireServer(stamina, 0.25, humanoid, sprintSpeed)
					stamina -= 0.025
				end
			end
		else
			humanoid.WalkSpeed = regularSpeed
		end
	else
		if stamina < maxStamina then
			stamina += 0.025
		end
		humanoid.WalkSpeed = regularSpeed
	end
	plr.PlayerGui.Interface.bg.Bar:TweenSize(UDim2.new(stamina / maxStamina, 0, -1, 0), Enum.EasingDirection.In, Enum.EasingStyle.Linear, 0)
end

Server

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local stamDecrease = ReplicatedStorage:WaitForChild("stamDecrease")

local function onStamDecrease(player, stamina, decrease, humanoid, sprintSpeed)
	stamina -= decrease
	print(stamina)
	humanoid.WalkSpeed = sprintSpeed
	player.valHolder.stamCurrent.Value = stamina
end

stamDecrease.OnServerEvent:Connect(onStamDecrease)
1 Like

well I did fix it by adding plr.valHolder.stamCurrent.Value = stamina under the place where it decreases stamina and humanoid.WalkSpeed = sprintSpeed under where it increase (both locally).
Though I must ask, is this really the way to do it? I thought the remotevent would know the player and humanoid so it could change its properties on the serverscript.

1 Like

Thanks to you showing your code, I have found something interesting for you:

(Maybe it’s not really what you want, but still wanting to show it:)

local stamina = game.Players.LocalPlayer.valHolder.stamCurrent.Value

This code will obtain the value of game.Players.LocalPlayer.valHolder.stamCurrent only once ! So the stamina won’t be synchornized with game.Players.LocalPlayer.valHolder.stamCurrent.

If you want ot have a always synchronized stamina value, you should instead set the variable stamina like this:

local stamina = game.Players.LocalPlayer.valHolder.stamCurrent

And index it like this:

stamina.Value

For this:

well I did fix it by adding plr.valHolder.stamCurrent.Value = stamina under the place where it decreases stamina and humanoid.WalkSpeed = sprintSpeed under where it increase (both locally).

The first thing can potentially be fixed by the new way of indexing values, and the second thing can instead done by calling the server to update your walk speed:

stamDecrease:FireServer(stamina, -0.25, humanoid, sprintSpeed)

I honestly hope this helps, because right now the message is pretty confusing.

1 Like

well that’s the thing, I did try to update my speed on the server, but it doesn’t increase it locally when doing that. Same thing with the stamina as I said, the properties for some reason don’t change locally when doing a remoteevent. I don’t know how it’s supposed to work, but if it is supposed to increase locally when it’s inreasing on the server, then it doesn’t work.

I’m not entirely sure why you’re duplicating the change on the server, as avatar movement is best handled by the client to ensure minimal latency. In this position, I’d simply remove the server’s involvement and handle the walkspeed and stamina entirely from the client. This could resolve any issues with what the client and server see, and we also wouldn’t have to worry about updating our variables on both sides.

but doesn’t that cause potential issues?
For example if the staminabar had to be shown to other players, or to prevent cheating.

In that situation, we send our stamina value to the server for it to show other players, but there’s no need to do anything else with it.

Additionally, with the way the LocalScript currently works, one can use an exploit to feed whatever values they want into the RemoteEvent. However, because the client can change the character’s walkspeed, there’s no need to do that at all. They can change it directly and it won’t be replicated.

1 Like

I’ve made some improvements to your code that might help it run better

local char = script.Parent
local humanoid = char:WaitForChild("Humanoid")
local plr = game.Players.LocalPlayer
local uis = game:GetService("UserInputService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local stamDecrease = ReplicatedStorage:WaitForChild("stamDecrease")
	
local movementKeys = {
	Enum.KeyCode.W;
	Enum.KeyCode.A;
	Enum.KeyCode.S;
	Enum.KeyCode.D;
}

local sprintKey = Enum.KeyCode.LeftShift
local WalkAnim = script.Parent.CharacterAimations:WaitForChild("Walk")
local walkAnimTrack = humanoid.Animator:LoadAnimation(WalkAnim)

local label = game.Players.LocalPlayer.PlayerGui.Interface.bg.TextLabel

local maxStamina = game.Players.LocalPlayer.valHolder.stamMax.Value
local stamina = game.Players.LocalPlayer.valHolder.stamCurrent.Value
label.Text = string.format("%d/%d", stamina, maxStamina)

local sprinting = false
local sprintSpeed = 30
local regularSpeed = 15

function startSprint()
	sprinting = true
end

function stopSprint()
	sprinting = false
end

function checkKey(key, isTyping, doSprint)
	if isTyping then return end
	if key.KeyCode ~= sprintKey then return end
	if doSprint then
		startSprint()
	else
		stopSprint()
	end
end

uis.InputBegan:Connect(function(key, isTyping)
	checkKey(key, isTyping, true)
end)

uis.InputEnded:Connect(function(key, isTyping)
	checkKey(key, isTyping, false)
end)

game:GetService("RunService").Heartbeat:Connect(function()
	if sprinting then
		if stamina > 0.025 then
			for _, keyCode in movementKeys do
				if uis:IsKeyDown(keyCode) then
					stamDecrease:FireServer(stamina, 0.25, humanoid, sprintSpeed)
					stamina -= 0.025
				end
			end
		else
			humanoid.WalkSpeed = regularSpeed
		end
	else
		if stamina < maxStamina then
		   stamina += 0.025
		   if stamina > maxStamina then stamina = maxStamina end
		end
		humanoid.WalkSpeed = regularSpeed
	end
	plr.PlayerGui.Interface.bg.Bar.Size = UDim2.new(stamina / maxStamina, 0, -1, 0)
end)
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local stamDecrease = ReplicatedStorage:WaitForChild("stamDecrease")

local function onStamIncrease(player, stamina, decrease, humanoid, sprintSpeed)
	print(player.Name .. " fired the RemoteEvent")
	stamina -= decrease
    if stamina < 0 then stamina = 0 end
	print(stamina)
	humanoid.WalkSpeed = sprintSpeed
	player.valHolder.stamCurrent.Value = stamina
end

stamDecrease.OnServerEvent:Connect(onStamIncrease)
2 Likes