I’m working on a furniture system where the user can place objects, but when I send the CFrame to server the server gives the wrong rotation, meaning that the object will always be put in the opposite direction
I tried using cf:ToEulerAnglesXYZ() to get rotations and sending cframe position, rx, ry, rz to server, and when I print rx/ry/rz they have the same values in both environments, but when I create the CFrame in the server (with CFrame.new(position) * CFrame.fromEulerAnglesXYZ(rx, ry, rz)) it still giving the same wrong result:
y r u being so weird with it, just use cframe not separate, if not, math.rad(180) + [x/y/z]
-- Client
local cf = Model:GetPivot()
print("Client CFrame: " .. tostring(cf))
local result = PlaceRemote:InvokeServer(Model.Name, cf)
-- Server
PlaceObject.OnServerInvoke = function(player: Player, furnitureName: string, cf)
print("Server CFrame: " .. tostring(cf))
-- Use the received CFrame to place the object
-- ...
end
I’ve tried sending directly the PrimaryPart CFrame to server and using SetPrimaryPart on server, gives the same results.
Using CFrame directly in parameter was the first thing that I did. Rotating 180 degrees obviously works but’s kinda a hacky way and I’m curious about why CFrame isn’t replicating correctly through Client → Server
idk could be sum wrong with your network ownership, or how your cloning your model, or where you get them from, like if they don’t have rotation but on the client placing you have rotation, I tried your system real quick on mine and I got nothing wrong.
The same model. Server gets the model from ReplicatedStorage using the name that client gave. Clients also gets the model from the same place (ReplicatedStorage)
-- This code should be placed in a LocalScript under StarterPlayerScripts
local Players = game:GetService("Players")
local ContextActionService = game:GetService("ContextActionService")
local player = Players.LocalPlayer
local function doTeleport(_actionName, inputState, _inputObject)
local character = player.Character
if character and character.Parent and inputState == Enum.UserInputState.Begin then
-- Move the character 10 studs forwards in the direction they're facing
local currentPivot = character:GetPivot()
character:PivotTo(currentPivot * CFrame.new(0, 0, -10))
end
end
ContextActionService:BindAction("Teleport", doTeleport, true, Enum.KeyCode.F)
It is from:
These two lines of code:
local currentPivot = character:GetPivot() – send to server
character:PivotTo(currentPivot * CFrame.new(0, 0, -10)) – use on server
I feel obligated to point out that both -4.37113883e-08 and -6.18172393e-08 are both effectively zero and that them being rounded to zero is probably due to some quirk on the C++ side.
Try changing your code so that you only provide the server with the Position and LookVector of the CFrame, and then reconstruct it that way.
-- Client
local result = PlaceRemote:InvokeServer(Model.Name, cf.Position, cf.LookVector)
-- Server
PlaceObject.OnServerInvoke = function(player: Player, furnitureName: string, position: Vector3, lookVector: Vector3)
-- also dear god please put some sanity checks in here so you don't get NaN'd
-- assert position == position, lookVector == lookVector, etc.
local cf = CFrame.lookAlong(position, lookVector, Vector3.yAxis)
end
Oh, thank you so much! I thought client was sending like -4.371 and -6.181, I didn’t know that they are basically 0.
After some research I discovered that what was causing the object point to wrong direction was actually the MeshPart that had been set to -180 orientation at some point in Studio (My model is a MeshPart with a extra PrimaryPart for hitbox) and setting it back to 0 solve the issue.
The only thing I didn’t understand was the CFrame being different on client and server, but with your explication now it makes total sense, it’s probably just the Improved rotation replication precision in action.