So I’m making a Block Tales inspired turn-based rpg, but I encountered an issue.
When it’s the enemies’ turn, they have a noticeable delay when they start walking (shown in video).
I’m currently using parts with an AlignPosition inside the HumanoidRootParts of the characters to walk them to their exact position, and I’ve already set all of their NetworkOwnerships to nil.
How can i make them walk smoothly on the server side? Or is it better to set their NetworkOwnerships to the client and handle everything there?
Code:
local function GetWalkForce(char)
if char:FindFirstChild("WalkForce") then
return char.WalkForce
end
local hrp = char.HumanoidRootPart
local walkforce = objects.WalkForce:Clone()
walkforce.Parent = char
walkforce.Name = "WalkForce"
walkforce.CFrame = hrp.CFrame
walkforce.Weld.Part1 = hrp
walkforce:SetNetworkOwner(nil)
return walkforce
end
function WalkTo(char, moveGoal, waitUntilFinished)
local player = game.Players:GetPlayerFromCharacter(char)
local hrp : Part, hum : Humanoid = char.HumanoidRootPart, char.Humanoid
hrp:SetNetworkOwner(nil) -- setting all parts seems to have the same effect
hum:ChangeState(Enum.HumanoidStateType.Running)
hum.AutoRotate = false
moveGoal = Vector3.new(moveGoal.x, hrp.Position.y, moveGoal.z)
local walkforce : Part = GetWalkForce(char)
local alignPos = walkforce.AlignPosition
alignPos.Enabled = true
alignPos.Position = moveGoal
if waitUntilFinished then
local dist, speed = (hrp.Position-(moveGoal)).Magnitude, hum.WalkSpeed
local walkDelay = player and -0.4 or 0.1
task.wait(dist/speed + walkDelay)
hrp.CFrame = hrp.CFrame.Rotation + Vector3.new(moveGoal.x, hrp.Position.y, moveGoal.z)
alignPos.Enabled = false
hum.AutoRotate = true
end
end
i saw you used network ownership to nil, but instead try to put the ownership ONLY to the enemy who the player clicked, else do it at the start of the fight
When I set the enemy’s network ownership to the player, their animations become delayed. I also would rather use server ownership for dodging and evading attacks.
I don’t want the enemies to lag before walking, so it’s not going to be a feature in my game. However, maybe I can add that later if I can fix the lag and have the server control the characters smoother.
local function GetWalkForce(char)
if char:FindFirstChild("WalkForce") then
return char.WalkForce
end
-- Ensure 'WalkForce' exists in ServerStorage or a valid location
local walkforce = game.ServerStorage.WalkForce:Clone() -- Replace with actual location of WalkForce
local hrp = char.HumanoidRootPart
walkforce.Parent = char
walkforce.Name = "WalkForce"
walkforce.CFrame = hrp.CFrame
-- Ensure the AlignPosition constraint is set up properly
local alignPos = walkforce:FindFirstChildOfClass("AlignPosition") or Instance.new("AlignPosition")
alignPos.Parent = walkforce
alignPos.MaxForce = 100000 -- Adjust force as needed
alignPos.Attachment0 = walkforce:FindFirstChild("Attachment") -- Ensure this is correct in your setup
walkforce.Weld.Part1 = hrp
walkforce:SetNetworkOwner(nil)
return walkforce
end
function WalkTo(char, moveGoal, waitUntilFinished)
local player = game.Players:GetPlayerFromCharacter(char)
local hrp, hum = char.HumanoidRootPart, char.Humanoid
hrp:SetNetworkOwner(nil) -- Setting all parts seems to have the same effect
hum:ChangeState(Enum.HumanoidStateType.Running)
hum.AutoRotate = false
-- Adjust y-coordinate of moveGoal to match the character's current height
moveGoal = Vector3.new(moveGoal.x, hrp.Position.y, moveGoal.z)
local walkforce = GetWalkForce(char)
local alignPos = walkforce.AlignPosition
alignPos.Enabled = true
alignPos.Position = moveGoal
if waitUntilFinished then
local dist = (hrp.Position - moveGoal).Magnitude
local speed = hum.WalkSpeed
local walkDelay = player and -0.4 or 0.1 -- Small adjustment for player movement
task.wait(dist / speed + walkDelay)
-- Ensure proper rotation after movement
hrp.CFrame = CFrame.new(moveGoal.x, hrp.Position.y, moveGoal.z) * hrp.CFrame - hrp.Position
alignPos.Enabled = false
hum.AutoRotate = true
end
end
The problem looks to be, that your movement logic is built around AlignPosition constraints processed by the server-side and that can add extra latency from processing on the server and latency itself.
So should I handle everything on the client? I dont think it would be very secure and it would result in delay for other players in the battle. I have to use AlignPosition because humanoid:MoveTo() is a stud away from the target position.
The game seems deteministic, so the server handles the outcome of the battle (damage, dodge, ecc.) The client plays characters’ animations. By the way it seems that the character has a little delay because the Network Ownership changes from the server to the client (when it gets near the player). But i might be wrong
I think the network ownership stays the same the whole time (i tested through printing). I’m thinking about switching to client side, but I’m still worried it might not be secure and that it could introduce delays for other clients. There could also be walking actions that the enemies could do without a target player, so I have to set network ownership to the server for that.
Just make a remote event that gets fired by the server to all clients when the attack/move function is called. The server still manages the damage, health, ecc… And in the client you play the animation/movement. You just give to the client which character is going to move and the Animation/movemente info.
The client can’t change the outcome of the attack because it is managed in the server.
Each change in the part’s position, during the movement, gets replicated to the client. It’s for this reason that the movement often it’s not smooth. So it doesn’t really matter if the client has bad ping/fps.
That makes sense. But what i’m wondering is what could i do if a client is lagging in framerate and an enemy is shown punching on their screen, and on the server the targeted player just landed from their jump (the enemy’s fist phases through the player)?
When the jump is replicated does it account for the other client’s framerates? Or does it skip a few frames to be accurate as possible?
Btw, putting animation/movement on the client seems to be much more smoother. Just not sure about the potential issue i have above.
Sorry for bothering you again. I have another issue with handling everything on the client side. What do i do when a new player joins the battle during a turn? They will just see the characters doing nothing.
I meant to ask about what to do when a player joins in the middle of a turn. Since the remoteEvents for that turn have already been fired to the players that joined before, what do i do for the new player? If i fire the same remote to them, it will be delayed.