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.
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
Use Dot
Products of Vectors.
The dot product of two unit vectors (length/magnitude = 1) will tell you how similar two vectors are (in terms of direction) i.e. -1
if they’re exactly opposite, 0
if they are perpendicular or 1
if they’re the exact same.
Some code:
local RaycastResult = workspace:Raycast(Origin, Direction, RayParams); --// Make sure `Direction` is a unit vector
if (RaycastResult) then
if (RaycastResult.Instance) then
local Hit = RaycastResult.Position;
local DotProduct = Direction:Dot(Camera.CFrame.LookVector)
if (DotProduct > 0) then
--// 0 means perpendicular, so "> 0" means within less than 90 degrees (which means its within visible range)
end;
end;
end;
i literally never used raycasting for magnitude since its easier to do this
(EndPart.Position - StartPart.Position).Magnitude
It returns the direction into studs and it does the same thing except not using raycasts
You could detect when the player’s CFrame changes
Local Script:
local players = game:GetService("Players")
local runService = game:GetService("RunService")
local plr = game:GetService("Players").LocalPlayer
local char = plr.Character
local hrp : BasePart = char.HumanoidRootPart
local part = workspace.Part
local d
hrp:GetPropertyChangedSignal("CFrame"):Connect(function()
if (hrp.Position - part.Position).Magnitude <= 40 then
d = runService.RenderStepped:Connect(function()
--code
end)
else
if d then
d:Disconnect()
end
end
end)
or you could use :GetPartBoundsInRadius()
Server Script:
local runService = game:GetService("RunService")
local part = workspace.Part
runService.Heartbeat:Connect(function()
local inRadius = workspace:GetPartBoundsinRadius(part.Position, 40)
if #inRadius > 0 then
for _, v in pairs(inRadius) do
if v:FindFirstChildOfClass("Humanoid") then
---script
end
end
end
end)
Already figured knew this i was stuck on this:
Only takeaway from my reply is the concept of dot products.
Whatever I provided was just an example and a use case of how dot products should be used to tell how similar two (unit) vectors are (in terms of direction).