Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
0

Why doesn't this script work?

Asked by 9 years ago

Please make your question title relevant to your question content. It should be a one-sentence summary in question form.

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

Log in to vote
2
Answered by
BlueTaslem 18071 Moderation Voter Administrator Community Moderator Super Administrator
9 years ago

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

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! Shrekerly 70 — 9y
Ad

Answer this question