I’m trying to detect on the server when a player’s character has teleported from PointA to an undefined PointB, and the distance between it.
I tried to achieve this by using GetPropertyChangedSignal(‘Position’) on the HumanoidRootPart, but this doesn’t seem to be working. It’s not firing the event when my character moves.
local Players = game:GetService('Players')
local VerifiedPlayers = {}
function SetupVerification(player)
local Character = player.Character or player.CharacterAdded:Wait()
Character = player.Character
local HRP = Character:WaitForChild('HumanoidRootPart')
local CurrentPosition = HRP.Position
HRP:GetPropertyChangedSignal('Position'):Connect(function()
local DistanceTravelled = (CurrentPosition - HRP.Position).magnitude
print(DistanceTravelled)
CurrentPosition = HRP.CFrame.Position
end)
end
for _ , player in pairs (Players:GetPlayers()) do
if not (VerifiedPlayers[player]) then
VerifiedPlayers[player] = true
end
SetupVerification(player)
end
Players.PlayerAdded:Connect(function(player)
if not (VerifiedPlayers[player]) then
VerifiedPlayers[player] = true
end
SetupVerification(player)
end)
Players.PlayerRemoving:Connect(function(player)
if (VerifiedPlayers[player]) then
VerifiedPlayers[player] = nil
end
end)
1 Like
Changed
and its neighbor events will only fire for when a script explicitly changes something, so the fact that it never fires when you do standard movement via controls is to be expected.
Seeing your code, I recommend a loop connected to something like RunService.Heartbeat
or RunService.Stepped
(either works) to poll the position once every frame. In the context of your script, granted you remember to clean up your connection should the player reset or quit, you could actually just replace the HRP connection with the RunService connection.
Now as for firing when you teleport them? I’d think it would change. I think it only fires for the property you script though, so if you set CFrame, it’s going to fire for CFrame, not Position or Rotation.
1 Like
I was experimenting with ways to achieve what I needed and this is actually exactly the solution I tried out, and it works! I decided to check the player’s position every 1/5th of a second. How would you recommend cleaning up the RunService connections? The script I currently have is this:
local Players = game:GetService('Players')
local RunService = game:GetService('RunService')
local VerifiedPlayers = {}
function SetupVerification(player)
local Character = player.Character or player.CharacterAdded:Wait()
Character = player.Character
local HRP = Character:WaitForChild('HumanoidRootPart')
local CurrentPosition = HRP.Position
local passedtime, debounce, steplength = 0, false, 0.2
VerifiedPlayers[player].connection = RunService.Heartbeat:Connect(function(step)
passedtime += step
if passedtime > steplength then
passedtime = 0
debounce = false
end
if not (debounce) then
debounce = true
local CharPos = HRP.Position
local DistanceTravelled = (CurrentPosition - CharPos).magnitude
if DistanceTravelled > 0.1 then
print(DistanceTravelled)
end
CurrentPosition = CharPos
end
end)
end
for _ , player in pairs (Players:GetPlayers()) do
if not (VerifiedPlayers[player]) then
VerifiedPlayers[player] = {}
end
SetupVerification(player)
end
Players.PlayerAdded:Connect(function(player)
if not (VerifiedPlayers[player]) then
VerifiedPlayers[player] = {}
end
SetupVerification(player)
end)
Players.PlayerRemoving:Connect(function(player)
if (VerifiedPlayers[player]) then
VerifiedPlayers[player].connection:Disconnect()
VerifiedPlayers[player] = nil
end
end)
Edit: Added a disconnect to it.
Yeah, that script there works. I had been writing a reply to preserve the boolean, but that there also works just fine.
As for whether or not you want to make the values of VerifiedPlayers
the connections themselves is up to you (I’d personally rename the table at that point) or you can store it in a sub-table as .connection
, but either way, that will work.
The only thing you need to remember to do is disconnect any old connections at the start of SetupVerification
because connections don’t get GC’d unless the thing they are connected to is destroyed, and RunService can’t be destroyed, obviously. It’d cause stacking connections for every reset / reload.
Another thing is that you should run SetupVerification
in player.CharacterAdded
so that if they reset, it tracks the proper current character. I’d still bind it to the associated player (via Players:GetPlayerFromCharacter
), but that is something to note.
1 Like
Thanks for the reminder and pointing that out. I was thinking of adding the CharacterAdded event inside SetupVerification
. That way I only need to disconnect when the player leaves, I believe.
1 Like