My code just isn't working specifically on consoles, but logically has no reason as to why

So, in my game I have NPCs. These NPCs work in literally all other devices, but the 2 people we’ve had play on a PS5 have reported the exact same issue, the NPCs just get stuck.

Here are the 2 scripts I believe to be culprits but also not because they work on literally all other devices.

This is the pathfinding movement: (I’m still a noob with pathfinding)

local function followPath(path: Path, humanoid: Humanoid, root: BasePart): boolean
	if not path or path.Status == Enum.PathStatus.NoPath then return false end

	local blocked = false
	local conn, conn2
	conn = path.Blocked:Connect(function() blocked = true end)
	conn2 = humanoid.MoveToFinished:Connect(function(reached)
		if not reached then
			blocked = true
		end
	end)

	local npcMove, npcGoal = 0, #path:GetWaypoints()

	for index, waypoint in ipairs(path:GetWaypoints()) do
		humanoid:MoveTo(waypoint.Position)

		local reached = false
		local startTime = os.clock()
		while os.clock() - startTime < 2 do
			if blocked then break end
			if humanoid.MoveToFinished.Wait then
				reached = humanoid.MoveToFinished:Wait()
				break
			end
			task.wait()
		end

		if not reached or blocked then
			if conn then
				conn:Disconnect()
				conn2:Disconnect()
			end
			return false
		end

		npcMove = index
	end

	if conn then
		conn:Disconnect()
		conn2:Disconnect()
	end

	return true
end

And this is my NPCs “shopping loop”

