Need help on moving the enemys on the client

I got some help on making my TD Game enemy System but now I am confused about how will I make the enemies move smoothly, right now they keep teleporting and doing the turning sequence, and thats all I tried tween service but it went horribly wrong any help?

Server Sided Script:

local enemy = {}

local replicated = game:GetService("ReplicatedStorage")
local runService = game:GetService("RunService")

local modules = replicated.Modules

local Waves = require(modules.Waves)
local mobInfoDB = require(modules.mobInfoDataBase)
_G.EnemyDB = {}
local background = require(script.Background)

local events = replicated:WaitForChild("Events")

local enemySyncer = events:WaitForChild("EnemySyncer")

local map = game.Workspace["Crash Test Zone"]
local Nodes = map.Waypoints

local spawnCFrame = Nodes[1].CFrame

local function enemyDead(enemy)
	_G.EnemyDB[enemy.EnemyHash] = "dead"
end

local function addEnemyToDB(name)
	local Table = {}
	for itemName, item in pairs(mobInfoDB[name]) do
		Table[itemName] = item
		if itemName == "CFrame" then
			Table["CFrame"] = spawnCFrame
		end
		Table["RealName"] = name
		Table["EnemyHash"] = #_G.EnemyDB + 1
	end
	table.insert(_G.EnemyDB, Table)
end

local function IntitiateTurningSequence(enemyData)
	if enemyData.Node + 1 >= #Nodes:GetChildren() then
		enemyDead(enemyData)
		return
	end

	enemyData.Turning = true
	task.wait(((Nodes[enemyData.Node].Position - Nodes[enemyData.Node].Mid.Position).Magnitude / enemyData.Speed) - enemyData.TurnerHelper)
	enemyData.CFrame = Nodes[enemyData["Node"]].Mid.CFrame
	task.wait((Nodes[enemyData.Node].Mid.Position - Nodes[enemyData.Node].End.Position).Magnitude / enemyData.Speed)
	enemyData.Turning = false
	enemyData.CFrame = Nodes[enemyData["Node"]].End.CFrame
	enemyData.Node += 1
end


local function WaveSequence()
	task.wait(5)
	for waveCount, waveData in pairs(Waves) do
		for EnemyCount, enemyData in pairs(waveData.Enemies) do
			task.wait(enemyData.startDelay)
			for count = 1, enemyData.Amount do
				addEnemyToDB(enemyData.EnemyName)
				task.wait(enemyData.Interval)
			end
		end		
	end
end

local count = 0
local overallDeltaTime = 0

runService.Heartbeat:Connect(function(deltaTime)
	count += 1
	overallDeltaTime += deltaTime
	for enemyID, enemyData in pairs(_G.EnemyDB) do
		if enemyData.Turning == false and enemyData ~= "dead" then
			enemyData.CFrame = Nodes[enemyData["Node"]].CFrame:ToWorldSpace(CFrame.new(0, 0, (enemyData.CFrame.Position - Nodes[enemyData["Node"]].Position).Magnitude - (enemyData.Speed * overallDeltaTime)))
			
			local clientEnemyInfo = {
				["RealName"] = enemyData.RealName,
				["EnemyHash"] = enemyID,
				["CFrame"] = enemyData.CFrame,
				["Health"] = enemyData.Health,
				["Node"] = enemyData.Node,
				["Speed"] = enemyData.Speed,
				["TurnerHelper"] = 0,
				["CornerStatus"] = 0,
				["XOffset"] = enemyData.XOffset,
				["YOffset"] = enemyData.YOffset
			}
			
			enemySyncer:FireAllClients(clientEnemyInfo)
			if Nodes[enemyData["Node"]].CFrame:ToWorldSpace():ToObjectSpace(enemyData.CFrame).Position.Z <= 0 then
				enemyData.TurnerHelper = (Nodes[enemyData["Node"]].CFrame:ToWorldSpace():ToObjectSpace(enemyData.CFrame).Position.Z * -1) / enemyData.Speed
				enemyData.CFrame = Nodes[enemyData["Node"]].CFrame
				coroutine.wrap(IntitiateTurningSequence)(enemyData)
			end
		end
	end
end)

coroutine.wrap(WaveSequence)()

return enemy

Client Sided Script:

local replicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local UIS = game:GetService("UserInputService")
local ts = game:GetService("TweenService")

local modules = replicatedStorage:WaitForChild("Modules")
local Events = replicatedStorage:WaitForChild("Events")
local enemyModels = replicatedStorage:WaitForChild("Enemies")

