AI unable to catch up to player

This is actually a pretty good solution, but it is still vulnerable to exploiters.

2 Likes

I’ll just do some testing on my own later today and see if I can find one of my past projects. If I do I’ll let you know.

2 Likes

Hey, I’m having the same issue with the same module. I’ll put this conversation at watching because I REALLY need solutions to this.

1 Like

Just so you know, I’m working on this as I speak. Sorry it took me a few days to get to it, I had to deal with other stuff in life. Nevertheless, this problem is sort of fun. It’s a break from the usual problems I deal with. Anyways, I have done some initial testing, and I should have a solution later tonight. It turns out I was on the right track earlier when I provided the getPathfindPoint function, but I took a wrong turn, as well as I didn’t account for the actual latency between the client and server.

I’ll post in an hour or two with the actual solution. Just know that with it, it will definitely require you to centralize your system. However, it can also be done with a single script in a character for demonstration purposes.

EDIT: Never mind, it’s going to be until tomorrow until I complete this. I decided to go the perfectionist route and create a new module that has functionality above what is required to make this work. Oh well.

1 Like

I’m having this issue as well. I’m beginning to think this is an engine bug…

1 Like

It’s not an engine bug, It’s caused by latency between the client and the server. The problem doesn’t show up in studio unless you go to the network settings in the studio settings tab and set the incoming replication lag to something above 0.

Also, just updating to let everyone else know I’m still working on this. The problem turned out to be a bit more complex, but I’m on the right path now and can get the NPC within 2-3 studs of the player. I should have it completed either today or tomorrow.

EDIT: I am now able to predict the position of the player rather accurately whenever the player walks in a straight line. However, I am dealing with an issue whenever they are turning. So now I’m modeling the player walk path along a curve, something I’ve never done before. This may take a few more days.

1 Like

Alright, I’ve completed my testing. I’ll update this reply later with the finished product. As for now, all I can say is this. I’ve found a method for predicting the future position of the player, but it only works with low latency/ping. If the player has a relatively high ping (around/above 100) there is no reliable way to predict their current position. The latency is just too great. With that said, it should still work with those of a lower ping.

1 Like

This solution isn’t bad, just beware that giving network ownership of the character models to the player will allow them to do anything physics related to their body and it will replicate.
E.g WalkSpeed and JumpPower.

2 Likes

Now I’m no like genius I’m just trying to put in an effort or attempt to help
But really the latency happening is the functions you have, although yes run and execution time of the functions still happen very fast
I didn’t make very hard changes, just some I feel like would improve

local RS = game:GetService("ReplicatedStorage")
local SS = game:GetService("ServerStorage")
local SP = require(SS:WaitForChild("SimplePath"))

local sprinter = script.Parent
local hum = sprinter:WaitForChild("Humanoid")
local HRP = sprinter:WaitForChild("HumanoidRootPart")

local path = SP.new(sprinter)
path.Visualize = true

local names = {}
for _, name in pairs(RS:WaitForChild("Enemies"):GetChildren()) do
	table.insert(names, name.Name)
end

sprinter.PrimaryPart:SetNetworkOwner(nil)

local Target
local Blocked = true
local Distance

function findTarget()
	local aggro = 200
	local ThisTarget = nil
	local ThisBlock = true
	for _, character in pairs(workspace:GetChildren()) do
		local human = character:FindFirstChild("Humanoid")
		local RP = character:FindFirstChild("HumanoidRootPart")
		if human and RP and human.Health > 0 and not table.find(names,RP.Parent.Name) then
            local dist = (RP.Position - HRP.Position).Magnitude
			if dist < aggro then
				aggro = dist
				ThisTarget = RP
				local rayInfo = RaycastParams.new()
				rayInfo.FilterType = Enum.RaycastFilterType.Blacklist
				rayInfo.FilterDescendantsInstances = sprinter:GetChildren()
				local hit = workspace:Raycast(HRP.Position, (RP.Position - HRP.Position).Unit * 200, rayInfo)
				if hit.Instance == RP then
					ThisBlock = false
				end
			end
		end
	end
	Target = ThisTarget
    Distance = (ThisTarget ~= nil and aggro) or nil
    Blocked = (ThisTarget ~= nil and ThisBlock) or nil
end

