NPC seating problem?

I have encountered this strange problem, in relation with seats and NPCs. My game is about Barbershops, a server script spawns an NPC and right after that NPC spawns, another server script named CustomersHandler will take care of it, and will make the NPC walk inside the place and seat on an available seat. If the customer is not taken care of, they will get mad and eventually leave the place. So my problem is, there’s this client-server desync thing. On the client’s side, the NPC stands up. On the other hand, the NPC stays in the seat in the server.

Please see this video so you know what I mean: NPC seat problem - YouTube

I have no idea what is causing this. Note that, it sometimes happens that way and sometimes it does not. I thought to myself, the problem might be with the unsitting of the NPC. I tried two methods of unsitting the NPC from the seat,

-- METHOD 1
Humanoid.Jump = true

-- METHOD 2 (CURRENTLY IM USING)
Humanoid.Sit = false

But it did not make any difference, there’s still that problem. I have tried looking for solutions for this problem, and have seen similar problems that I have. But, I don’t find their solution solving my issue.
Posts such as:

Now, this code is a part of my CustomersHandler script (mainly takes care of the NPC whenever it spawns in the workspace) that looks for an available seat for the NPC and making them seat on it:

local CustomersFunction = require(game.ServerScriptService.CustomerFunctions)


local assignedSeat = CustomersFunction.FindSeat(Config.WorkspaceFolders.BarberSeats) -- CUSTOMER FINDSEAT FUNCTION (LOOKS FOR AN AVAILABLE SEAT FOR THE CUSTOMER)

