Pathfinding * animation

Im currently making a zombie game and I use pathfinding for my zombie, but there’s a thing, when my zombie reach each checkpoint it the path, the animation just reset, the animation didn’t just stop but it just reverse back and then continue
here’s my code

local Zombie = script.Parent
local humanoid = Zombie.Humanoid
Zombie.PrimaryPart:SetNetworkOwner(nil)
local attack1 = script.Parent.AI.attack1
local attack2 = script.Parent.AI.attack2
local damage1 = script.Parent.AI.damage1
local damage2 = script.Parent.AI.damage2
local damage3 = script.Parent.AI.damage3
local agressive1 = script.Parent.AI.agressive1
local agressive2 = script.Parent.AI.agressive2
local agressive3 = script.Parent.AI.agressive3



local function canSeeTarget(target)
	local origin = Zombie.HumanoidRootPart.Position
	local direction = (target.HumanoidRootPart.Position - Zombie.HumanoidRootPart.Position).unit * 40
	local ray = Ray.new(origin, direction)
	
	local hit, pos = workspace:FindPartOnRay(ray, Zombie)
	
	
	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 = 33
	local nearestTarget
	
	for index, player in pairs(players) do
		if player.Character then
			local target = player.Character
			local distance = (Zombie.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 PathfindingService = game:GetService("PathfindingService")
	
	local pathParams = {
		["AgentHeight"] = 15,
		["AgentRadius"] = 4,
		["AgentCanJump"] = true
	}
	
	local path = PathfindingService:CreatePath(pathParams)
	
	path:ComputeAsync(Zombie.HumanoidRootPart.Position, destination.Position)
	
	return path
end

local function attack(target)
	local distance = (Zombie.HumanoidRootPart.Position - target.HumanoidRootPart.Position).Magnitude

	if distance > 6 then
		humanoid:MoveTo(target.HumanoidRootPart.Position)
		
	else
		local attackAnim = humanoid:LoadAnimation(script.Attack)
		attackAnim:Play()
		target.Humanoid.Health = target.Humanoid.Health -11
		local random = math.random(1, 3)
		if random == 1 then
			attack1:Play()
			damage1:Play()
		elseif random == 2 then
			damage2:Play()
			attack2:Play()
		elseif random == 3 then
			damage3:Play()
		end
		humanoid.WalkSpeed = 1.5
		wait(0.3)
		humanoid.WalkSpeed = 4
	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
				print("PLAYER FOUND", target.Name)
				humanoid.WalkSpeed = 15

				attack(target)
				break
			else
				humanoid.WalkSpeed = 1
				print("Moving to ", waypoint.Position)
				humanoid:MoveTo(waypoint.Position)
				humanoid.MoveToFinished:Wait(4)
			end
		end
	else
		humanoid:MoveTo(destination.Position - (Zombie.HumanoidRootPart.CFrame.LookVector * 10))
	end
end

function patrol()
	local waypoints = workspace.waypoints:GetChildren()
	local randomNum = math.random(1, #waypoints)
	walkTo(waypoints[randomNum])
end

while wait(0.25) do
	patrol()
end
1 Like

Separate Animation Logic from Movement Logic:

  • Move the animation logic out of the walkTo function. You can have a separate function for handling the attack and animation logic.

Update Animation Logic:

  • Ensure that the animation is not resetting or being interrupted. You might want to play the animation only if it is not already playing.

Check Animation State:

  • Make sure the animation is not being reset due to the state of the humanoid. Check if the humanoid is currently in the “Running” state or any other state that might interfere with your animation.

Script:

local Zombie = script.Parent
local humanoid = Zombie.Humanoid
Zombie.PrimaryPart:SetNetworkOwner(nil)
local attack1 = script.Parent.AI.attack1
local attack2 = script.Parent.AI.attack2
local damage1 = script.Parent.AI.damage1
local damage2 = script.Parent.AI.damage2
local damage3 = script.Parent.AI.damage3
local agressive1 = script.Parent.AI.agressive1
local agressive2 = script.Parent.AI.agressive2
local agressive3 = script.Parent.AI.agressive3

local function canSeeTarget(target)
    local origin = Zombie.HumanoidRootPart.Position
    local direction = (target.HumanoidRootPart.Position - Zombie.HumanoidRootPart.Position).unit * 40
    local ray = Ray.new(origin, direction)
    
    local hit, pos = workspace:FindPartOnRay(ray, Zombie)
    
    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 = 33
    local nearestTarget
    
    for index, player in pairs(players) do
        if player.Character then
            local target = player.Character
            local distance = (Zombie.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 PathfindingService = game:GetService("PathfindingService")
    
    local pathParams = {
        ["AgentHeight"] = 15,
        ["AgentRadius"] = 4,
        ["AgentCanJump"] = true
    }
    
    local path = PathfindingService:CreatePath(pathParams)
    
    path:ComputeAsync(Zombie.HumanoidRootPart.Position, destination.Position)
    
    return path
end

local function attackAndAnimate(target)
    local distance = (Zombie.HumanoidRootPart.Position - target.HumanoidRootPart.Position).Magnitude

    if distance > 6 then
        humanoid:MoveTo(target.HumanoidRootPart.Position)
    else
        local attackAnim = humanoid:LoadAnimation(script.Attack)
        if not attackAnim.IsPlaying then
            attackAnim:Play()
            
            local random = math.random(1, 3)
            if random == 1 then
                attack1:Play()
                damage1:Play()
            elseif random == 2 then
                damage2:Play()
                attack2:Play()
            elseif random == 3 then
                damage3:Play()
            end

            humanoid.WalkSpeed = 1.5
            wait(0.3)
            humanoid.WalkSpeed = 4
        end
    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
                print("PLAYER FOUND", target.Name)
                humanoid.WalkSpeed = 15

                attackAndAnimate(target)
                break
            else
                humanoid.WalkSpeed = 1
                print("Moving to ", waypoint.Position)
                humanoid:MoveTo(waypoint.Position)
                humanoid.MoveToFinished:Wait(4)
            end
        end
    else
        humanoid:MoveTo(destination.Position - (Zombie.HumanoidRootPart.CFrame.LookVector * 10))
    end
end

function patrol()
    local waypoints = workspace.waypoints:GetChildren()
    local randomNum = math.random(1, #waypoints)
    walkTo(waypoints[randomNum])
end

while wait(0.25) do
    patrol()
end

This script separates the animation logic, checks if the animation is already playing, and addresses potential issues.

2 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.