Hey all! I’m working on a system for my game where you rack up points based on how long someone has been flying/moving and I am having some troubles with the local script side of things. I feel like I may be going about it the wrong way as well so any pointers I’ll take!
As previously stated, I do not know how to get the points value to stop ticking up on the GUI even after the while loop on the server side has finished and returns a Boolean to the local script.
I’ve tried various things such as using a remote function, but that only returns a value AFTER everything has ran. I could use 2 client firing events but that seems clunky. I liked that idea of using the client event twice though so what I’m trying is to fire one client event with 2 different Boolean values but I don’t quite understand how it works. I will leave the script bellow so you all can see what I am talking about.
Local Script:
local replicatedStorage = game:GetService("ReplicatedStorage")
local eventCalls = replicatedStorage:WaitForChild("LocalEventCalls")
local pointsEvent = eventCalls:WaitForChild("PointsEvent")
local pointsGUI = script.Parent
local pointAmount = pointsGUI.Frame["Point Amount"]
local pointCounter = 0
pointsEvent.OnClientEvent:Connect(function(addingPoints)
pointsGUI.Enabled = true
print("Client fired")
while addingPoints == true do
pointAmount.Text = pointCounter
pointCounter += 1
if addingPoints == false then --Currently not functioning
print("Not true anymore")
break
end
task.wait()
end
end)
Module Script:
local addingPoints = true
pointsEvent:FireClient(player, addingPoints)
while addingPoints == true do
local distance = (humanPlayer.Position - victimRootPart.Position).Magnitude
--print(math.ceil(distance))
print("Player is moving")
if victimRootPart.Velocity.Magnitude < 0.1 then
addingPoints = false
pointsEvent:FireClient(player, addingPoints)
--print("Player has stopped")
return distance
end
task.wait()
end
As a bonus, if there is any way that I can directly plug the currently flung distance into the GUI element so that it’s accurate that would be wildly appreciated. Thanks!
Hello! First of all i wanted to mention the fact your script is pretty unoptimised i recommend using RunService.Heartbeat instead of the while loop. Also can you explain which booleans you want to send? It provides more context.
Since you’re passing the value through a RemoteEvent, it creates a copy of the boolean’s value, not the current value. This means if you change the boolean on the server, it doesn’t affect the copy of the boolean.
To solve this, you can create a BooleanValue on the Player (In PlayerService Or The Character) and change the boolean through there. You can replace the RemoteEvents entirely and just switch it out for a .Changed event signal and THEN run the loop there.
So something like:
Local Script
local RunService = game:GetService("RunService")
local player = game:GetService("Players").LocalPlayer
local pointCounter = 0
local addingPoints = player:WaitForChild("AddingPoints")
local function addPoints()
if addingPoints.Value == true then
pointCounter += 1
print(pointCounter)
-- Additional Code here
end
-- You dont need an extra check to see if the boolean is set to false unless you want extra code
end
RunService.Heartbeat:Connect(addPoints)
Server Script:
local addingPoints = player.AddingPoints
local RunService = game:GetService("RunService")
function checkPoints()
while addingPoints.Value == true do
local distance = (humanPlayer.Position - victimRootPart.Position).Magnitude
--print(math.ceil(distance))
print("Player is moving")
if victimRootPart.Velocity.Magnitude < 0.1 then
addingPoints.Value = false
--print("Player has stopped")
return distance
end
end
end
checkPoints()
You can do something like this so the server and client can communicate to eachother properly.
local replicatedStorage = game:GetService("ReplicatedStorage")
local eventCalls = replicatedStorage:WaitForChild("LocalEventCalls")
local pointsEvent = eventCalls:WaitForChild("PointsEvent")
local pointsGUI = script.Parent
local pointAmount = pointsGUI.Frame["Point Amount"]
local pointCounter = 0
local thread = nil
local function addPointsLoop()
while true do -- Using task.cancel will stop this loop from running, even though it's a while true do loop
pointAmount.Text = pointCounter
pointCounter += 1
task.wait()
end
end
pointsEvent.OnClientEvent:Connect(function(addingPoints)
pointsGUI.Enabled = true
print("Client fired")
if addingPoints == true then
if thread == nil then -- If a thread exists, do not start a new loop
thread = task.spawn(addPointsLoop)
end
else
if thread then
task.cancel(thread)
thread = nil
print("Not true anymore")
end
end
end)
Edit: I forgot to add an end. The code should work correctly now
Hey! Didn’t know much about heartbeat but after reading into it and understanding your solution its worked out quite well! Though this is marked as a solution already there’s one more thing I would like to ask. How would I reference the other players root part in the local script so I can have a counter on the screen showing in real time how far the other person is traveling? I will send new images with the updated code if you would like to take a quick look at it.
Module Script:
local addingPoints = player:WaitForChild("AddingPoints")
local function checkPoints()
addingPoints.Value = true
while addingPoints.Value == true do
local distance = (humanPlayer.Position - victimRootPart.Position).Magnitude
print(math.ceil(distance))
print("Player is moving")
if victimRootPart.Velocity.Magnitude < 0.1 then
addingPoints.Value = false
player.leaderstats.Score.Value += math.ceil(distance)
end
task.wait()
end
end
checkPoints()
end
return module
Local Script:
local pointCounter = 0
local addingPoints = player:WaitForChild("AddingPoints")
local function addPoints()
if addingPoints.Value == true then
local distance = (hrp.Position).Magnitude --How would I reference the other player so I can show the distance in a GUI???
print(distance)
--print(pointCounter)
end
end
runService.Heartbeat:Connect(addPoints)
Sorry to poke you about what is probably another minor issue, just the small bumps you run into when learning game development for the first time.
Thanks!
local player = game:GetService('Players').LocalPlayer -- Gets the player (only works on LocalScripts)
local char = player.Character or player.CharacterAdded:Wait() -- Gets the player's Character or waits for it to load/be added in
player.CharacterAdded:Connect(function(newCharacter) -- When character respawns or gets added
char = newCharacter -- set the char variable to the new character
end)
you can reference the rootpart directly using char.PrimaryPart or create a new variable that updates when the CharacterAdded signal is triggered, so itll be something like:
loacl hrp = char.PrimaryPart
player.CharacterAdded:Connect(function(newCharacter) -- When character respawns or gets added
char = newCharacter -- set the char variable to the new character
hrp = newCharacter.PrimaryPart
end)