Humanoid.MoveToFinished:Wait() Makes The Walking Animation Break

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

image
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

Like This?

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.