Changing CFrame of Character is Inconsistent

Over the past few month I have been trying to accurately set the CFrame of the character to a part’s CFrame within my round-based game. Despite conducting various tests and sanity checks to ensure the reliability of my code, I’ve encountered a recurring issue where the character’s CFrame fails to update to that of the target part’s CFrame on certain occasions. This anomaly occurs despite all conditions seemingly being met, leading to a situation where the character’s CFrame is successfully set as intended only about 80% of the time, thus highlighting a significant inconsistency in the process.

To address this, I’ve been setting all CFrames for the character on the server side, employing methods such as :PivotTo and directly assigning the HumanoidRootPart.CFrame to the desired CFrame. Unfortunately, both approaches have resulted in the same unpredictable behavior regarding CFrame updates. This inconsistency poses a considerable challenge, impacting the game’s functionality and user experience.

Links to other people facing the same issue:

Video of inconsistent CFraming:

2 Likes

There is no error messages. All CFraming for the characters is done on the server using PivotTo.

Here is the logic:

local tpCF = Selected_Map:WaitForChild("TeleportPart").CFrame
local teleport = tpCF * CFrame.new(0, 7, 0)
char:PivotTo(teleport)

I bet this is a network ownership issue, the client has control of their character’s physics, so if you set their position and they’re lagging or tabbed out, they might just flatout ignore it and end up teleporting themselves back to where they were.

1 Like

You could use a RemoteEvent to tell the client where to go. Or temporarily set the network owner of the player’s HumanoidRootPart to the server.

1 Like

Have you tried this on the client yet? It should work just fine there. If you’re doing it on the server to avoid abuse, well, that’s sorta useless since players have networkownership of their character anyway.

Also, if you’re doing this on the server, I’m curious about what you mean by doing sanity checks on your code? Is the client sending information to your script? I can’t really think of any client information you would reliably need for this.

1 Like

This happens very irregularly and especially with adaptive-timestep physics.

I usually remedy pivoting characters on spawn with this little trick:

task.defer(workspace.PivotTo, Character, CFrame)

If that doesn’t work, you could try waiting an extremely short amount of time with this hack:

script:WaitForChild("\0", 0.000001)

I’ve genuinely considered rewriting character spawning just because of how awful the engine treats it.

I tried these two workarounds before. I will try again if @index_self’s workarounds does not work.

EDIT
The problem is also figuring out if it still happens, as it is very inconsistent.

Hi, when I refer to sanity checks I meant the code is part of a bigger game logic. Sorry for the confusion, it was unrelated to the CFrames not being reliable.

Could you please explain how both workarounds work, I don’t quite understand. And is this on the server?

No worries! That makes sense now. But I truly think the best way to handle this if you want consistent results is to just move the character via the client. Is there any reason you wanna do it by the server? The only method that might work with the server is temporarily setting the network ownership of the player character’s primary to nil, but I’m not sure if that even works, and it’s sorta hacky.

Thanks for the report! We’ll follow up when we have an update for you.