TD Enemy Movement, how to tween and sync enemy positions across every client?

I’m working on a tower defense project, and I want to have smooth and non-laggy enemy movement.
Some devforum posts say to use client-sided rendering or movement, but how exactly can I do this?

My main issue with this is that I couldn’t figure out how to make enemy positions in-sync across all clients. For the game, I need to tween the enemies across nodes until it reaches the last node, which I can do, but being in sync on every client, I’m not sure how I can do that.

I’ve been trying to figure this out for a while now, any help would be appreciated.

You can use workspace:GetServerTimeNow() to get the time offset between when an enemy spawns on the server (send the server time to the client) and calling the function on the client for comparison.

This should get a time offset when multiplied by the enemies speed get a distance offset needed to sync the client with the server.

1 Like

I’m not sure if I’m doing this right, but here is my code. Did I do it right? the enemyInfo.Tick is the server time

remotes.CreateEnemy.OnClientEvent:Connect(function(enemyInfo)
	enemyInfo.Model = game.ReplicatedStorage:WaitForChild('Enemies'):FindFirstChild(tostring(enemyInfo.Name)):Clone()
	enemyInfo.Model.Name = tostring(enemyInfo.ID)
	enemyInfo.Model.Parent = workspace:WaitForChild('Enemies')
	enemyInfo.Model:PivotTo(workspace:WaitForChild('Spawn').CFrame)
	
	local timeOffset = (enemyInfo.Tick - workspace:GetServerTimeNow())
	local distanceOffset = (enemyInfo.Speed * timeOffset)
	
	while enemyInfo.CurrentNode ~= #nodes:GetChildren() + 1 do
		local node = nodes:FindFirstChild(tostring(enemyInfo.CurrentNode))
		local mag = (enemyInfo.Model.HumanoidRootPart.Position - node.Position).magnitude
		
		tween(enemyInfo.Model.HumanoidRootPart, 'Linear', 'In', {CFrame = CFrame.new(node.Position - Vector3.new(0, 0, distanceOffset))}, mag / enemyInfo.Speed)
		
		task.wait(mag / enemyInfo.Speed)
		
		enemyInfo.CurrentNode += 1
	end
end)

1 Like

The calculation for distance offset looks ok, but you should print it to see if the value is reasonable.

The issue I see is that the direction is applied in the Z axis.

This offset should be applied to the initial spawn CFrame towards the direction of the next way point.

1 Like

Can you give me an example please?

1 Like

	
	local timeOffset = (enemyInfo.Tick - workspace:GetServerTimeNow())
	local distanceOffset = (enemyInfo.Speed * timeOffset)

		local node = nodes:FindFirstChild(tostring(enemyInfo.CurrentNode))
local directionToNode = node.Position - workspace:WaitForChild('Spawn').CFrame.Position
	enemyInfo.Model:PivotTo(workspace:WaitForChild('Spawn').CFrame+directionToNode.Unit*distanceOffset )

1 Like

After applying this offset to the spawn CFrame, do I just tween the enemies to the node positions like normal?

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