local Waves = require(modules:WaitForChild("Waves"))
_G.EnemyDB = {}
EnemyInfoDB = require(modules:WaitForChild("mobInfoDataBase"))
mobAbilities = require(modules:WaitForChild("mobAbilities"))

local enemySyncer = Events:WaitForChild("EnemySyncer")

local PlayerModels = {}

local Player = Players.LocalPlayer
local playerUI = Player:WaitForChild("PlayerGui")

local healthGUI = playerUI:WaitForChild("HealthUI")
local MainFrame = healthGUI:WaitForChild("Main")

local Name = MainFrame:WaitForChild("Name"):WaitForChild("Name")
local Health = MainFrame:WaitForChild("Bar"):WaitForChild("Health")
local MaxHealth = MainFrame:WaitForChild("Bar"):WaitForChild("MaxHealth")
local HealthText = MainFrame:WaitForChild("Bar"):WaitForChild("HealthText")

local map = game.Workspace["Crash Test Zone"]
local Nodes = map.Waypoints

local rayCast = nil
local barTween = nil

local Camera = workspace.CurrentCamera

local spawnCFrame = Nodes[1].CFrame + Vector3.new(0, 3, 0)

local function enemyDead(enemy)
	workspace.Enemies.Active[enemy.EnemyHash].Parent = workspace.Enemies.Dead
	workspace.Enemies.Dead[enemy.EnemyHash]:Destroy()
	_G.EnemyDB[enemy.EnemyHash] = "dead"
end

local function Lerp(a, b, t)
	return a + (b - a) * t
end

local function QuadraticBezier(t, p0, p1, p2)
	local l1 = Lerp(p0, p1, t)
	local l2 = Lerp(p1, p2, t)
	local quad = Lerp(l1, l2, t)

	return quad
end

local function mouseRayCast(blackList)
	local mousePos = UIS:GetMouseLocation()
	local mouserRay = Camera:ViewportPointToRay(mousePos.X, mousePos.Y)
	local rayCastParams = RaycastParams.new()
	rayCastParams.FilterType = Enum.RaycastFilterType.Exclude
	rayCastParams.FilterDescendantsInstances = blackList

	local mouseRayCastResult = workspace:Raycast(mouserRay.Origin, mouserRay.Direction * 5000, rayCastParams)

	return mouseRayCastResult
end

local function IntitiateDBTurningSequence(enemyData)
	if enemyData.Node >= #Nodes:GetChildren() then
		enemyDead(enemyData)
		return
	end	
	enemyData.Turning = true
	task.wait(((Nodes[enemyData.Node].Position - Nodes[enemyData.Node].Mid.Position).Magnitude / enemyData.Speed) - enemyData.TurnerHelper)
	enemyData.CFrame = Nodes[enemyData["Node"]].Mid.CFrame
	task.wait((Nodes[enemyData.Node].Mid.Position - Nodes[enemyData.Node].End.Position).Magnitude / enemyData.Speed)
	enemyData.Turning = false
	enemyData.CFrame = Nodes[enemyData["Node"]].End.CFrame
	enemyData.Node += 1
end

local function InitiateGraphicalTurningSequenceLoop(deltaTime, enemyId, enemyData, Time, Distance, Position, EndCFrame, lookPos, Node0, Node1, Node2)
	if _G.EnemyDB[enemyId] == "dead" then 
		RunService:UnbindFromRenderStep("CornerTurn"..enemyId)
		return
	end	
	enemyData.CornerStatus += deltaTime

	Time = enemyData.CornerStatus / Distance

	if Time > 1 then
		workspace.Enemies.Active:WaitForChild(enemyId).PrimaryPart.CFrame = EndCFrame
		enemyData.CornerStatus = 0
		RunService:UnbindFromRenderStep("CornerTurn"..enemyId)
	else
		Position = QuadraticBezier(Time, Node0, Node1, Node2)
		lookPos = QuadraticBezier(Time + 0.001, Node0, Node1, Node2)

		if workspace.Enemies.Active:FindFirstChild(enemyId) then
			workspace.Enemies.Active:FindFirstChild(enemyId).PrimaryPart.CFrame = CFrame.lookAt(Position, lookPos)
		end
	end
end

