[SOLVED] AI always breaks when cloned

So recently I have been trying to improve my AI for my game Bacon Escape: Bacon Escape [ALPHA] - Roblox

This is probably the most stressful thing I have done, because whenever I clone the bot into the game his Pathfinding script always breaks. Whenever he moves he stutters a lot and can’t target players correctly. I did try to ChangeState(10), but it didn’t work. This only occurs when he is cloned, when he is just in workspace he works perfectly fine. Why is this the case?

Extra Note: He only breaks if he is cloned in the specific spot too, I am also using SoundRegions. His paths always fail when he is spawned too.

Code
local myHuman = script.Parent:WaitForChild("Humanoid")
local myRoot = script.Parent:WaitForChild("HumanoidRootPart")
local torso = script.Parent:WaitForChild("LowerTorso")
local pathArgs = {
	["AgentRadius"] = 2,
	["AgentHeight"] = 3
}

local hit = Instance.new("Animation")
hit.AnimationId = "rbxassetid://04751027547"
local hitAnim = myHuman:LoadAnimation(hit)
local laugh = script.Parent.Laugh
local jump = script.Parent.jump
local growl = script.Parent.StomachGrowl
local squish = script.Parent.Squish

function walkRandomly()
	local xRand = math.random(-50,50)
	local zRand = math.random(-50,50)
	local goal = myRoot.Position + Vector3.new(xRand, 0, zRand)
	
	local path = game:GetService("PathfindingService"):CreatePath(pathArgs)
	path:ComputeAsync(myRoot.Position, goal)
	local waypoints = path:GetWaypoints()
	
	if path.Status == Enum.PathStatus.Success then
		for _, waypoints in ipairs(waypoints) do
			if waypoints.Action == Enum.PathWaypointAction.Jump then
				myHuman.Jump = true
			end
			myHuman:MoveTo(waypoints.Position)
			local timeOut = myHuman.MoveToFinished:Wait(1)
			if not timeOut then
				print("Stuck")
				getUnstuck()
			end
		end
	else
		print("Path failed")
		wait(1)
		walkRandomly()
	end
end

function getUnstuck()
	myHuman:Move(Vector3.new(math.random(-1,1),0,math.random(-1,1)))
	myHuman.Jump = true
	wait(1)
end

function findDist(torso)
	return (myRoot.Position - torso.Position).Magnitude
end

function findTarget()
	local dist = 150
	local target = nil
	for i,v in ipairs(workspace:GetChildren()) do
		local human = v:FindFirstChild("Humanoid")
		local torso = v:FindFirstChild("Torso") or v:FindFirstChild("HumanoidRootPart")
		if human and torso and v.Name ~= script.Parent.Name and game.Players:GetPlayerFromCharacter(v).Team ~= game.Teams.FryCook then
			if findDist(torso) < dist and human.Health > 0 then
				target = torso
				dist = findDist(torso)
			end
		end
	end
	return target
end

function checkSight(target)
	local ray = Ray.new(myRoot.Position, (target.Position - myRoot.Position).Unit * 20)
	local hit,position = workspace:FindPartOnRayWithIgnoreList(ray,{script.Parent})
	if hit then
		if hit:IsDescendantOf(target.Parent) then
			return true
		end
	end
	return false
end

