Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
0

How would I go about making an AI that chases and kills you around obstacles?

Asked by 4 years ago

I am making a game that is very similar to [The Rake] (https://www.roblox.com/games/2413927524/THE-RAKE-Classic-Edition-v1-1-1c)

You're put in a map that has buildings and other obstacles littered around it. There is a monster that is supposed to chase you throughout this map. I have used basic things like MoveTo(), but obviously that doesn't work very well because the monster can't get around obstacles. So I tried different ways to do this using pathfinding, but I still can't get it just right.

This is my code as of right now. If it looks cluttered it's because I've constantly been changing it to try to fit my needs.

local runSpeed = 28
local pathService = game:GetService("PathfindingService")
local humanoid = script.Parent.Humanoid

humanoid.WalkSpeed = runSpeed

function findNearestTorso(pos)
    local list = game.Workspace:children()
    local torso = nil
    local dist = 800
    local temp = nil
    local human = nil
    local temp2 = nil
    for x = 1, #list do
        temp2 = list[x]
        if (temp2.className == "Model") and (temp2 ~= script.Parent) then
            temp = temp2:findFirstChild("HumanoidRootPart")
            human = temp2:findFirstChild("Humanoid")
            if (temp ~= nil) and (human ~= nil) and (human.Health > 0) then
                if (temp.Position - pos).magnitude < dist then
                    torso = temp
                    dist = (temp.Position - pos).magnitude
                end
            end
        end
    end
    return torso
end

local path

while true do
    wait(0.5)
    local target = findNearestTorso(script.Parent.HumanoidRootPart.Position)
    if target ~= nil then
        path = pathService:CreatePath()
        path:ComputeAsync(script.Parent.HumanoidRootPart.Position, target.Position)

        local waypoints = path:GetWaypoints()

        if path.Status == Enum.PathStatus.Success then
            for i,v in pairs(waypoints) do
                local part = Instance.new("Part", workspace)
                part.Anchored = true
                part.CanCollide = false
                part.Material = Enum.Material.Neon
                part.Position = v.Position
                part.Size = Vector3.new(0.6,0.6,0.6)
                part.Shape = "Ball"

                humanoid:MoveTo(v.Position)

                if v.Action == Enum.PathWaypointAction.Jump then
                    humanoid.Jump = true
                end 
            end
        end
    end
end

Like I said it's pretty cluttered. What this does right now is it makes a path over and over towards the closest player. But instead of following this path correctly, the monster goes straight to the waypoint at the end of the path. Also, the monster is supposed to jump over obstacles in the path, but fails to do so. I've been at this all day and haven't been able to come to a solution. Keep in mind most of this is bits and pieces from videos, forums, the wiki etc. I am not an experienced scripter so most of this is pretty difficult for me.

Please, if you can, explain and show me how to fix this and how to do it efficiently, if possible. Thanks.

0
ALSO MAKE A VALUE DJH_100 28 — 4y
0
there are alot of pathfinding models, i would just use the scripts in those dominicjj54321 8 — 4y
0
I did try that but none of them really worked well BaconMan1455 4 — 4y

2 answers

Log in to vote
0
Answered by
DJH_100 28
4 years ago
Edited 4 years ago

if you want path finding, do this and put a value and name it Target

debugMode = false
targetNPCs = false

--

h = script.Parent.Parent:WaitForChild("Humanoid")
pathService = game:GetService("PathfindingService")
targetV = script.Parent:WaitForChild("Target")

function closestTargetAndPath()
    local humanoids = {}
    if targetNPCs then
        local function recurse(o)
            for _,obj in pairs(o:GetChildren()) do
                if obj:IsA("Model") then
                    if obj:findFirstChild("Humanoid") and obj:findFirstChild("Torso") and obj.Humanoid ~= h and obj.Humanoid.Health > 0 and not obj:findFirstChild("ForceField") then
                        table.insert(humanoids,obj.Humanoid)
                    end
                end
                recurse(obj)
            end
        end
        recurse(workspace)
    else
        for _,v in pairs(game.Players:GetPlayers()) do
            if v.Character and v.Character:findFirstChild("HumanoidRootPart") and v.Character:findFirstChild("Humanoid") and v.Character.Humanoid.Health > 0 and not v:findFirstChild("ForceField") then
                table.insert(humanoids,v.Character.Humanoid)
            end
        end
    end
    local closest,path,dist
    for _,humanoid in pairs(humanoids) do
        local myPath = pathService:ComputeRawPathAsync(h.Torso.Position,humanoid.Torso.Position,500)
        if myPath.Status ~= Enum.PathStatus.FailFinishNotEmpty then
            -- Now that we have a successful path, we need to figure out how far we need to actually travel to reach this point.
            local myDist = 0
            local previous = h.Torso.Position
            for _,point in pairs(myPath:GetPointCoordinates()) do
                myDist = myDist + (point-previous).magnitude
                previous = point
            end
            if not dist or myDist < dist then -- if true, this is the closest path so far.
                closest = humanoid
                path = myPath
                dist = myDist
            end
        end
    end
    return closest,path
end

function goToPos(loc)
    h:MoveTo(loc)
    local distance = (loc-h.Torso.Position).magnitude
    local start = tick()
    while distance > 4 do
        if tick()-start > distance/h.WalkSpeed then -- Something may have gone wrong. Just break.
            break
        end
        distance = (loc-h.Torso.Position).magnitude
        wait()
    end
end

while wait() do
    local target,path = closestTargetAndPath()
    local didBreak = false
    local targetStart
    if target and h.Torso then
        targetV.Value = target
        targetStart = target.Torso.Position
        roaming = false
        local previous = h.Torso.Position
        local points = path:GetPointCoordinates()
        local s = #points > 1 and 2 or 1
        for i = s,#points do
            local point = points[i]
            if didBreak then 
                break
            end
            if target and target.Torso and target.Health > 0 then
                if (target.Torso.Position-targetStart).magnitude < 1.5 then
                    local pos = previous:lerp(point,.5)
                    local moveDir = ((pos - h.Torso.Position).unit * 2)
                    goToPos(previous:lerp(point,.5))
                    previous = point
                end
            else
                didBreak = true
                break
            end
        end
    else
        targetV.Value = nil
    end
    if not didBreak and targetStart then
        goToPos(targetStart)
    end
end
0
I'm pretty happy with the final product. The only thing that seems to still not be working is when the monster gets close to you, it kind of glitches out and can't touch you while your walking. If you could help me out with that problem then it'll be perfect! Thanks a ton! BaconMan1455 4 — 4y
Ad
Log in to vote
0
Answered by 3 years ago
Edited 3 years ago

i have fixed your code it may be a bit laggy

local runSpeed = 28
local pathService = game:GetService("PathfindingService")
local humanoid = script.Parent.Humanoid
humanoid.Parent.PrimaryPart:SetNetworkOwner(nil)

humanoid.WalkSpeed = runSpeed

function findNearestTorso(pos)
    local list = game.Workspace:children()
    local torso = nil
    local dist = 800
    local temp = nil
    local human = nil
    local temp2 = nil
    for x = 1, #list do
        temp2 = list[x]
        if (temp2.className == "Model") and (temp2 ~= script.Parent) then
            temp = temp2:findFirstChild("HumanoidRootPart")
            human = temp2:findFirstChild("Humanoid")
            if (temp ~= nil) and (human ~= nil) and (human.Health > 0) then
                if (temp.Position - pos).magnitude < dist then
                    torso = temp
                    dist = (temp.Position - pos).magnitude
                end
            end
        end
    end
    return torso
end

local path

while true do
    wait(0.5)
    local target = findNearestTorso(script.Parent.HumanoidRootPart.Position)
    if target ~= nil then
        path = pathService:CreatePath()
        path:ComputeAsync(script.Parent.HumanoidRootPart.Position, target.Position)

        local waypoints = path:GetWaypoints()

        if path.Status == Enum.PathStatus.Success then
            for i,v in pairs(waypoints) do
                local part = Instance.new("Part", workspace)
                part.Anchored = true
                part.CanCollide = false
                part.Material = Enum.Material.Neon
                part.Position = v.Position
                part.Size = Vector3.new(0.6,0.6,0.6)
                part.Shape = "Ball"



                if v.Action == Enum.PathWaypointAction.Jump then
                    humanoid.Jump = true
                end 
                humanoid:MoveTo(v.Position)
                humanoid.MoveToFinished:Wait()
            end
        end
    end
end

hope you like it

Answer this question