NPC behave different on client and server

Ciao, I’m trying to make an NPC spawner that after they spawn it makes them follow a path. Simple right?
Well… the NPC on the client sometimes glitch out when they reach the end of the path, while on the server they make strange movements?

Scripts
The NPC spawner it’s a server script:

--Servizi
local Generale = require(game.ReplicatedStorage.Codici.Generale)

--Costanti
local Tycoon = script.Parent.Parent
local Cartella = Tycoon.Clienti
local ClienteModello = game.ReplicatedStorage.Modelli.Cliente

--Funzione per creare il cliente
function Cliente(Posto)
	--Variabili
	local Clone = ClienteModello:Clone()
	local Humanoid = Clone:WaitForChild("Humanoid")
	local HumanoidRootPart = Clone:WaitForChild("HumanoidRootPart")
	
	--Sistema
	Clone.Name = "Cliente"..Posto.Name
	
	--Metti il cliente come figlio del posto
	Posto.Cliente.Value = Clone
	Clone.Parent = Cartella.Modelli
	HumanoidRootPart.CFrame = Cartella.Generatore["1"].CFrame

	--Animazioni
	local Walk = Humanoid:LoadAnimation(Clone.Animazioni.Walk)
	local Idle = Humanoid:LoadAnimation(Clone.Animazioni.Idle):Play()
	
	--Cammina
	Generale.Curve(
		Cartella.Generatore["1"].Position,
		Posto,
		Cartella.Generatore["2"].Position,
		HumanoidRootPart,
		Walk
	)
	
end

--Funzione infinita
while wait(5) do
	--Here there's code to find if the end place is empity or not.
    --If it is empity, it creates the NPC
    Cliente(Posto)
end

Module script in replicated storage called ‘Generale’

local Generale = {}

--Servizi
local TweenService = game:GetService("TweenService")

function Generale.Curve(Inizio,Fine,Intermedio,Dummy,Animazione)
	--Funzioni
	local function lerp(a,b,t)
		return (1 - t) * a + t * b
	end

	--Inizia animazione
	if Animazione then
		Animazione:Play()
	end
	
	--Ciclo
	for i = 0,20,1 do
		--Variabili
		local T = i/20

		--Calcoli
		local l1 = lerp(Inizio,Intermedio,T)
		local l2 = lerp(Intermedio,Fine.Position,T)
		local quad = lerp(l1,l2,T)
		local diff = l2-l1
		local AngleY = math.atan2(diff.x,diff.z)*(180/math.pi)
		local Aspetta = (Dummy.Position - quad).Magnitude / 16

		--Sistema il dummy
		TweenService:Create(
			Dummy,
			TweenInfo.new(Aspetta),
			{Position = quad}
		):Play()
		TweenService:Create(
			Dummy,
			TweenInfo.new(Aspetta),
			{Orientation = Vector3.new(0,AngleY,0)}
		):Play()

		wait(Aspetta)
	end

	--Finisce animazione
	if Animazione then
		Animazione:Stop()
	end

	--Sistema
	TweenService:Create(
		Dummy,
		TweenInfo.new(0.1),
		{Position = Fine.Position}
	):Play()
	TweenService:Create(
		Dummy,
		TweenInfo.new(0.1),
		{Orientation = Fine.Orientation}
	):Play()
	
	wait(0.5)
end

return Generale

I tried searching around a solution, but it’s pretty hard to find. Thanks

this may not be obvious but the reason is because you are using Position instead of CFrame

I know this because the same happened for my TD game
you can use CFrame without changing the orientation like this

local function poscf(pos, cf) --name this whatever you want
   --how this works is this makes a new CF with the same XYZ as the Vector3 but keeps the other 9 arguments of the cframe meant for orientation the same
   return CFrame.new(pos.X, pox.Y, pos.Z, select(4, cf:GetComponents()))
end
1 Like

after reading it more it seems you are using position and orientation separately
you should instead use CFrame as it would fix your problem and it can both use position and orientation, this is probably the fix

local cf = CFrame.new(pos) * CFrame.Angles(rot.x, rot.y, rot.z)

(remember to convert your rot xyz values to radians)
you can tween the CFrame property of the humanoidrootpart using this to fix this issue

I still dont know why the Position and the Rotation properties doesnt work correctly in general

2 Likes

Thank you a lot, it is fixed now! :sunglasses:

2 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.