How do I detect if a part is on a ledge, in real time, for parts, not humans?
And how can I get the part that is not on on ground (the half of the part that is on air)
I thought of raycasting, but it would take a whole lot of raycasting…
Raycast downwards from all four corners of the part, if one of the cast rays hits the floor (baseplate) the part must be on a ledge.
local Workspace = workspace
local Part = Workspace.Part
local function IsOnLedge(Part)
local Corner1 = Part.Position + Vector3.new(Part.Size.X / 2, 0, Part.Size.Z / 2)
local Corner2 = Part.Position + Vector3.new(-Part.Size.X / 2, 0, -Part.Size.Z / 2)
local Corner3 = Part.Position + Vector3.new(Part.Size.X / 2, 0, -Part.Size.Z / 2)
local Corner4 = Part.Position + Vector3.new(-Part.Size.X / 2, 0, -Part.Size.Z / 2)
local Corners = {Corner1, Corner2, Corner3, Corner4}
local Parameters = RaycastParams.new()
Parameters.FilterDescendantsInstances = {Part}
for _, Corner in ipairs(Corners) do
local Direction = (Corner - (Corner + Vector3.new(0, 1, 0))).Unit
local Result = Workspace:Raycast(Corner, Direction * 50, Parameters)
if Result then
if Result.Instance.Name == "Baseplate" then
return true
end
end
end
return false
end
local Result = IsOnLedge(Part)
print(Result)
Result is ‘true’.
Result is ‘false’.
This works, very well, and thank you so much, but there are a few glitches, like it sometimes returning true when it’s not close to a ledge, or it returning false when its even over a ledge. And is there a way to get the area of the part that is on air?
This works, very well, and thank you so much, but there are a few glitches
I should clarify that the implementation I wrote will not work with rotated parts and/or parts already on the floor.
local Workspace = workspace
local Baseplate = Workspace.Baseplate --Reference to the 'floor' part.
local Part = Workspace.Part
local function IsOnLedge(Part)
local Corner1 = Part.CFrame * CFrame.new(Part.Size.X / 2, 0, Part.Size.Z / 2)
local Corner2 = Part.CFrame * CFrame.new(-Part.Size.X / 2, 0, -Part.Size.Z / 2)
local Corner3 = Part.CFrame * CFrame.new(Part.Size.X / 2, 0, -Part.Size.Z / 2)
local Corner4 = Part.CFrame * CFrame.new(-Part.Size.X / 2, 0, -Part.Size.Z / 2)
local Corners = {Corner1, Corner2, Corner3, Corner4}
local Parameters = RaycastParams.new()
Parameters.FilterDescendantsInstances = {Part}
local Results = {}
for _, Corner in ipairs(Corners) do
local Position = Corner.Position
local Direction = (Position - (Corner * CFrame.new(0, 1, 0)).Position).Unit
local Result = Workspace:Raycast(Position, Direction * 50, Parameters)
if Result then
local Distance = (Result.Position - Position).Magnitude
if Result.Instance ~= Baseplate or Distance > Part.Size.Y / 2 then
if not table.find(Results, Result.Instance) then
table.insert(Results, Result.Instance)
end
end
end
end
return if (table.find(Results, Baseplate) and #Results > 1) then true else false
end
local Result = IsOnLedge(Part)
print(Result)
Here’s an implementation which is compatible with rotated parts and parts already on the floor (baseplate).
Result is ‘true’.
Result is ‘false’.
Result is ‘false’.
Result is ‘true’.
Result is ‘false’.