Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
✓ ANSWER ACCEPTED

Why doesn't this script work?

So, this script is supposed to print that a Player is close to a gate when they are within 6 studs. But, for some reason, it does not do so, even when they are within the specified amount of studs. Can you help me understand why it is not working?

-----------------
--| Variables |--
-----------------
local Players = game:GetService("Players")

local Gates = script.Parent:GetChildren()

local RequiredDistance = 6

-----------------
--| Functions |--
-----------------
function GetDistance(Object)
	if (Object:IsA("Player")) then
		for _,Child in pairs(Gates) do
			if (Child:IsA("Part")) then
			local Distance = Object:DistanceFromCharacter(Child.Position)
				if (Distance <= RequiredDistance) then
					return true
				end
			end
			return false
		end
	end
end

-----------------
--| Main Code |--
-----------------
Players.PlayerAdded:connect(function(Player)
	local Character = Player.Character or Player.CharacterAdded:wait()
	repeat wait() until Character.Torso
	local Torso = Character.Torso
	Torso.Changed:connect(function()
		if (GetDistance(Player)) then
			print(Player.Name.." is close to a gate!")
		end
	end)
end)

1 answer

✓ Accepted answer

Cleanup

  • You should really use better variable names.
    • Child is a poor name for a Gate.
    • Object is a poor name for a Player.
    • GetDistance is a poor name for something that doesn't return a number. IsNearGate or NearGate makes more sense.
  • You don't need parenthesis around conditions, and it's not idiomatic to include them.
  • It's widely regarded best to fail fast. There's no reason for GetDistance/NearGate to only continue if it's given a player. The only check that might belong is assert(Player:IsA("Player")). It is the caller's responsibility to give the right parameters.

The Problem

There are two problems with this code.

First, that only the first torso will be tracked by this script -- if they die, you'll still have Torso pointing to the first torso they had. This actually won't matter, because of the second point:

.Changed doesn't fire for changes caused by physics. Consequently, while teleporting the player will trigger the changed event, walking won't.

There isn't really a good event to get when the player moves (it would happen too often anyway). It's much more straightforward to just check every half a second with a while loop:

Players.PlayerAdded:connect(function(Player)
	while Player.Parent do
		if NearGate(Player) then
			print(Player.Name .. " is close to a gate")
		end
		-- check twice a second
		wait(1/2)
	end
end)

Note that DistanceFromCharacter returns 0 if the player doesn't have a head, so between lives this will believe that they are near the gate. It might be a good idea to require Distance to also be above, say, .01 in addition to being less than RequiredDistance

1 comment

0

Wow... This was an extremely helpful and constructive answer. Honestly, one of the best I've ever gotten and seen. Thank you very, very much for your help!

This discussion is preserved as it was. New answers, comments, and votes are closed.