local function InitiateGraphicalTurningSequence(enemyId, enemyData)
	if _G.EnemyDB[enemyId] == "dead" then return end

	workspace.Enemies.Active:FindFirstChild(enemyId).PrimaryPart.CFrame = enemyData.CFrame
	local distance = ((Nodes[enemyData["Node"]].Position - Nodes[enemyData["Node"]].Mid.Position).Magnitude / enemyData["Speed"]) - enemyData.TurnerHelper + (Nodes[enemyData["Node"]].Mid.Position - Nodes[enemyData["Node"]].End.Position).Magnitude / enemyData["Speed"]
	local Time = 0
	local pos = 0
	local lookPos = 0

	local Node = enemyData["Node"]

	local Node0 = Nodes[Node].Position + (workspace.Enemies.Active[enemyId].PrimaryPart.CFrame:ToWorldSpace(CFrame.new(enemyData.XOffset, enemyData.YOffset, 0)).Position - workspace.Enemies.Active[enemyId].PrimaryPart.Position)
	local Node1 = Nodes[Node].Mid.Position + (workspace.Enemies.Active[enemyId].PrimaryPart.CFrame:ToWorldSpace(CFrame.new(enemyData.XOffset, enemyData.YOffset, enemyData.XOffset)).Position - workspace.Enemies.Active[enemyId].PrimaryPart.Position) 
	local Node2 = Nodes[Node].End.Position + (workspace.Enemies.Active[enemyId].PrimaryPart.CFrame:ToWorldSpace(CFrame.new(0, enemyData.YOffset, enemyData.XOffset)).Position - workspace.Enemies.Active[enemyId].PrimaryPart.Position)

	local EndCFrame = Nodes[Node].End.CFrame + (workspace.Enemies.Active[enemyId].PrimaryPart.CFrame:ToWorldSpace(CFrame.new(0, enemyData.YOffset, enemyData.XOffset)).Position - workspace.Enemies.Active[enemyId].PrimaryPart.Position)


	RunService:BindToRenderStep("CornerTurn".. enemyId, 0, function(DeltaTime)
		InitiateGraphicalTurningSequenceLoop(DeltaTime, enemyId, enemyData, Time, distance, pos, EndCFrame, lookPos, Node0, Node1, Node2)
	end)
end

local gui = playerUI.MainUI
local tweenService = game:GetService("TweenService")

local function displayEndScreen(status)
	local screen = gui.Endscreen

	if status == "Game Over" then
		screen.Content.Title.TextColor3 = Color3.new(255,0,0)
		screen.Content.SubTitle.Text = "Better Luck Next Time"

	elseif status == "Victory" then
		screen.Content.Title.TextColor3 = Color3.new(0.0627451, 0.427451, 0.00784314)
		screen.Content.SubTitle.Text = "Congratulations, You Won!"
	end

	screen.Content.Title.Text = status
	screen.Stats.Money.Text = "Money: "..game.ReplicatedStorage.GameStats.Wave.Value * 10 + 10
	screen.Stats.Exp.Text = "Exp: "..game.ReplicatedStorage.GameStats.Wave.Value * 5

	screen.Size = UDim2.new(0,0,0,0)
	gui.Endscreen.Visible = true

	local tweenStyle = TweenInfo.new(0.5, Enum.EasingStyle.Back, Enum.EasingDirection.Out, 0, false, 0)
	local zoomTween = tweenService:Create(screen, tweenStyle, {Size = UDim2.new(1,0,1,0)})
	zoomTween:Play()	


	local exitEvent = game.ReplicatedStorage.Events:WaitForChild("Exit")

	screen.Teleport.Activated:Connect(function()
		screen.Visible = false
		exitEvent:FireServer(game.ReplicatedStorage.GameStats.Wave.Value * 10 + 10)
	end)		
end

local function DoNeededThings(enemy)
	local Animation = enemy:WaitForChild("Walk")
	local track = enemy:WaitForChild("Humanoid"):WaitForChild("Animator"):LoadAnimation(Animation)

	track:Play()
end

local function intitatePlayerScan()
	for i,v in pairs(Players:GetPlayers()) do
		if v.Character or v.CharacterAdded:Wait() then
			table.insert(PlayerModels, v.Character)
		end
	end
end

Players.PlayerAdded:Connect(function(v)
	if v.Character or v.CharacterAdded:Wait() then
		table.insert(PlayerModels, v.Character)
	end
end)

Players.PlayerRemoving:Connect(function(v)
	PlayerModels[v.Character] = nil
end)