function pathToTarget(target)
	local path = game:GetService("PathfindingService"):CreatePath(pathArgs)
	path:ComputeAsync(myRoot.Position,target.Position)
	if path.Status == Enum.PathStatus.Success then
		local waypoints = path:GetWaypoints()
		for i,v in ipairs(waypoints) do
			if v.Action == Enum.PathWaypointAction.Jump then
				myHuman.Jump = true
			end
			myHuman:MoveTo(v.Position)
			spawn(function()
				wait(0.3)
				if myHuman.WalkToPoint.Y > myRoot.Position.Y then
					myHuman.Jump = true
				end
			end)
			local moveSucess = myHuman.MoveToFinished:Wait()
			if not moveSucess then
				getUnstuck()
				break
			end
			if checkSight(target) and math.abs(math.abs(myRoot.Position.Y) - math.abs(target.Position.Y)) < 3 then
				break
			end
			if (target.Position - waypoints[#waypoints].Position).Magnitude > 30 then
				break
			end
			if i % 5 == 0 then
				if findTarget() ~= target then
					break
				end
			end
		end
	else
		getUnstuck()
		print("Path failed")
	end
end

local attackCool = true

function attack(target)
	if attackCool == true then
		attackCool = false
		local rand = math.random(5)
		if rand == 1 then
			squish:Play()
		end
		myHuman.JumpPower = 25 * (math.abs(math.abs(myRoot.Position.Y) - math.abs(target.Position.Y))) / 2 + 10
		myHuman.Jump = true
		myRoot.Velocity = myRoot.CFrame.LookVector * 50 
		torsoTouched = torso.Touched:Connect(function(obj)
			if obj.Parent.Name ~= script.Parent.Name then
				local human = obj.Parent:FindFirstChild("Humanoid")
				if human then
					if human.Health > 0 then
						hitAnim:Play()
						human:TakeDamage(20)
						if human.Health < 1 then
							laugh:Play()
						end
						torsoTouched:Disconnect()
					end
				end
			end
		end)
		spawn(function() wait(1) torsoTouched:Disconnect() end)
		spawn(function() wait(0.1) myHuman.JumpPower = 50 wait(0.9) attackCool = true end)
	end
end

myHuman.Jumping:Connect(function()
	jump:Play()
end)

torso.Touched:Connect(function(obj)
	local human = obj.Parent:FindFirstChild("Humanoid")
	if human then
		if human.Health < 1 then
			myHuman.Jump = true
		end
	elseif obj.Position.Y >= myRoot.Position.Y then
		myHuman.Jump = true
	end
end)

function main()
	myHuman:ChangeState(10)
	local target = findTarget()
	if target then
		if checkSight(target) and math.abs(math.abs(myRoot.Position.Y) - math.abs(target.Position.Y)) < 3 then
			myHuman:MoveTo(target.Position)
			if findDist(target) < 15 then
				attack(target)
			end
		else
			pathToTarget(target)
		end
	else
		if math.random(5) == 1 then
			growl:Play()
		end
		walkRandomly()
	end
end

while wait() do
	if myHuman.Health < 1 then
		break
	end
	main()
end

Thanks For Reading! :slightly_smiling_face:

1 Like

Hi, can you paste your code? (30 chars)

I added it in the topic, like I said it works perfectly fine except for when he is cloned.

After some more playing around, I found out that the bot only breaks when my map loads in the game, could it be some kind of lag that breaks the script?

Edit: It also seems to just be my npc as well, other ones work fine, so it can’t be any type of lag

Edit2: I guess I am going to have to remake the bot because it just doesn’t want to work

When it is cloned, do you see any errors or warnings related to it in the output pane?

sometimes its path fails, but that doesn’t seem to be a problem. Besides that nothing else shows in the output

I dont know if this is the exact problem but i want to note that you are cloning:

local clone = script.Parent:Clone()

Which also I believe clones your script essentially over and over again. I could be wrong I only glanced at your code and havent looked through your code much further yet.

1 Like

That is for when the bot dies, it respawns

1 Like

i cant really test anything to solve your issue (replicate it), do you by any chance have a example place file showcasing the issue?

i like the game btw, looks cool

Apologies for that, I should have put up an example.

Here is a little clip:

As you can see his movement is very choppy, it isn’t like this when he isn’t cloned.

Thank you, I am trying my best to get it popular now!

Edit: I ended up getting rid of the respawn on death part of the script, because I realize that it isn’t necessary, but he still moves very choppy.

1 Like

Hey, that choppiness could actually be related to the high amount of rays you’re firing.

Do you have an idea of how I could fix it?

Edit: This is super weird, now I have been just trying out different AI’s and they also break when they are cloned into the map. What is going on?

Here is another clip of him when he is not being cloned (Not Choppy):

I found the issue! It is my pathToTarget() function. The waypoint position barely changes, meaning he isn’t necessarily moving choppy, but moving slightly each time. Does anyone know why this could be? Maybe the maps I have? And if you can please tell me how I could fix this.

Code:

function pathToTarget(target)
	local path = game:GetService("PathfindingService"):CreatePath(pathArgs)
	path:ComputeAsync(myRoot.Position,target.Position)
	if path.Status == Enum.PathStatus.Success then
		local waypoints = path:GetWaypoints()
		for i,v in ipairs(waypoints) do
			if v.Action == Enum.PathWaypointAction.Jump then
				myHuman.Jump = true
			end
			myHuman:MoveTo(v.Position)
			spawn(function()
				wait(0.3)
				if myHuman.WalkToPoint.Y > myRoot.Position.Y then
					myHuman.Jump = true
				end
			end)
			local moveSucess = myHuman.MoveToFinished:Wait()
			if not moveSucess then
				getUnstuck()
				break
			end
			if checkSight(target) and math.abs(math.abs(myRoot.Position.Y) - math.abs(target.Position.Y)) < 3 then
				break
			end
			if (target.Position - waypoints[#waypoints].Position).Magnitude > 30 then
				break
			end
			if i % 5 == 0 then
				if findTarget() ~= target then
					break
				end
			end
		end
	else
		getUnstuck()
		print("Path failed")
	end
end

So after looking on the forum some and messing with my code. I found out that using runservice is a way to bypass this error, although I feel it is kind of hacky. I also found out that this could be an engine bug as well. I will make sure to take note of this and hope that others who see this do as well, for this could be very frustrating to a lot of people.

Sources that helped:

1 Like