function getPathfindingPosition(agent, target)
	local agentPos = agent:GetPivot().Position
	local targetPos = target:GetPivot().Position
	
	local direction = (agentPos - targetPos)
	local distance = direction.Magnitude
	
	if distance < 5 then
		local result = workspace:Raycast(targetPos, direction)
		return if result then result.Position else (targetPos + direction)
	elseif distance < 10 then
		local humanoid = target.Parent.Humanoid
		direction = (humanoid.MoveDirection*humanoid.WalkSpeed)
		
		local result = workspace:Raycast(targetPos, direction)
		return if result then result.Position else (targetPos + direction)
	else
		return targetPos
	end
end

game:GetService("RunService").Heartbeat:Connect(function()
    coroutine.resume(coroutine.create(function()
        findTarget()
    end))
	if Target then
		if not Blocked then
			print("not blocked")
			hum:MoveTo(getPathfindingPosition(sprinter, target), workspace.Terrain)
		elseif Blocked then
			path:Run(getPathfindingPosition(sprinter, target))
		end
	end
end)

You could give this try, obviously keep the code you have currently, as this is only just trial and error at this point and having older versions could lead to a solution

I also recommend maybe
when it does hum:MoveTo()
to just take the Target and do

local cf = Target.CFrame*CFrame.new(0,0,-3)
hum:MoveTo(cf.Position)
1 Like

Just a heads up, I’m still experiencing issues with this. I’ve been keeping an eye on the thread for the past few weeks but haven’t posted because I’ve been out of town. I’m aware @BuilderBob25620 is working on something but if anyone has any more suggestions please let me know. So far, everyone seems to be more or less in agreement that it’s a latency problem.

2 Likes

It 100% is a latency problem. Without a doubt.

1 Like

Oh, my bad! I had completely forgotten about this! Anyways, like I said earlier, I managed to get it working with lower latencies, but for players with a higher latency you should probably just hand the pathfinding off to their client. Despite the risk of this method due to exploiters, there’s no other way that I know of for high-latency players. Anyways, I’ll clean my code up today and have it ready for presentation by tomorrow.

1 Like

UPDATE: Truly sorry I won’t be able to present this today. I broke my collar bone earlier today and as a result, all projects of mine, including this one, have been put on hold until I can type without pecking the keyboard. Again, truly sorry. I’ll have this as my first priority once I am healed enough to not do damage. I still had a few things I needed to get cleaned up, but if you want me to just post what
I have now and try and try to get it working yourself then just say so and I can.

2 Likes

That really sucks, hope you get better soon. Take as much time as you need; I’d rather you post it when you feel it’s complete so that I don’t have to spend time trying to figure out the incomplete parts when you already have them figured out but just can’t implement them because of the injury.

In the meantime, I’ll try to find other parts of the game that I can work on that don’t rely on the success of the pathfinding.

2 Likes

Oh my gosh, I’m having the exact same issue! I’ve spent the last 8 hours trying to fix it and now my script is real messed up… I hope you can find an answer to it because i do not want to make my AI slower than the player (no point of a sprint system otherwise)

Please @ me if you figure out a solution because I’m stumped at the moment too

Also hope you get better soon @BuilderBob25620!

2 Likes

I have surgery tomorrow, so I should be able to finish this sometime next week, after I get caught up on homework.

The solution is all about monitoring the players latency and assembly velocity and then adjusting from there. I actually became stumped at one point when trying to get the prediction for the characters estimated position, but I recently found the solution for that from another project I was working on.

2 Likes

Don’t stress yourself dude, I’m in no rush, and I might be ok with a bit of lag now that I’m adding the jumpscare code. So it might not matter that much, at least for me.

Also you sound like an absolute genius in coding and a great person!

Hope your surgery goes well, and that you’re back in good health soon :yum:

2 Likes

Don’t worry. I’m not so much stressed as I am engrossed. Also, I don’t think I worded the bottom paragraph correctly. What I meant to say was it will help me estimate their position for greater latencies.

2 Likes

This isn’t a client server latency issue. It happens to ai as well I made a helper NPC to kill ai zombies and the same issue occurs still.

1 Like

I don’t have too much time and I’m away from my computer so I can’t test it, but isn’t there a delay with pathfinding? I’m pretty sure that computing a path yields the thread until a path is returned. I’m unsure how long that takes (I usually write my own pathfinding scripts) but that could be at least one source of delay. Might be too fast to notice though.

Try making it so it goes directly towards the player if you’re within a certain range of them to see if that fixes it.

Server-based entities will still have to deal with server to client latency of course, but this might be able to reduce the overall latency maybe.