Client sided position or orientation is incorrectly displayed from its true server position

  1. What do you want to achieve? Keep it simple and clear!
    I want the player and enemy to be at the same position and orientation during the attack as the animation plays.

  2. What is the issue? Include screenshots / videos if possible!
    the player and enemy are correctly positioned on the server but for the client side of the player it is incorrect (this also happens for players when i tested with the player emulator)

  3. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
    I have seen some vaguely similar posts on the devforum suggesting this, so i tried using a remote event to fire the client and send the position and orientation to the client to see if it fixed it, but it hasnt changed anything.

CLIENT: [it made me go underground in the animation due to incorrect position/orientation?]

SERVER: [correctly aligned]
image

CODE FOR ALIGNMENT:

“Hum” is the players humanoid (person doing the attack)
“humanoid” is the enemy humanoid
“HRP” is the players humanoid root part
“EnemyHumanoidRootPart” is the enemy humanoid root part

		Hum.AutoRotate = false
		humanoid.AutoRotate = false
		HRP.Anchored = true
		EnemyHumanoidRootPart.Anchored = true
		local attackerPosition = HRP.Position
		local Y = HRP.Orientation.Y 

		--Making sure the player parallel with the floor
		local attackerFlatCFrame = CFrame.new(attackerPosition) * CFrame.Angles(0, math.rad(Y), 0)
		HRP.CFrame = attackerFlatCFrame
		EnemyHumanoidRootPart.CFrame = HRP.CFrame

Bump,Bump
Bump,Bump
Bump,Bump
Bump,Bump
Bump,Bump

Discrepancies between server and client positions can arise due to latency or how the engine handles physics and animations differently on both ends. I would use RemoteEvents to ensure the client updates its position and orientation based on the server.

Ultimately the logic behind this is sending the positions to the clients, and force the clients so set the positions of the characters accordingly, as opposed to doing so on the server exclusively.

You may need to adjust the code a bit, but your server script would look something like:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local AlignEvent = Instance.new("RemoteEvent", ReplicatedStorage)
AlignEvent.Name = "AlignEvent"

-- Function to align characters
local function alignCharacters(attacker, enemy)
    local HRP = attacker:FindFirstChild("HumanoidRootPart")
    local EnemyHumanoidRootPart = enemy:FindFirstChild("HumanoidRootPart")
    local Hum = attacker:FindFirstChildOfClass("Humanoid")
    local EnemyHumanoid = enemy:FindFirstChildOfClass("Humanoid")

    if HRP and EnemyHumanoidRootPart and Hum and EnemyHumanoid then
        Hum.AutoRotate = false
        EnemyHumanoid.AutoRotate = false
        HRP.Anchored = true
        EnemyHumanoidRootPart.Anchored = true
        
        local attackerPosition = HRP.Position
        local Y = HRP.Orientation.Y 

        -- Make sure the player is parallel with the floor
        local attackerFlatCFrame = CFrame.new(attackerPosition) * CFrame.Angles(0, math.rad(Y), 0)
        HRP.CFrame = attackerFlatCFrame
        EnemyHumanoidRootPart.CFrame = HRP.CFrame

        -- Fire event to clients with positions and orientations
        AlignEvent:FireAllClients(attacker, HRP.Position, HRP.Orientation, enemy, EnemyHumanoidRootPart.Position, EnemyHumanoidRootPart.Orientation)
    end
end

-- Example function call (call this function somewhere in your code when you need to do the animation)
alignCharacters(playerCharacter, enemyCharacter)

Handling the alignment on the client’s side (LocalScript)

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local AlignEvent = ReplicatedStorage:WaitForChild("AlignEvent")

AlignEvent.OnClientEvent:Connect(function(attacker, attackerPos, attackerOri, enemy, enemyPos, enemyOri)
    -- Update the attacker's position and orientation
    if attacker then
        local HRP = attacker:FindFirstChild("HumanoidRootPart")
        if HRP then
            -- Smoothly update the position and orientation to avoid sudden jumps
            HRP.Anchored = true
            HRP.CFrame = CFrame.new(attackerPos) * CFrame.Angles(0, math.rad(attackerOri.Y), 0)
            HRP.Anchored = false
        end
    end

    -- Update the enemy's position and orientation
    if enemy then
        local EnemyHumanoidRootPart = enemy:FindFirstChild("HumanoidRootPart")
        if EnemyHumanoidRootPart then
            -- Smoothly update the position and orientation to avoid sudden jumps
            EnemyHumanoidRootPart.Anchored = true
            EnemyHumanoidRootPart.CFrame = CFrame.new(enemyPos) * CFrame.Angles(0, math.rad(enemyOri.Y), 0)
            EnemyHumanoidRootPart.Anchored = false
        end
    end
end)
2 Likes

Honestly thank you so much, this fixed it perfectly, you saved me so much time.
The only thing i had to do was run align characters more than once as the attack involved alot of movement in the starting phase causing inconcistency.
Seriously thank you!

2 Likes

My pleasure! Would love to see how the finished product turns out when completed :smiley:

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