Hello! I’m Making A Pathfinding AI For My Horror Game (The AI Is Similar To PIGGY) And The Animation Stutters When The Monster Is Moving, When I Remove “Humanoid.MoveToFinished:Wait()” The Animation Works Perfectly, But The AI Breaks, What Do I Do?
The AI With “Humanoid.MoveToFinished:Wait()” :
The AI Without “Humanoid.MoveToFinished:Wait()” :
AI Script :
local VDI = script.Parent
local Humanoid = VDI.Humanoid
local PathFindingService = game:GetService("PathfindingService")
VDI.PrimaryPart:SetNetworkOwner(nil)
local function CanSeeTarget(Target)
local origin = VDI.HumanoidRootPart.Position
local direction = (Target.HumanoidRootPart.Position - VDI.HumanoidRootPart.Position).unit * 40
local ray = Ray.new(origin, direction)
local hit, pos = workspace:FindPartOnRay(ray, VDI)
if hit then
if hit:IsDescendantOf(Target) then
return true
end
else
return false
end
end
local function FindTarget()
local Players = game.Players:GetPlayers()
local MaxDistance = 75
local NearestTarget = nil
for index, player in pairs(Players) do
if player.Character then
local Target = player.Character
local Distance = (VDI.HumanoidRootPart.Position - Target.HumanoidRootPart.Position).Magnitude
if Distance < MaxDistance and CanSeeTarget(Target) then
NearestTarget = Target
MaxDistance = Distance
end
end
end
return NearestTarget
end
local function GetPath(destination)
local PathParms = {
["AgentHeight"] = 10,
["AgentRadius"] = 8,
["AgentCanJump"] = false
}
local Path = PathFindingService:CreatePath(PathParms)
Path:ComputeAsync(VDI.HumanoidRootPart.Position, destination.Position)
return Path
end
local function Attack(Target)
local Distance = (VDI.HumanoidRootPart.Position - Target.HumanoidRootPart.Position).Magnitude
if Distance > 8 then
Humanoid:MoveTo(Target.HumanoidRootPart.Position)
Humanoid.WalkSpeed = 32
else
Target.Humanoid.Health = 0
end
end
local function WalkTo(destination)
local Path = GetPath(destination)
if Path.Status == Enum.PathStatus.Success then
for index, waypoint in pairs(Path:GetWaypoints()) do
local Target = FindTarget()
if Target and Target.Humanoid.Health > 0 then
Attack(Target)
break
else
Humanoid.WalkSpeed = 16
Humanoid:MoveTo(waypoint.Position)
Humanoid.MoveToFinished:Wait() --This Is The Part That Breaks The Animation
end
end
else
Humanoid:MoveTo(destination.Position - (VDI.HumanoidRootPart.CFrame.LookVector * 10))
end
end
local function Patrol()
local WayPoints = workspace.WayPoints:GetChildren()
local RandomNum = math.random(1, #WayPoints)
WalkTo(WayPoints[RandomNum])
end
while task.wait() do
Patrol()
end
Everything I Found Did Not Help Me, So Thats Why I’m Making This Post.
4 Likes
Are you running the script on the server or the client? I have issues with running path finding and human humanoid move when on server. I’d recommend running on client
Im Running It On The Server, Also How Will Running It On Client Do Anything? Wont That Just Ruin Break it? Cuz It WIll Kill The Player On The Client Side? My Brain Is Too Smol For This.
1 Like
Sometimes Humanoid:WalkToFinished()
is a bit buggy and unreliable, so I tend to not use it.
I would recommend replacing Humanoid:WalkToFinished()
with something like this:
local timeout = 0
local maxTimeout = 50 --How many times it checks before deciding to proceed anyways
local nextPointDistance = 2 --How far VDI has to be before going to next point
repeat
task.wait(0.1) --You can change this to whatever to increase or decrease checking speed
timeout += 1
until timeout >= maxTimeout or (VDI.PrimaryPart.Position - Vector3.new(0, [VDI height from ground], 0) - waypoint.Position).Magnitude <= nextPointDistance
If that doesn’t work out, it may be something in the script that controls the animations of VDI
3 Likes
Do I Put This In The Place The WALKTOFINISHED Was?
Sorry, I meant where you put Humanoid:MoveToFinished:Wait()
2 Likes
oh my god… IT WORKS! THANK YOU SO MUCHHH!!!
2 Likes
Sometimes the AI Doesnt even pathfind (runs into walls, doesnt even touch the waypoint)… is that a bug with the AI or the thing i used to replace MoveToFinished?
1 Like
That might be an issue with the code I gave you, I didn’t test it and purely wrote it from memory.
It may still be pathfinding, but it acts weird due to one of the two conditions being met too early. Try adjusting the variable nextPointDistance
and checking timeout
and the distance between VDI
and the waypoint.Position
.
2 Likes
ye i am stumped, this is what happens, and this in a horror game might be a bad idea, dont ya think?
the literal only fix i have is just making the entire VDI CanCollide OFF, but it still looks… weird.
Try visualizing the waypoints and see if it attempts to target the waypoints prematurely. That’s what I am assuming is going wrong.
You can make a part that indicates the current waypoint it is targeting or use lightguides (File → Studio Settings → Studio → Visualization → Navigation Mesh)
Edit: It was navigation mesh, make sure to enable that to see the waypoint visualization
2 Likes
wha- okay what the heck is going on?
it tries to go the correct way but just turns 45 degrees? what is happenin?
Yeah, I think it is trying to go to the other waypoints too early…
Can you send your current script? It’s weird how it works the first time but it doesn’t after…
nice. id still recommened checking to see if moved to was reached with a connection. This is similar to what i use for my bots
ocal RunService = game:GetService("RunService")
-- do this once in your script
local moveToReached = nil
local moveToCon = Humanoid.MoveToFinished:Connect(function(reached)
moveToReached = reached
end)
local timeout = 1
local function WalkTo(destination)
local Path = GetPath(destination)
if Path.Status == Enum.PathStatus.Success then
local waypoints = Path:GetWaypoints()
local index = 1
while index < #waypoints do
local Target = FindTarget()
if Target and Target.Humanoid.Health > 0 then
Attack(Target)
break
else
Humanoid.WalkSpeed = 16
moveToReached = nil
Humanoid:MoveTo(waypoint.Position)
local timeElapsed = 0
while true do
if moveToReached then
break
end
if timeElapsed >= timeout then
break
end
timeElapsed += RunService.Heartbeat:Wait()
end
if moveToReached then
index += 1
else
-- break and recompute path or retry
end
end
end
else
Humanoid:MoveTo(destination.Position - (VDI.HumanoidRootPart.CFrame.LookVector * 10))
end
end
Sure! Heres the script :
local VDI = script.Parent
local Humanoid = VDI.Humanoid
local PathFindingService = game:GetService("PathfindingService")
VDI.PrimaryPart:SetNetworkOwner(nil)
local timeout = 0
local maxTimeout = 100 --How many times it checks before deciding to proceed anyways
local nextPointDistance = 2 --How far VDI has to be before going to next point
local function CanSeeTarget(Target)
local origin = VDI.HumanoidRootPart.Position
local direction = (Target.HumanoidRootPart.Position - VDI.HumanoidRootPart.Position).unit * 40
local ray = Ray.new(origin, direction)
local hit, pos = workspace:FindPartOnRay(ray, VDI)
if hit then
if hit:IsDescendantOf(Target) then
return true
end
else
return false
end
end
local function FindTarget()
local Players = game.Players:GetPlayers()
local MaxDistance = 75
local NearestTarget = nil
for index, player in pairs(Players) do
if player.Character then
local Target = player.Character
local Distance = (VDI.HumanoidRootPart.Position - Target.HumanoidRootPart.Position).Magnitude
if Distance < MaxDistance and CanSeeTarget(Target) then
NearestTarget = Target
MaxDistance = Distance
end
end
end
return NearestTarget
end
local function GetPath(destination)
local PathParms = {
["AgentHeight"] = 8,
["AgentRadius"] = 6,
["AgentCanJump"] = false
}
local Path = PathFindingService:CreatePath(PathParms)
Path:ComputeAsync(VDI.HumanoidRootPart.Position, destination.Position)
return Path
end
local function Attack(Target)
local Distance = (VDI.HumanoidRootPart.Position - Target.HumanoidRootPart.Position).Magnitude
if Distance > 8 then
Humanoid:MoveTo(Target.HumanoidRootPart.Position)
Humanoid.WalkSpeed = 32
else
Target.Humanoid.Health = 0
end
end
local function WalkTo(destination)
local Path = GetPath(destination)
if Path.Status == Enum.PathStatus.Success then
for index, waypoint in pairs(Path:GetWaypoints()) do
local Target = FindTarget()
if Target and Target.Humanoid.Health > 0 then
Attack(Target)
break
else
Humanoid.WalkSpeed = 16
Humanoid:MoveTo(waypoint.Position)
repeat
task.wait(0.05) --You can change this to whatever to increase or decrease checking speed
timeout += 1
until timeout >= maxTimeout or (VDI.PrimaryPart.Position - Vector3.new(0, 5, 0) - waypoint.Position).Magnitude <= nextPointDistance
end
end
else
Humanoid:MoveTo(destination.Position - (VDI.HumanoidRootPart.CFrame.LookVector * 10))
end
end
local function Patrol()
local WayPoints = workspace.WayPoints:GetChildren()
local RandomNum = math.random(1, #WayPoints)
WalkTo(WayPoints[RandomNum])
end
while task.wait(0.5) do
Patrol()
end
Ok I see the problem now, you aren’t resetting timeout
When it gets out of the until
loop, reset timeout
to 0
1 Like
Yes, timeout
needs to be reset every time for it to work.
1 Like
Nice, it works. There is one more thing that is very buggy but its not really for this topic.
1 Like
Is it still related to the movement/animations? We can move our conversation into messages.
Either way, glad I could help you figure out some of the issues.