Zombie AI [Sorry, if I am repeating points, but Review is always good anyway…]
ROBLOX PATHFINDING:
-
The Path (Waypoints) are the least important bit of Pathfinding, as one is going to only use the first 1 or 2 Waypoints, before getting a new Path;
unless one wants an AI to “patrol” some Path, before switching to a follow Player routine…
-
Pathfinding may have changed, but last I scripted it, one is going to only use every-other waypoint to allow for diagonal movement of the zombie.
-
The important bit is to check for an error after getting Path; then handling the error and getting another Path.
This code somewhat handles the two most important errors [Hacky, because I’m bad at math; Logic is my strong suit]
FailFinishNotEmpty is returned from Path, when the endpoint is unobtainable (Maybe the endpoint is inside of a Part, or there just is no Path). I just move the EndPoint closer to the AI, and try again. .
The others are when Startpoint is no good. Maybe the AI is already standing too close to a wall. I move the StartPoint to different places around the AI, and try again…
function ReturnPath(start, finish, MaxDist)
local path = pathfinding:ComputeRawPathAsync(start, finish, MaxDist)
print (path.Status)
if path.Status == Enum.PathStatus.FailFinishNotEmpty then
local dist = (finish - start).magnitude
while dist > 8 and path.Status == Enum.PathStatus.FailFinishNotEmpty do
wait()
finish = start + (finish - start)/1.5
path = pathfinding:ComputeRawPathAsync(start, finish, MaxDist)
dist = (finish - start).magnitude
local part = Instance.new("Part", Workspace)
part.FormFactor = Enum.FormFactor.Custom
part.Size = Vector3.new(4,4,4)
part.CFrame = CFrame.new(finish)
part.Shape = "Ball"
part.Anchored = true
part.CanCollide = false
part.BrickColor = BrickColor.Red()
table.insert(Showed, part)
end -- room to manuveur?
Bot.ShowPath (start, finish)
end -- finish error
if path.Status == Enum.PathStatus.FailStartNotEmpty
or path.Status == Enum.PathStatus.ClosestNoPath then
wait()
start = start + Vector3.new(0,0,4)
path = pathfinding:ComputeRawPathAsync(start, finish, MaxDist)
if path.Status == Enum.PathStatus.FailStartNotEmpty
or path.Status == Enum.PathStatus.ClosestNoPath then
start = start + Vector3.new(4,0,-4)
path = pathfinding:ComputeRawPathAsync(start, finish, MaxDist)
end
if path.Status == Enum.PathStatus.FailStartNotEmpty
or path.Status == Enum.PathStatus.ClosestNoPath then
start = start + Vector3.new(-4,0,-4)
path = pathfinding:ComputeRawPathAsync(start, finish, MaxDist)
end
if path.Status == Enum.PathStatus.FailStartNotEmpty
or path.Status == Enum.PathStatus.ClosestNoPath then
start = start + Vector3.new(-4,0,-4)
path = pathfinding:ComputeRawPathAsync(start, finish, MaxDist)
end
Hum:MoveTo(start)
wait()
end -- start error?
return path
end–Return Path
You will probably come-up with better ways to handle these errors…
Other methods work as well or better:
RAYCASTING
Wall Hugging to get out of a maze:
Just shooting one Ray in the direction of Nearest Player and checking for obstruction and then turning left continually recursively, and always checking (after, maybe after a half second or so) if one can get out of the recursion by turning right; works great;
with the disadvantage that the zombie will not take a diagonal tact, until actually reaching the wall.
This model used to do that; also fired a ray diagonally upwards to see if he could jump obstacle; fired a Ray in front and directly down to check for high cliffs or the edge of the world; checked, if a ladder was the obstacle and then just kept walking “Forward” (He will automatically climb).
*It’s important to just keep walking forward, until a “We are not getting anywhere” check (Time-out or Positionally) is True…
Speed AI by RealAi Inc. - Brains 4 Zombies - Roblox
Surprisingly; The shortest Script, which actually looks great (Zombie looks like an actual Player) and works very well at close or medium distances; is having the Nearest Torso drop “bread crumbs” continually of his Position; then having the zombie just go from one “crumb” to the next.
Importants:
- Player only drops a new crumb, after moving far enough away from the current crumb (OR: I just treated the World like a 3D checkerboard of, maybe (3 or 4, 3,3), and only dropped a new crumb, when Player moved to another square.)
EDIT: Bad Explanation: A “crumb” actually holds the co-ordinates of the next crumb. And in my Checkerboard method, the crumbs were actual anchored, invisible Parts, I think, which deleted themselves after a while, and could be treated non-sequentially: A NEW Nearest Torso (Player), or even the same Player might cross the path of the old crumbs, and replace the old info (of “Next Crumb”), with newer info. The entire exercise was just Too Fun…
-
When checking for “Are we there yet” before going to next crumb; strip the Y value from the .Magnitude check; turning the goal from a sphere, into a cylinder of infinite height.
(Almost everyday, I see a post, which says “.Magnitude is not accurate, and I can never ask if I am closer than 3 studs from the target”, That is because they are comparing the Player’s Torso to a Goal, on the on the baseplate, which is ALWAYS at least 3 studs away in height form the Torso
-
To jump; just check if the next crumb is in a higher square…
It’s important to use two or three of these methods in the same AI. If one fails; move on to the next.
Also; if zombie is very close to the Player, skip them and just go straight at him.; else zombie may take a detour and run from Player…
[I may add to this if I remember more…]
GL
P.S. If you want to learn to program, or are a really good artist; join me. I’m making the first wargame om the net, which is on an actual globe, instead of a donut-shaped (Toroid) planet… (which is the actual shape if you let the player wrap from the right of the map to the left, and from the N. Pole to S. Pole)
It’s gonna a be wic…, and has nothing to do with Pathfinding (except on a sphere of coarse)…