--[[local function rayCastLoop()
	rayCast = mouseRayCast({PlayerModels})

	if replicatedStorage.GameStats.BaseHealth.Value <= 0 then
		RunService:UnbindFromRenderStep("RayCastLoop")
	end

	if rayCast then
		if rayCast.Instance:IsDescendantOf(workspace.Enemies.Active) then
			MainFrame.Position = UDim2.fromOffset(UIS:GetMouseLocation().X, UIS:GetMouseLocation().Y)
			if healthGUI.Values.Hash.Value == _G.EnemyDB[tonumber(rayCast.Instance:FindFirstAncestorWhichIsA("Model").Name)].EnemyHash and healthGUI.Values.Health.Value == _G.EnemyDB[tonumber(rayCast.Instance:FindFirstAncestorWhichIsA("Model").Name)].Health then
				barTween = ts:Create(
					Health,
					TweenInfo.new(
						.4,
						Enum.EasingStyle.Quad
					),
					{Size = UDim2.new(_G.EnemyDB[tonumber(rayCast.Instance:FindFirstAncestorWhichIsA("Model").Name)].Health / _G.EnemyDB[tonumber(rayCast.Instance:FindFirstAncestorWhichIsA("Model").Name)].MaxHealth, 0, 1, 0)}
				)
				barTween:Play()
			else
				if barTween then
					barTween:Cancel()
					barTween = nil
				end
				Health.Size = UDim2.new(_G.EnemyDB[tonumber(rayCast.Instance:FindFirstAncestorWhichIsA("Model").Name)].Health / _G.EnemyDB[tonumber(rayCast.Instance:FindFirstAncestorWhichIsA("Model").Name)].MaxHealth, 0, 1, 0)
			end

			HealthText.Text = _G.EnemyDB[tonumber(rayCast.Instance:FindFirstAncestorWhichIsA("Model").Name)].Health.."/".._G.EnemyDB[tonumber(rayCast.Instance:FindFirstAncestorWhichIsA("Model").Name)].MaxHealth

			healthGUI.Values.Health.Value = _G.EnemyDB[tonumber(rayCast.Instance:FindFirstAncestorWhichIsA("Model").Name)].Health
			healthGUI.Values.Hash.Value = _G.EnemyDB[tonumber(rayCast.Instance:FindFirstAncestorWhichIsA("Model").Name)].EnemyHash

			Name.Text = _G.EnemyDB[tonumber(rayCast.Instance:FindFirstAncestorWhichIsA("Model").Name)].RealName

			healthGUI.Enabled = true
		else
			healthGUI.Enabled = false
		end
	else
		healthGUI.Enabled = false
	end
end-]]


local function timer(data)
	task.wait(data.Timer)
	return true
end

enemySyncer.OnClientEvent:Connect(function(clientInfo, overallDeltaTime)
	if not workspace.Enemies.Active:FindFirstChild(clientInfo["EnemyHash"]) then
		local new = replicatedStorage.Enemies:FindFirstChild(clientInfo["RealName"]):Clone()
		new.Parent = workspace.Enemies.Active
		new.HumanoidRootPart.CFrame = spawnCFrame

		new.Name = clientInfo["EnemyHash"]
	else
		local new = workspace.Enemies.Active:FindFirstChild(clientInfo["EnemyHash"])
		clientInfo.CFrame = Nodes[clientInfo["Node"]].CFrame:ToWorldSpace(CFrame.new(0, 0, (clientInfo.CFrame.Position - Nodes[clientInfo["Node"]].Position).Magnitude - (clientInfo.Speed * overallDeltaTime)))
		if Nodes[clientInfo["Node"]].CFrame:ToWorldSpace():ToObjectSpace(clientInfo.CFrame).Position.Z <= 0 then
			clientInfo.TurnerHelper = (Nodes[clientInfo["Node"]].CFrame:ToWorldSpace():ToObjectSpace(clientInfo.CFrame).Position.Z * -1) / clientInfo.Speed
			clientInfo.CFrame = Nodes[clientInfo["Node"]].CFrame
			coroutine.wrap(IntitiateDBTurningSequence)(clientInfo)
			coroutine.wrap(InitiateGraphicalTurningSequence)(clientInfo["EnemyHash"], clientInfo)
		end
		new.HumanoidRootPart.CFrame = clientInfo.CFrame + (workspace.Enemies.Active[clientInfo["EnemyHash"]].PrimaryPart.CFrame:ToWorldSpace(CFrame.new(clientInfo.XOffset, clientInfo.YOffset, 0)).Position - workspace.Enemies.Active[clientInfo["EnemyHash"]].PrimaryPart.Position)

	end	
end)

intitatePlayerScan()
2 Likes