Hello everyone! 
So I’m currently working on a survival game where the players have to find a way to survive attacking drones, which are able to track paths and sounds. The drones are supposed to behave similar to the egg drones of the Sonic Movie franchise:
A video of my progress (the visualized path you see in the video is not part of the drone)
Extra: Uhhhhh
As you can see in the video, the drone can duck if it detects a roof, and can go up when the ground below it goes up as well. Currently, the system searches the most direct way (in a straight line) to the target (which is a Vector3).
The current script
local RunService = game:GetService("RunService")
local Drone = script.Parent
local RootPart = Drone.RootPart
local LinearVelocity = RootPart.LinearVelocity
local AlignOrientation = RootPart.AlignOrientation
local RayParams = RaycastParams.new()
RayParams.FilterDescendantsInstances = {Drone, table.unpack(CollectionService:GetTagged("AI_RaycastIgnore"))}
RayParams.FilterType = Enum.RaycastFilterType.Exclude
local Speed = 10
local HeightResponsiveness = 2.5
local SearchingHeight = 10
local ObservingHeight = 25
local MaxScanDistance = 100
local Waypoints = {
Vector3.new(-57, 30, -111),
Vector3.new(10, 46, -90),
Vector3.new(-55, 16, 30)
}
local currentWaypointIndex = 1
local connection
local Mode = "Searching"
local function getTargetHeight()
local forwardOffset = 10 -- How many studs ahead to predict
local droneCFrame = RootPart.CFrame
local origin = droneCFrame.Position
local forwardPosition = origin + droneCFrame.LookVector * forwardOffset
-- Raycast down from current position
local downResult = workspace:Raycast(origin, Vector3.new(0, -MaxScanDistance, 0), RayParams)
-- Raycast down from forward position
local forwardDownResult = workspace:Raycast(forwardPosition, Vector3.new(0, -MaxScanDistance, 0), RayParams)
-- Optionally raycast up if you care about ceilings
local upResult = workspace:Raycast(origin, Vector3.new(0, MaxScanDistance, 0), RayParams)
local forwardUpResult = workspace:Raycast(forwardPosition, Vector3.new(0, MaxScanDistance, 0), RayParams)
-- Find ground and ceiling ahead
local groundY, ceilingY
if forwardDownResult then
groundY = forwardDownResult.Position.Y
elseif downResult then
groundY = downResult.Position.Y
end
if forwardUpResult then
ceilingY = forwardUpResult.Position.Y
elseif upResult then
ceilingY = upResult.Position.Y
end
-- If both found, hover in the middle
if groundY and ceilingY then
return (groundY + ceilingY) / 2
elseif groundY then
if Mode == "Searching" then
return groundY + SearchingHeight
else
return groundY + ObservingHeight
end
elseif ceilingY then
if Mode == "Searching" then
return groundY - SearchingHeight
else
return groundY - ObservingHeight
end
else
return origin.Y -- No surfaces found, stay at current Y
end
end
function updateMovement(targetWaypoint: Vector3)
connection = RunService.Heartbeat:Connect(function()
local horizontalDirection = (Vector3.new(targetWaypoint.X, RootPart.Position.Y, targetWaypoint.Z) - Vector3.new(RootPart.Position.X, RootPart.Position.Y, RootPart.Position.Z)).Unit
local horizontalVelocity = horizontalDirection * Speed
local desiredY = getTargetHeight()
local heightError = desiredY - RootPart.Position.Y
local verticalVelocity = Vector3.new(0, heightError * HeightResponsiveness, 0)
local finalVelocity = horizontalVelocity + verticalVelocity
LinearVelocity.VectorVelocity = finalVelocity
if horizontalDirection.Magnitude > 0.1 then
local lookAtCFrame = CFrame.lookAt(RootPart.Position, RootPart.Position + horizontalDirection)
AlignOrientation.CFrame = lookAtCFrame
end
local distanceToWaypoint = (Vector3.new(RootPart.Position.X, 0, RootPart.Position.Z) - Vector3.new(targetWaypoint.X, 0, targetWaypoint.Z)).Magnitude
if distanceToWaypoint < 5 then
LinearVelocity.VectorVelocity = Vector3.zero
connection:Disconnect()
end
end)
end
local targetPos = Waypoints[currentWaypointIndex]
updateMovement(targetPos)
How it is set up
But of course this is not how I want it to function in-game. A drone has to find its own path to the target, including avoiding obstacles.
With Roblox’s current pathfinding system, which is mainly used for ground-based NPCs, it is nearly impossible to achieve flight-based pathfinding without having to make your own system for it.
I hope that someone out there has tips or something else that I could use to achieve the pathfinding functionality that I want to achieve.