RemoteEvents acting strangely

When holding down a key, my RemoteEvents seem to act really weird and messes up in many different ways.

Context & Scenario: I am making a soccer/football-based game, and I am currently working on a Low Pass movement which the player can control the power of by holding down the key. As the key is held down, the power goes up by increments of 1 up to 100%, of course stopping if the key is released along the way. Once released, the power is inflicted onto the ball. Thing is that the power on the ball is the only thing working perfectly. I am doing this using a LocalScript in the Pass tool, and a Server Script in the ball. In addition, 3 RemoteEvents in ReplicatedStorage (2nd and 3rd being the child of the first one).

The Problems: When running this in studio, there are tons, and I mean TONS of different outcomes each time I hold the key. First time holding the key there is a 50% chance that the power percentage won’t even roll. If the percentage does roll, it either stops rolling a while after I released from the key, stops before I release from the key, starts & stops at the exact 0%, or doesn’t stop at all and reaches 100% (which I scripted to wait 2 seconds before releasing immediately). And just when I thought it was the end of it, the event that controls the power being selected runs twice after everything ended just for fun. Matter a fact, while I was typing this, I thought of an idea to try and fix it but instead was introduced to NEW PROBLEMS.

Things I’ve Tried: I had no idea what’s going on with most of this and I assumed half the stuff that occurred is due to delay between client and server. But this doesn’t make up for the things happening while I was still holding the key. Most I have tried was adding some debounces for the events & removing one of the events (I used to have 4). I realized early on that this is most likely due to my lack of knowledge on client to server relationships and my scripts probably being a bit messy.

Here are the scripts.

LocalScript within the Tool:

local Services = {
	Players = game:GetService("Players"),
	ReplicatedStorage = game:GetService("ReplicatedStorage"),
	Workspace = game:GetService("Workspace"),
	UserInputService = game:GetService("UserInputService")
}

local reFolder = Services.ReplicatedStorage:WaitForChild("RemoteEvents")

local Events = {
	lpassEvent = reFolder:FindFirstChild("LPassRE")
}

local tool = script.Parent
local toolOn = false

local pwrdebounce = false

local player = Services.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character:WaitForChild("Humanoid")
local animator = humanoid:WaitForChild("Animator")

local ball = Services.Workspace:FindFirstChild("Ball")

local Animations = {
	lpass = Instance.new("Animation")
}

Animations.lpass.AnimationId = "rbxassetid://17644737293"
Animations.lpass.Parent = script.Parent.Anims
local lpassTrack = animator:LoadAnimation(Animations.lpass)

local function onAction(track, event)
	track:Play()
	event:FireServer()
end

local function onPowerScroll(button, track, event)
	local PwrChangeRE = event.PowerChangeRE
	local PwrHeldRE = event.PowerHeldRE
	local PwrReleaseRE = event.PowerReleaseRE
	
	PwrHeldRE:FireServer()
	
	for power = 0, 100, 1 do
		if button == false then
			PwrReleaseRE:FireServer()
			print("its over! sent to server!")
			onAction(track, event)
			break
		elseif power == 100 then
			wait(2)
			PwrReleaseRE:FireServer()
			onAction(track, event)
			break
		end

		task.wait(0.00001)
	end
end

Services.UserInputService.InputBegan:Connect(function(input, gameProcessedEvent)
	local eHeld = Services.UserInputService:IsKeyDown(Enum.KeyCode.E)
	
	if toolOn == true and eHeld then
		onPowerScroll(eHeld, lpassTrack, Events.lpassEvent)
	end
end)

-- Many scripts have been left out for your convenience as they do not relate to the problem at hand.

Server Script in the ball:

local Services = {	
	Players = game:GetService("Players"),
	Debris = game:GetService("Debris"),
	ReplicatedStorage = game:GetService("ReplicatedStorage"),
	Workspace = game:GetService("Workspace"),
	RunService = game:GetService("RunService"),
	StarterPack = game:GetService("StarterPack")
}

local reFolder = Services.ReplicatedStorage:WaitForChild("RemoteEvents")

local Events = {
	drib = reFolder:WaitForChild("DribbleRE"),
	Fdrib = reFolder:WaitForChild("FDribbleRE"),
	flick = reFolder:WaitForChild("FlickUpRE"),
	lpass = reFolder:WaitForChild("LPassRE")
}

local Activates = {
	drib = false,
	Fdrib = false,
	flick = false,
	lpass = false
	
}

local ball = script.Parent
local Table = {}

local pwrdebounce = false
local pwrheld = false
local pwrreleased = false

local Power = ball:WaitForChild("Power")
local Pwrval = Power.Value

-------------------------------------------------------------

local function onPowerScroll(event)
	if pwrheld == true then
		pwrheld = false
		for power = 0, 100, 1 do
			print(power .. "%")
			
			if pwrreleased == true then
				print("stop! The power is " .. power .. "%")
				pwrreleased = false
				Power.Value = power
				Pwrval = Power.Value
				break
			elseif power == 100 then
				print("stop! The power is full!")
				pwrreleased = false
				Power.Value = power
				Pwrval = Power.Value
				break
			else
				print("keep goin")
			end
			
			task.wait(0.00001)
		end
	end 
end

Events.lpass.PowerReleaseRE.OnServerEvent:Connect(function()
	pwrreleased = true
	print("its over! message from client!")
end)

Events.lpass.PowerHeldRE.OnServerEvent:Connect(function()
	pwrheld = true
	onPowerScroll(Events.lpass)
end)

Events.lpass.OnServerEvent:Connect(function()
	Activates.lpass = true
	wait(0.3)
	Activates.lpass = false
end)

local function onBallActive(root, F1, F2)
	local Settings = {
		Kick_Force1 = F1, -- Height
		Kick_Force2 = F2 -- Distance
	}

	local Direction = CFrame.lookAt(root.Position, ball.Position).LookVector
	if Direction.Magnitude < 0.001 then
		return
	end

	ball.AssemblyLinearVelocity = (Direction.Unit * Settings.Kick_Force2) + Vector3.new(0, Settings.Kick_Force1, 0)
end

 ---------------------------------------------------------------

ball.Touched:Connect(function(Part)
	local Character = Part.Parent
	if not Character then
		return
	end
	
	local Player = Services.Players:GetPlayerFromCharacter(Character)
	local Humanoid = Character:FindFirstChildOfClass("Humanoid")
	local Root = Character:FindFirstChild("HumanoidRootPart")

	if not Player or not Humanoid or Humanoid.Health <= 0 or not Root or table.find(Table, Player) then
		return
	end
	
	if Activates.lpass == true then
		onBallActive(Root, 20, Pwrval)
		print("lpass")
		Activates.lpass = false
	end
end)

-- Many scripts have been left out for your convenience as they do not relate to the problem at hand.

Please let me know if this is an Events problem, script layout problem, or I just outright did this incorrectly.

And as always, thank you in advance.

2 Likes

I wonder whether the use of both InputBegan and InputEnded might be more suitable if your current events are unreliable.
The flaw I see in your current method relates to how InputBegan requires a further input on releasing E to check the button == false in onPowerScroll(). I don’t believe that is truly a valid check for you in that instance.

Documentation on the vents for reference:

I actually tried using InputEnded in the place of button == false in earlier stages. I tried it again and it seems to do the same thing it did when I used it before. It doesn’t combat holding down keys, so it instantly fires when I press E.

I do however feel that simply finding a better, more organized way for the client and server to communicate between that doesn’t take so many RemoteEvents. I’ve got a feeling that the RemoteEvents are greatly delaying the process, dwindling down to 1 or 2 would be better.