Align Position Stuttering On Client But Smooth On Server

I am making a tower defense game and I’m using align position and align orientation to move and rotate the enemies.

All goes well while running the game, but when playing I noticed a stutter when they reached the waypoints on the client.

  • Basically it stutters for about a second once reaching the waypoint and then continues to the next, but when switching to the server it is a smooth as butter.

  • I’ve tried setting the network ownership to the server but it didn’t seem to do anything.

  • searched a good bit but I can’t seem to find the same issue online.

Any help?

create the alignposition on the client, physics replication is notoriously stuttery

wouldn’t that cause issues for like every other player desyncing their position for each player?
By that I mean wouldn’t the position for the enemies be different for each player even by a little bit?

if they have the same target position it should be fine

alright, but how do you suppose I create it on the client, I spawn the characters using a server side script so I’m not quite sure what to do about creating it on the client.
Maybe I just spawn them on the server and move them for each client?

are they only visual? or are the positions being used for some logic? if its only visual then you could just use remote events to tell the client how to create the alignposition.

it’s not really visual only, it’s used to move the enemies, damage the base and end the game.
So I wouldn’t really say it’s visual only, I use the alignPositions to move them.
Any suggestions?

i just woke up so i might be missing a more obvious solution here, but you could:

  1. use an invisible anchor for the server to track its ACTUAL position
  2. move the actual visual enemy on the clients by creating the alignposition for each client
  3. add a check to make sure that the anchor and enemy dont get too far apart (optional)

the invisible anchor would be the enemy’s position for distance calculations, like checking if the enemy is in range of a tower for example. they should only be about as far apart as the velocity multiplied by the player’s ping for each client, which won’t be much in any case.

1 Like

that’s actually a pretty good idea, though how would you suppose moving the anchor for the enemy?
Since I move the humanoidRootPart on the server for my current enemy movement, can I just do the same but visualize it on the client?
Or for example make a part that will be the anchor (it’s absolute position) and make the enemies humanoidRootPart use alignPosition on that to move it?

i was thinking an invisible part that the server places the alignposition on and treats it as the enemy’s position, and the humanoid root part is only ever moved by the client.

whenever the server alignposition’s attachment is set, you would send a remote event to the clients to set their local attachments as well. that way, any stutter in replicating the anchor would be ignored since the client’s visuals are completely decoupled from it.

1 Like

alright so what I’m getting from this is the invisible part is the part where the alignPosition is set and is the part which the humanoidrootpart follows. Though how would we move that invisible part is my question?

the invisible part has an alignposition on the server moving it, replacing the humanoid root part.
the humanoid root part on the client is doing what the server was doing in the original version

server example

local THRESHOLD = 0.5

local Enemy = workspace.Rig
local Path = workspace.Path
local Waypoints = Path:GetChildren()

local SetWaypoint = game.ReplicatedStorage.SetWaypoint

local Anchor = Instance.new("Part")
Anchor.CanCollide = false
Anchor.Parent = workspace

local AlignPosition = Instance.new("AlignPosition", Anchor)
AlignPosition.Attachment0 = Instance.new("Attachment", Anchor)
AlignPosition.MaxVelocity = 2

game.Players.PlayerAdded:Wait()

while true do
	local attachment = Waypoints[math.random(#Waypoints)]
	AlignPosition.Attachment1 = attachment
	SetWaypoint:FireAllClients(attachment)
	repeat task.wait() until (AlignPosition.Attachment1.WorldPosition - AlignPosition.Attachment0.WorldPosition).Magnitude < THRESHOLD
end

client

local Enemy = workspace.Rig
local AlignPosition = Instance.new("AlignPosition", Enemy:WaitForChild("HumanoidRootPart"))
AlignPosition.Attachment0 = Enemy.HumanoidRootPart:WaitForChild("RootAttachment")
AlignPosition.MaxVelocity =2

game.ReplicatedStorage.SetWaypoint.OnClientEvent:Connect(function(attachment)
	AlignPosition.Attachment1 = attachment
end)
1 Like

Thanks you, I’ll be sure to test it out by later. One last question, how did you visualize the attachment lines?

in the model tab
image

1 Like

Yeah I see it now, thank you so much man, you’ve been a huge help.

1 Like

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