So, I’ve been working on this Pathfinding AI thing that I can reuse overtime, Everything is working fine besides one thing, no the AI doesn’t stutter (well It kinda does but you get what i’m trying to say).
So, the issue is that the NPC seems to be slower whilst playtesting (KEEP IN MIND THE WALKSPEED IS 50).
Theres not much else to say, but heres a video of it.
Playtesting:
Running on the server:
The script:
script.Parent.PrimaryPart:SetNetworkOwner(nil)
--// MAIN FUNCTIONS \\--
function RayCheck(target)
local origin = AIRoot.Position
local direction = (target.Position - AIRoot.Position).Unit * CONFIG_DR
local rp = RaycastParams.new()
rp.FilterDescendantsInstances = {script.Parent}
rp.FilterType = Enum.RaycastFilterType.Blacklist
local result = workspace:Raycast(origin, direction, rp)
if result then
if result.Instance:IsDescendantOf(target.Parent) and math.abs(result.Position.Y - AIRoot.Position.Y) < 2 then
return true
else
return false
end
end
end
function MoveToRayCheck(pos)
local origin = AIRoot.Position
local direction = (pos - AIRoot.Position).Unit * CONFIG_DR
local rp = RaycastParams.new()
rp.FilterDescendantsInstances = {script.Parent}
rp.FilterType = Enum.RaycastFilterType.Blacklist
local result = workspace:Raycast(origin, direction, rp)
if result then
return false
else
return true
end
end
function FOVCheck(target) -- DEPRECATED
local npcToChar = (target.Position - script.Parent.Head.Position).Unit
local npcLook = script.Parent.Head.CFrame.LookVector
local dotProduct = npcToChar:Dot(npcLook)
if dotProduct > 0.5 then
if RayCheck(target) then
print("IN FOV")
return true
else
return false
end
else
print("NOT IN FOV")
return false
end
end
local function MoveRandomly()
print("MOVING RANDOMLY")
local X_Rand = math.random(-25, 25)
local Z_Rand = math.random(-25, 25)
local FinalResult = Vector3.new(X_Rand, 0, Z_Rand)
if MoveToRayCheck(AIRoot.Position + FinalResult) then
repeat
AIHum:MoveTo(AIRoot.Position + FinalResult)
AIHum.MoveToFinished:Wait(1)
until PathfindingToTarget == true or (AIRoot.Position - (AIRoot + FinalResult)).Magnitude < 3
end
end
local function FindTarget()
local ws = workspace
local dist = CONFIG_DR
local temp = nil
for i, v in pairs(workspace:GetDescendants()) do
if v:FindFirstChild("Humanoid") and v.Humanoid ~= AIHum then
if v:FindFirstChild("HumanoidRootPart") and v.HumanoidRootPart ~= AIRoot then
if (v.HumanoidRootPart.Position - AIRoot.Position).Magnitude < dist and v.Humanoid.Health > 0 and v.Humanoid ~= nil then
dist = (v.HumanoidRootPart.Position - AIRoot.Position).Magnitude
temp = v.HumanoidRootPart
end
end
end
end
return temp
end
local function CalculateAgentParam()
if AIHum.RigType == Enum.HumanoidRigType.R15 then
local Torso = script.Parent.UpperTorso
local Limb1 = script.Parent.RightUpperArm
local Limb2 = script.Parent.LeftUpperArm
local Head = script.Parent.Head
local LegLower = script.Parent.LeftLowerLeg
local LegUpper = script.Parent.LeftUpperLeg
local Foot = script.Parent.LeftFoot
local radius = math.ceil((Torso.Size.X + Limb1.Size.X + Limb2.Size.X))
local height = math.floor((Head.Size.Y + Torso.Size.Y + LegLower.Size.Y + LegUpper.Size.Y + Foot.Size.Y))
local agentCanJump = true
local final = {
["AgentRadius"] = radius,
["AgentHeight"] = height,
["AgentCanJump"] = agentCanJump
}
agentParam = final
return final
end
end
local function GeneratePath(target)
PathfindingToTarget = true
local path = PS:CreatePath(CalculateAgentParam())
path:ComputeAsync(AIRoot.Position, target.Position)
local waypoints = path:GetWaypoints()
if path.Status == Enum.PathStatus.Success then
for _, v in pairs(waypoints) do
-- WAYPOINT GENERATION
local point = Instance.new("Part")
point.Anchored = true
point.CanCollide = false
point.Parent = workspace.Waypoints
point.Size = Vector3.new(0.5, 0.5, 0.5)
point.Shape = Enum.PartType.Ball
point.Position = v.Position + Vector3.new(0, 2, 0)
point.BrickColor = BrickColor.new("Institutional white")
-- MAIN
if v.Action == Enum.PathWaypointAction.Jump then
AIHum.Jump = true
end
if RayCheck(target) then
repeat
AIHum:MoveTo(target.Position)
wait(0.1)
if target == nil then
break
elseif target.Parent == nil then
break
end
until RayCheck(target) == false or target.Parent.Humanoid.Health < 1
break
else
AIHum:MoveTo(v.Position)
local timeout = AIHum.MoveToFinished:Wait(0.1)
if not timeout then
AIHum.Jump = true
print("Path too long ")
break
end
end
end
end
PathfindingToTarget = false
end
while wait() do
local target = FindTarget()
if target and RayCheck(target) then
GeneratePath(target)
elseif target == nil then
--MoveRandomly() (DEPRECATED)
end
end