Hello there,
A while ago I created a pathfinding enemy to use in one of my games, but have been stuck on it as I have run into a problem I cannot seem to fix. The monster keeps walking into walls and getting stuck while trying to walk around. I have tried a lot of different things to try to make it work but I am still stuck on it. I originally followed this tutorial by GnomeCode (made 3 years ago), but have also tried other tutorials, creating my own and searching the devfourm for a solution, but nothing has worked so far. I am not sure whether it is a problem with the shape of my rig (as the rig resembles a hippo, not a human shape like most rigs).
Code
I have three scripts inside of the hippo (main script, animation script and jumpscarescript inside a collision box) plus another three local scripts for chase start, chase end and the jumpscare (yes, I know that I can do both the chase ones in a single script)
The main script: (the one I am having the problem with)
local hippo = script.Parent
local humanoid = hippo.Humanoid
--local jumpscare = game.ReplicatedStorage:FindFirstChild("HippoJumpscare")
local chase = game.ReplicatedStorage:FindFirstChild("Chase")
local chaseEnd = game.ReplicatedStorage:FindFirstChild("ChaseEnd")
hippo.HumanoidRootPart:SetNetworkOwner(nil)
local function canSeeTarget(target)
local origin = hippo.HumanoidRootPart.Position
local direction = (target.HumanoidRootPart.Position - hippo.HumanoidRootPart.Position).unit * 40
local ray = Ray.new(origin, direction)
local hit, pos = workspace:FindPartOnRay(ray, hippo)
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 = math.huge
local nearestTarget
for index, player in pairs(players) do
if player.Character then
local target = player.Character
local distance = (hippo.HumanoidRootPart.Position - target:WaitForChild("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"] = 9.5,
["AgentRadius"] = 4,
["AgentCanJump"] = false
}
local path = PathfindingService:CreatePath(pathParams)
path:ComputeAsync(hippo.HumanoidRootPart.Position, destination.Position)
return path
end
local function attack(target)
local distance = (hippo.HumanoidRootPart.Position - target.HumanoidRootPart.Position).Magnitude
--humanoid:MoveTo(target.HumanoidRootPart.Position)
local targetPos = target.HumanoidRootPart
local path = getPath(targetPos)
humanoid:MoveTo(targetPos.Position)
local player = game.Players:GetPlayerFromCharacter(target)
chase:FireClient(player)
print("ahh scary chase")
--local attackAnim = humanoid:LoadAnimation(script.Attack)
--attackAnim:Play()
--wait(0.5)
--target.Humanoid.Health = 0
--local player = game.Players:GetPlayerFromCharacter(target)
--jumpscare:FireClient(player)
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
humanoid.WalkSpeed = 17
attack(target)
break
else
chaseEnd:FireAllClients()
humanoid.WalkSpeed = 16
humanoid:MoveTo(waypoint.Position)
humanoid.MoveToFinished:Wait()
end
end
else
humanoid:MoveTo(destination.Position - (hippo.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
Photos & Videos of the problem
The hippo attempting to walk through a solid wall with a small door it it, although it cannot.
I have tidied up my code and made some changes, but the problem is still happening…
local hippo = script.Parent
local humanoid = hippo.Humanoid
--local jumpscare = game.ReplicatedStorage:FindFirstChild("HippoJumpscare")
local chase = game.ReplicatedStorage:FindFirstChild("Chase")
local chaseEnd = game.ReplicatedStorage:FindFirstChild("ChaseEnd")
hippo.HumanoidRootPart:SetNetworkOwner(nil)
local function canSeeTarget(target)
local origin = hippo.HumanoidRootPart.Position
local direction = (target.HumanoidRootPart.Position - hippo.HumanoidRootPart.Position).unit * 40
local ray = Ray.new(origin, direction)
local hit, pos = workspace:FindPartOnRay(ray, hippo)
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 = math.huge
local nearestTarget
for index, player in pairs(players) do
if player.Character then
local target = player.Character
local distance = (hippo.HumanoidRootPart.Position - target:WaitForChild("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"] = false
}
local path = PathfindingService:CreatePath(pathParams)
path:ComputeAsync(hippo.HumanoidRootPart.Position, destination)
return path
end
local function attack(target)
local distance = (hippo.HumanoidRootPart.Position - target.HumanoidRootPart.Position).Magnitude
--humanoid:MoveTo(target.HumanoidRootPart.Position)
local targetPos = target.HumanoidRootPart.Position
local path = getPath(targetPos)
humanoid:MoveTo(targetPos.Position)
local player = game.Players:GetPlayerFromCharacter(target)
chase:FireClient(player)
print("ahh scary chase")
--local attackAnim = humanoid:LoadAnimation(script.Attack)
--attackAnim:Play()
--wait(0.5)
--target.Humanoid.Health = 0
--local player = game.Players:GetPlayerFromCharacter(target)
--jumpscare:FireClient(player)
end
local function walkTo(destinationPos)
local path = getPath(destinationPos)
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
humanoid.WalkSpeed = 17
attack(target)
break
else
chaseEnd:FireAllClients()
humanoid.WalkSpeed = 16
humanoid:MoveTo(waypoint.Position)
humanoid.MoveToFinished:Wait()
end
end
else
humanoid:MoveTo(destinationPos - (hippo.HumanoidRootPart.CFrame.LookVector * 10))
end
end
function patrol()
local waypoints = workspace.Waypoints:GetChildren()
local randomNum = math.random(1, #waypoints)
walkTo(waypoints[randomNum].Position)
print(waypoints[randomNum].Position)
end
while wait(0.25) do
patrol()
end
I changed the patrol function to use the random waypoint’s position instead of the part object.
I also changed it to use pathfinding when chasing the player. But the issue still happens even if there are no players in the game.
At this point im just going to abandon this project because I cant fix it, even though its probably something really obvious.
local Agents={WaypointSpacing=(5),
AgentRadius=(4),AgentHeight=(15),
AgentCanJump=(false),AgentCanClimb=(false),
Costs={Metal=math.huge,Basalt=math.huge}}
whatever the wall is made of and they will avoid that.
I’ve looked through the roblox docs for pathfinding/ character pathfinding and a lot of tutorials through the last 2 months and I still have no idea why it is not working. I think it might just be a better idea to stick to a rig that better resembles the default roblox character as that is what it is made for.
From looking at your Hippo and arena, it looks like you should have an AgentHeight of about 9, and AgentRadius of around 3 to 4. The radius that matters, for a character that only walks forward, is half their width, plus a little bit of padding. If you had narrow pathways with tight corners, you might need the radius to be as long as half the length of the hippo, but that’s still only like 7.5.
That said, the hippo is likely to still sometimes get stuck because of how thin you made the walls, and because the hippo’s collision part is a rectangular block. Normally, you want your collision bodies to be smooth, like a pill capsule. The best for the hippo would be a Ball part at the front and rear with a cylinder connecting them to make a capsule shape. And DON’T union the parts, primitive Ball and Cylinder parts are smooth, and as soon as you Union them they become faceted meshes that can once again get stuck on things.
Ok,
I fixed everything now (I think)
The 2 problems were:
-The hippo’s radius and height were the wrong way around
-It could not calculate a path because the radius was too big
and ofcource it was some easy thing I missed
Thanks for the help!
Edit: oh… it still walks into walls some times with a radius of 7.5
Having a agent radius of 8 works, but the pathfinding hitbox looks like this now:
The problem with this is that it will not walk through smaller spaces under 8 studs that it should be able to.