So keeping it simple every heartbeat i want to check the magnitude between a part and the player and if the magnitude is less than 40 i want it to run a functions which loops forever until the players magnitude is more than 40 studs. Even better would be if the players camera is looking at the part. Im doing this to remove possible lag. Any way to do this?
well, if you want to check for magnitude, you can use raycasts
as for “only if player is looking at the part”, i have no clue
Im confused because you can check magnitude by (Part.Position - OtherPart.Position).Magntiude. i shouldve been more specific im confused on the part of connecting and disconnecting the event when the player is out of the 40 stud magnitude range
just use an if statement no?
local rService = game:GetService("RunService")
local part = part
rService.Heartbeat:Connect(function()
if (part.Position - playerPart.Position).Magnitude >= 40 then
-- do something
else
-- do nothing lol
end
end)
i don’t think you can disconnect something like this without it breaking, my guess is you’d have to use a third party script to handle the connecting
Wont if statements every frame be expensive? And i was planning on adding multiple objects. I thought of using a table and inserting only the objects that are in range
Example:
local objects = {
--objects here
}
local SeenObjects = {}
RunService.Heartbeat:Connect(function()
--loops through all the objects and inserts only the objects in the 40 range
end)
Something like this but i have trouble figuring out how to actually add a function for each seen object that will run till its removed from the table
(Sorry for making it seem confusing this was the question i had in mind)
Use a hit detector or a player hit zone detection likes zoneplus, it doesn’t need to constantly detect if player is within the object.
Reconnecting and disconnecting heartbeat whenever they leave or enter.
i’m not necessarily experienced with .Heartbeat so i wouldn’t know
but i do use if statements in my .Heartbeat connections and it doesn’t seem to kill the performance, although i do have an above-average pc so it could also be that
but your method could also work
It will because how would it know when the player leaves the zone.
This is what im stuck on
Im not sure at this point thanks for your help though
Except i dont use zone plus if i were to look into the code it would probably have a constant check and i dont need it. Detection isnt the problem
I have an idea of this one.
The first one involving checking the center the object.
local _, onScreen = camera:WorldToViewportPoint(corner.Position)
if onScreen then
return true
end
the second one just like first one but checking each corner of the object (assuming it a box)
canCameraSeeRegion = function(cam:Camera, region: Region3): boolean
local camera = cam or workspace.CurrentCamera
local regionSize = Vector3.new(math.abs(region.Size.X), math.abs(region.Size.Y), math.abs(region.Size.Z))
local regionCFrame = region.CFrame
local corners = {
regionCFrame * CFrame.new(regionSize.X / 2, regionSize.Y / 2, regionSize.Z / 2),
regionCFrame * CFrame.new(regionSize.X / 2, regionSize.Y / 2, -regionSize.Z / 2),
regionCFrame * CFrame.new(-regionSize.X / 2, regionSize.Y / 2, -regionSize.Z / 2),
regionCFrame * CFrame.new(-regionSize.X / 2, regionSize.Y / -2, -regionSize.Z / 2),
regionCFrame * CFrame.new(-regionSize.X / 2, regionSize.Y / -2, regionSize.Z / 2),
regionCFrame * CFrame.new(regionSize.X / 2, regionSize.Y / -2, regionSize.Z / 2),
regionCFrame * CFrame.new(regionSize.X / 2, regionSize.Y / -2, -regionSize.Z / 2),
regionCFrame * CFrame.new(-regionSize.X / 2, regionSize.Y / -2, -regionSize.Z / 2),
}
for _, corner in ipairs(corners) do
local _, onScreen = camera:WorldToViewportPoint(corner.Position)
if onScreen then
return true
end
end
table.clear(corners)
return false
end
It not great running it in loop, I use them via a scheduler following the player fps
This is useful the region arg in the function is just the object?
Sorry about the function I just fork it from my code you can convert an object into region via this.
createRegion = function(cframe:CFrame, size:Vector3) : Region3
return Region3.new(cframe.Position - (size / 2), cframe.Position + (size / 2))
end
You can try canCameraSeeRegion with an object since it only needs a CFrame and Size
You can use PostSimulation to not cap at 60fps
You could just use RunService to check the magnitude, then run the function if that magnitude were to be less than 40.
And do you know how i can connect and disconnect the code after they left the 40 studs
Okay isnt region 3 decaprecated? Ill still use it if its my only option
There are a lot of ways you can do this depending, it just depends on what you’re trying to specifically do. Like @lnguyenhoang42 said, you technically don’t need to run every heartbeat to check if the script is close, you can just use a part, and when that part is touched, then activate the script. And to detect when player has left you can just use constantly check the player’s character magnitude to the part’s position. [Edit change the fact you don’t need workspace:GetPartsInBounds]
local part = script.Parent::Part
local currentChar
function e()
while true do
-- whatever you want to happen
if (currentChar.PrimaryPart.Position - part.Position).Magnitude <= 40 then -- Turns script off if player is not 40 studs nearby
currentChar = nil
return --Turn off while loop
end
task.wait()--so it don't crash
end
end
part.Touched:Connect(function(hit)
if not currentChar then
if hit.Parent:FindFirstChild("Humanoid") then
currentChar = hit.Parent
e()
end
end
end)
The above script should work, though only detects for a single player near the script.
Also here’s a video you might want to watch when detecting if player is looking at something.
Using workspace :GetPartsInBounfbwill still require a constant check thr gsme has no idea when the player will decide to leave and ghe heartbeat check on the client is just fine. Thanks for the video its something ive been looking for a while
