local plr = game.Players.LocalPlayer
local char = plr.Character or plr.CharacterAdded:Wait()
local hum = char:WaitForChild("Humanoid")
hum:GetPropertyChangedSignal("MoveDirection"):Connect(function()
if (char.PrimaryPart.Position - SomePositionHere).mangitude < 50 then
--do something here
end
end)
So if I have 100 objects and 16 players moving around. All 100 objects should run that code all the time? won’t that “clog up” the system? That would be like 1600 operations every frame. Seems way less efficient than having a Touch-Event that only fires when someone enters? What am I missing?
You should use :GetPropertyChangedSignal on the Character’s root CFrame, MoveDirection’s Changed RBXScriptSignal will only fire if the player starts walking, stops or changes it’s walking direction, so sometimes it won’t detect the player.
Keep in mind this should be done on the client.
Yes, no. 2 would be too slow if you have like 100s of 1000s of objects. Use no. 1 if you can, otherwise use a spatial partitioning scheme to trade a bit of memory usage for execution time, e.g. quadtree or octree.
instead of putting all the load on the server each player should take responsibility for them self and tell the server when they are within range
and instead of blindly looping we can use the camera focus property to detect when the player has moved
we can also make it so that they have to move a few studs before checking the distance again in this demo i made them have to move 4 studs before checking the magnitude but that might be overkill because getting the magnitude to the object is not that expensive but i thought to include it just so you know how its done
-- server script
local event = game.ReplicatedStorage.RemoteEvent
event.OnServerEvent:Connect(function(player)
print(player, "is now in range")
end)
-- local scipt
local event = game.ReplicatedStorage.RemoteEvent
local camera = workspace.CurrentCamera
local position = Vector3.new(math.huge, math.huge, math.huge)
local object = workspace.Part
local inRange = false
local distance = 50
camera:GetPropertyChangedSignal("Focus"):Connect(function()
-- if the player has not moved more then 4 studs then exit the function
if (position - camera.Focus.Position).Magnitude < 4 then return end
-- if the player has moved more then 4 studs then update the position
position = camera.Focus.Position
-- get how far the player is from the object
local magnitude = (object.Position - position)
if inRange == false then
if magnitude < distance then
inRange = true
event:FireServer()
end
else
if magnitude > distance then
inRange = false
end
end
end)
Hmm, I guess that could work, but again, if you have a lot of different parts then you would have to write some kind of code to get a list of all the relevant objects. Sounds like it could be pretty messy.
You just put all your “different parts” into a folder and do as following
local PartToDetectWithinRange = Folder:FindFirstChild(Part)
if PartToDetectWithinRange and (position - PartToDetectWithinRange.Position).Magniture < Range then
--Run code here, you can even assign the part some attributes to make some specific code for some parts.
end
Or you could predefine a dictionary and do: (In this case, it will rely on the part.name
local function FunctionA(ValueA,ValueB)
print(ValueA,ValueB)
end
local function FunctionA(ValueA,ValueB)
print(ValueA,ValueB)
end
local DictionaryOfParts = {
["Bed"] = {"SpecificFunction"=FunctionA}
["Checkpoint"] = {"SpecificFunction"=FunctionB}
["Mountain"] = {"SpecificFunction"=false}
}
local PartToDetectWithinRange = DictionaryOfParts[Part.Name]
if PartToDetectWithinRange and (position - PartToDetectWithinRange.Position).Magniture < Range then
--Run code here
local SpecificFunction = DictionaryOfParts[Part.Name]["SpecificFunction"]
if SpecificFunction then
SpecificFunction("Hello", "World") -- This is a function we defined, as a test we send 2 values :)
end
end
-- server script
local event = game.ReplicatedStorage.RemoteEvent
event.OnServerEvent:Connect(function(player, part)
print(player, "is now in range of", part.Name)
end)
-- local scipt
local event = game.ReplicatedStorage.RemoteEvent
local camera = workspace.CurrentCamera
local position = Vector3.new(math.huge, math.huge, math.huge)
local inRange = {}
local distance = 50
camera:GetPropertyChangedSignal("Focus"):Connect(function()
-- if the player has not moved more then 4 studs then exit the function
if (position - camera.Focus.Position).Magnitude < 4 then return end
-- if the player has moved more then 4 studs then update the position
position = camera.Focus.Position
for i, child in ipairs(workspace.Folder:GetChildren()) do
-- get how far the player is from the child
local magnitude = (child.Position - position)
if inRange[child] == nil then
if magnitude < distance then
inRange[child] = true
event:FireServer(child)
end
else
if magnitude > distance then
inRange[child] = nil
end
end
end
end)
its also possible to do a chunk system where you group parts into chunks so that you only loop the objects in the chunks around the player but that’s a bit more complex i hope to make a video on my YouTube channel in the future explaining how
Please, please, please explain how I would do this. I know there are already modules on the site about it, but I want to know HOW. See my game is extremely laggy, because I have an incredible amount of parts and every frame I’m doing check to see whether they’re overlapping or not. part2.Position - part1.Position).Magnitude < part2.Size.Z / 2 + part1.Size.Z / 2 to the max.
And I’m doing this for on an average basis HUNDREDS AND HUNDREDS of parts every 1/60th of a second, I would rather use memory.
Use WorldRoot | Roblox Creator Documentation and only check parts returned by that. Should be lots faster because Roblox internally uses a spatial data structure for those types of queries (or they should, anyway).