if assignedSeat then -- CHECKS IF AN AVAILABLE SEAT IS FOUND

	CustomersFunction.SeatCustomer(customer, assignedSeat) -- CUSTOMER SEATCUSTOMER FUNCTION (MAKES THE CUSTOMER GO TO THE SEAT AND TAKE A SEAT
	
	NPCStatus.Value = "Seated" -- CHANGES THE NPC STATS TO SEATED

else -- THERE ARE NO AVAILABLE SEATS FOUND, THEREFORE MAKING THE NPC LEAVE

	NPCStatus.Value = "Failed" -- CHANGES THE NPC STATUS TO FAILED

	local exitPart = Config.WorkspaceFolders.CustomerSpawns:GetChildren()[math.random(#Config.WorkspaceFolders.CustomerSpawns:GetChildren())] -- CHOOSES A RANDOM EXIT PART FOR THE CUSTOMER

	CustomersFunction.Exit(customer, exitPart) -- CUSTOMER EXIT FUNCTION (MAKES THE CUSTOMER LEAVE THE PLACE)

end

game.ServerScriptService.CustomerSpawner.Disabled = false -- RE-ENABLES THE CUSTOMER SPAWNER SCRIPT (THE CUSTOMER SPAWNER SCRIPT DISABLES ITSELF AFTER SPAWNING AN NPC, THAT IS HOW IT WORKS AT THE MOMENT)

if NPCStatus.Value == "Seated" then -- IF THE NPC IS SEATED
    
    local barberSuccess = CustomerMechanism.ToggleBarberMechanism(customer, assignedSeat, Config.CustomerWaitingTime.Barber) -- TELLS WHETHER THE BARBER WAS SUCCESS OR NOT (WHETHER THE CUSTOMER WAS TAKEN CARE OF OR IGNORED)
    
    if barberSuccess then
        
        NPCStatus.Value = "Success"
    
    	CustomersFunction.ChatCustomer(customer, CustomerMessages.CustomerHaircutDoneMessages[math.random(#CustomerMessages.CustomerHaircutDoneMessages)]) -- MAKES THE CUSTOMER SAY RANDOM MESSAGES
    
    	wait(2)
    
    	humanoid.Sit = false -- UNSITS THE CUSTOMER
    
    	CustomersFunction.GoToCounter(customer, game.Workspace.CustomerWalkpoints)

    else
        
        NPCStatus.Value = "Failed"
        
    	CustomersFunction.ChatCustomer(customer, CustomerMessages.CustomerMadMessages[math.random(#CustomerMessages.CustomerMadMessages)]) -- MAKES THE CUSTOMER SAY RANDOM MESSAGES
    
    	local exitPart = Config.WorkspaceFolders.CustomerSpawns:GetChildren()[math.random(#Config.WorkspaceFolders.CustomerSpawns:GetChildren())] -- CHOOSES A RANDOM EXIT PART FOR THE CUSTOMER

		wait(2)

		humanoid.Sit = false -- UNSITS THE CUSTOMER

		CustomersFunction.Exit(customer, exitPart) -- CUSTOMER EXIT FUNCTION (MAKES THE CUSTOMER LEAVE THE PLACE)

    end

end

And, this code is from my CustomersFunction module script. These functions are the ones used in the script above:

local module = {}

function module.Exit(customer, exitPart) -- MAKES THE CUSTOMER LEAVE THE PLACE
	
	local PathService = game:GetService("PathfindingService")

	local humanoid = customer:FindFirstChild("Humanoid")

	if humanoid then -- CHECKS IF THE HUMANOID EXISTS

		local Path = PathService:CreatePath()
		Path:ComputeAsync(customer.PrimaryPart.Position, exitPart.Position) -- COMPUTES PATH TO THE EXIT PART

		if Path.Status == Enum.PathStatus.Success then -- CHECKS IF THE PATH COMPUTATION SUCCEEDS

			local Waypoints = Path:GetWaypoints() -- GATHERS THE WAYPOINTS OF THE COMPUTER PATH

			for i, point in pairs(Waypoints) do -- LOOPS THROUGH WAYPOINTS

				if point.Action == Enum.PathWaypointAction.Jump then -- MAKES THE NPC JUMP IF IT NEEDS TO

					humanoid.Jump = true

				end

				humanoid:MoveTo(point.Position)

				humanoid.MoveToFinished:Wait()

			end
			
			customer:Destroy()
			
			print("Customer left")

		end

	end
	
end


function module.GoToCounter(customer, walkpoints) -- MAKES THE CUSTOMER GO TO THE COUNTER SO THAT THEY CAN PAY FOR THEIR HAIRCUT
	
	local PathService = game:GetService("PathfindingService")

	local humanoid = customer:FindFirstChild("Humanoid")

	if humanoid then -- CHECKS IF THE HUMANOID EXISTS

		local Path = PathService:CreatePath()
		Path:ComputeAsync(customer.PrimaryPart.Position, walkpoints.Counter.Position) -- COMPUTES PATH

		if Path.Status == Enum.PathStatus.Success then -- CHECKS IF THE PATH COMPUTATION SUCCEEDS

			local Waypoints = Path:GetWaypoints() -- GATHERS THE WAYPOINTS OF THE COMPUTER PATH

			for i, point in pairs(Waypoints) do -- LOOPS THROUGH WAYPOINTS

				if point.Action == Enum.PathWaypointAction.Jump then -- MAKES THE NPC JUMP IF IT NEEDS TO

					humanoid.Jump = true

				end

				humanoid:MoveTo(point.Position)

				humanoid.MoveToFinished:Wait()

			end

		end

		print("Customer is now at counter")

	end
	
end


function module.FindSeat(seats) -- LOOKS FOR AN AVAILABLE SEAT
	
	for i, seat in pairs(seats:GetChildren()) do -- LOOPS THROUGH ALL OF THE SEATS
		
		if not seat.Seat.Occupant then -- CHECKS IF THE SEAT HAS AN OCCUPANT
			
			return seat -- RETURNS SEAT IF AVAILABLE
				
		end
	end
	
	return nil -- RETURNS NIL IF THERE IS NO SEAT AVAILABLE
	
end


function module.SeatCustomer(customer, seat) -- MAKES THE CUSTOMER SEAT ON THE AVAILABLE SEAT
	
	local PathService = game:GetService("PathfindingService")
	
	local humanoid = customer:FindFirstChild("Humanoid")
	
	if humanoid then -- CHECKS IF THE HUMANOID EXISTS
		
		local Seat = seat.Seat -- ASSIGNS THE ACTUAL SEAT TO A VARIABLE
		
		local Path = PathService:CreatePath()
		Path:ComputeAsync(customer.PrimaryPart.Position, Seat.Position) -- COMPUTES PATH
		
		if Path.Status == Enum.PathStatus.Success then -- CHECKS IF THE PATH COMPUTATION SUCCEEDS
			
			local Waypoints = Path:GetWaypoints() -- GATHERS THE WAYPOINTS OF THE COMPUTER PATH
			
			for i, point in pairs(Waypoints) do -- LOOPS THROUGH WAYPOINTS
				
				if point.Action == Enum.PathWaypointAction.Jump then -- MAKES THE NPC JUMP IF IT NEEDS TO
					
					humanoid.Jump = true
					
				end
				
				humanoid:MoveTo(point.Position)

				humanoid.MoveToFinished:Wait()
				
			end
			
		end
		
		
		Seat:Sit(humanoid) -- SITS THE CUSTOMER TO THE SEAT
		
		print("Customer is now seated")
		
	end
	
end

return module

Again, my problem is I don’t know what am I doing wrong that causes this. Correct me if I am wrong though, I don’t seem to have any problems with my script. So I would like your help in order to get around this, I need someone to tell me what’s the problem.

Thank you in advance!

IMPORTANT: I HAVE NO LOCAL SCRIPTS PRESENT IN THE GAME YET. SO THESE TWO CODES I SENT BELONGS TO A SERVER SCRIPT

While nothing is marked as solution, then it’s not solved yet.

Have you tried doing

Humanoid:ChangeState(Enum.HumanoidStateType.Jumping)

?

Great idea! I haven’t tried it yet, so I will be trying it today. I will let you know if it solves it. Thanks!

Unfortunately, it didn’t change anything. The problem is still there, similar to those other two methods.

Hm…

And you said this is client sided? I think you can try to make it serversided, if that fixes anything.

Though, what if you just made it play the animation and force it to ragdoll instead of sit? I’m thinking on some solutions right now as we speak, but I might have to just run some tests. (if you don’t mind me doing in a file version of your game)

Like I stated in my post, I have no local scripts present in the game, which would make anything client sided, so no. Everything is server sided, and that is exactly why I am having this problem and is unable to figure it out.

Is your issue similar to this one:

Yes, I have seen that topic before too, I forgot to state it. But I also couldn’t find any solution from it.

1 Like

Seems like this problem as well, try disabling the automatic on touch seating using this method:

Actually, all of the seats CanTouch property are turned off all the time. I didn’t make it so that whenever an NPC touches the seat, they automatically seat. But instead the scripts handle it, I use the Seat:Sit() function to seat the NPC after the Pathfinding finishes doing its job. So it can’t be a problem.

To fix this I just don’t even use seats. I created my own function to weld them to the bottom of the chair and change Humanoid.Sit = true. When I want them to get out of the chair I break the weld and set Humanoid.Sit = false.

Does this bug happen everytime?

Don’t know about him, but I had the same issue and for me it happened every time.

Have you tried setting the network ownership of the npc?