while spent < spendingLimit and maxTries > 0 do
		task.wait()
		local furnitureList = getFurnitureWithStock(storeModel, npc:GetAttribute("playerSpendingLimit") - spent)
		local validFurniture = {}

		task.desynchronize()
		for _, furniture in ipairs(furnitureList) do
			local item = furniture:GetAttribute("Item")
			local itemId = sharedF.getItemId(item, sharedF.stockList)
			local price = (sharedF.stockPrices[itemId] and sharedF.stockPrices[itemId].sell) or 0
			if not VISITED_ITEMS[furniture] and price <= spendingLimit - spent then
				table.insert(validFurniture, furniture)
			end
		end
		task.synchronize()

		local numFurniture = #validFurniture
		local totalFurniture = #furnitureList

		table.clear(furnitureList)

		if numFurniture == 0 and totalFurniture == numFurniture and not visitedAny then
			game.ReplicatedStorage:WaitForChild("events"):WaitForChild("sendServerDebug"):FireServer(`No furniture was found`)
			
			say(NPC_DIALOGUE.NothingToBuy[math.random(1, #NPC_DIALOGUE.NothingToBuy)], lastSpoke, root)
			lastSpoke = time()
			table.clear(VISITED_ITEMS)
			VISITED_ITEMS = nil
			break
			
		elseif numFurniture == 0 and totalFurniture ~= numFurniture and not visitedAny then
			game.ReplicatedStorage:WaitForChild("events"):WaitForChild("sendServerDebug"):FireServer(`NPC cannot afford items`)
			
			say(NPC_DIALOGUE.LowTrustDialogue[math.random(1, #NPC_DIALOGUE.LowTrustDialogue)], lastSpoke, root)
			lastSpoke = time()
			table.clear(VISITED_ITEMS)
			VISITED_ITEMS = nil
			break
			
		elseif numFurniture == 0 then
			game.ReplicatedStorage:WaitForChild("events"):WaitForChild("sendServerDebug"):FireServer(`No furiture remains to be visited`)
			
			table.clear(VISITED_ITEMS)
			VISITED_ITEMS = nil
			break
			
		end

		local chosen = pickFurniture(validFurniture, npc)
		if not chosen then
			game.ReplicatedStorage:WaitForChild("events"):WaitForChild("sendServerDebug"):FireServer(`Couldn't choose furniture- rng fallback`)
			chosen = validFurniture[math.random(1, numFurniture)] --// Fallback to old RNG system
		end
		
		VISITED_ITEMS[chosen] = true
		visitedAny = true

		local target = chosen:FindFirstChild("npcTarget")
		if not target then continue end

		path = computePath(path, root.Position, target.Position)
		if not path or not followPath(path, humanoid, root) then
			game.ReplicatedStorage:WaitForChild("events"):WaitForChild("sendServerDebug"):FireServer(`Path couldn't be calculated`)
			
			if #validFurniture == 1 then
				table.clear(validFurniture)
				say(NPC_DIALOGUE.CannotReach[math.random(1, #NPC_DIALOGUE.CannotReach)], lastSpoke, root)
				lastSpoke = time()
				warn("invalid furniture")
				break
			else
				table.clear(validFurniture)
				maxTries -= 1
				continue
			end
		end
		table.clear(validFurniture)

		local itemName = chosen:GetAttribute("Item")
		local itemId = sharedF.getItemId(itemName, sharedF.stockList)
		if not itemId then
			maxTries -= 1
			continue
		end

		local available = math.max(0, (chosen:GetAttribute("Amount") or 0) - (chosen:GetAttribute("npcReserved") or 0))
		if available <= 0 then
			maxTries -= 1
			continue
		end

		local price = (sharedF.stockPrices[itemId] and sharedF.stockPrices[itemId].sell) or 0
		if price <= 0 then
			maxTries -= 1
			continue
		end

		local maxAffordable = math.floor((spendingLimit - spent) / price)
		if maxAffordable <= 0 then
			say(NPC_DIALOGUE.cantAffordResponses[math.random(1, #NPC_DIALOGUE.cantAffordResponses)], lastSpoke, root)
			lastSpoke = time()
			maxTries -= 1
			continue
		end

		local desired = math.min(maxAffordable, math.random(1, 3 ^ (Players.LocalPlayer.leaderstats.Rating.Value / 1.6)), available)
		if desired <= 0 then
			maxTries -= 1
			continue
		end

		if npc.PrimaryPart and chosen.PrimaryPart then
			local lookAt = Vector3.new(chosen.PrimaryPart.Position.X, npc.PrimaryPart.Position.Y, chosen.PrimaryPart.Position.Z)
			npc:PivotTo(CFrame.lookAt(npc.PrimaryPart.Position, lookAt))
		end

		local boughtAmount = 0
		npc:SetAttribute("npcRngThreshold", rngThreshold)
		for i = 1, desired do
			grabAnim:Play()
			task.wait(math.random() * 0.4 + 0.2)

			boughtAmount += 1
			thoughtItemsBought += 1
			spent += price

			npc:SetAttribute("spentMoney", spent)
			if npc:FindFirstChild("BillboardGui") and npc.BillboardGui:FindFirstChild("TextLabel") then
				local totalSpendingLimit = npc:GetAttribute("playerSpendingLimit") or spendingLimit
				npc.BillboardGui.TextLabel.Text = `${math.max(0, totalSpendingLimit - spent)}`
			end

			local roll = math.random()
			if roll < rngThreshold then
				break
			end
			npc:SetAttribute("npcRngThreshold", (rngThreshold or 0) + (0.02/Players.LocalPlayer.leaderstats.Rating.Value))

			task.wait(math.random() * 0.3 + 0.1)
		end

		if boughtAmount > 0 then
			local success = game.ReplicatedStorage.functions.npcReserve:InvokeServer(npc, chosen, boughtAmount, itemId)
			if not success then
				thoughtItemsBought -= boughtAmount
				spent -= price
				npc:SetAttribute("spentMoney", spent)
				if npc:FindFirstChild("BillboardGui") and npc.BillboardGui:FindFirstChild("TextLabel") then
					local totalSpendingLimit = npc:GetAttribute("playerSpendingLimit") or spendingLimit
					npc.BillboardGui.TextLabel.Text = `${math.max(0, totalSpendingLimit - spent)}`
				end
				
			else
				if thoughtItemsBought > 0 then
					local hasAnyStock = false
					for _, v in storeModel.playerFurniture:GetChildren() do
						if v:GetAttribute("Item") and v:GetAttribute("Amount") > 0 then
							hasAnyStock = true
							break
						end
					end
					if not hasAnyStock then
						sharedF.Notification(`<font color="#ff2323">Your store has run out of stock!</font>`)
					end
				end
			end
		end
		task.desynchronize()
		boughtAmount = nil
		desired = nil
		chosen = nil
		maxAffordable = nil
		price = nil
		available = nil
		target = nil
		numFurniture = nil
		task.synchronize()

		maxTries -= 1
	end

I’m almost positive that either of these scripts are the problem because the code runs up to here and then gets stuck, as to why its only a problem on console, I have no idea.

I’m fully out of ideas, I’ve tried debugging it for 2 days already and I feel like I’m going insane.

And while we’re here, feel free to bash my code and tell me how I could write it better.

1 Like

I can recommend putting a bunch of print statements all around to see the exact line it’s not working.

Everything looks fine at a glance, but maybe it’s the stop wait for the animation or something with the task sync. I don’t see why anything would be console specific, but hope you can fix it.

1 Like

I don’t see anything wrong with it myself, but the only thing I could think of was the task.synchronize()and thetask.desynchronize()for the parallel.

If possible, you could remove the parallel and run a test to see the results?

1 Like

I’ve tried printing, I put them up to and within the loop itself.

The prints got up to the loop, and everything I added within the loop was if something didn’t work (like if the npc couldn’t find any furniture).

Alas, none of these were the problem, and I know for a fact it wasn’t an error or anything because the Error Report is completely empty to anything relevant to this code.

I am completely baffled.

1 Like