Client replicate Motor6D offset to server

I’m trying to change the offset of a motor6d in the player’s character (motor6d.C1) to make a character’s head turn towards the camera and other effects, but my changes are only appearing on the client. I’m trying to find a smooth way to replicate these changes to the server.

Here’s basically all there is to my client script:
joint.C1 = jointGoal
It works fine, but it just isn’t replicated to the server.

I’ve tried using RemoteEvents and tweening the motor’s C1 value from there, but as the joint tweens, the joint on the client starts spazzing out because both are trying to edit the joint’s offset.

(it’s hard to see because of the low recording framerate, but the character is definitely jittery)

I also can’t just change this from the server because the effect is then delayed on the client. Another issue with remote events is that I can’t fire it too fast or I will get a spam error, meaning it won’t be as smooth.

If anyone has any ideas please let me know!

2 Likes

Oh I had the exact same issue with my mech’s turret system. The fix is actually quite simple though it may be quite a hack. I locally cloned the Motor6D and disabled the server one to avoid the conflict.

function TurretController:EnableLocalControl()
	if self.LookAtConnection then
		self.LookAtConnection:Disconnect()
	end

	if not self.LocalControl then
		self.ServerJointMotor6D = self.JointMotor6D
		local originalTurretMotor = self.JointMotor6D
		originalTurretMotor.Enabled = false
		local turretMotorClone = self.JointMotor6D:Clone()
		turretMotorClone.Enabled = true
		turretMotorClone.Parent = originalTurretMotor.Parent
		self.JointMotor6D = turretMotorClone
		self.LocalControl = true
	else
		--warn("Local control already enabled")
	end
end

function TurretController:DisableLocalControl()
	if 	self.LocalControl then
		self.JointMotor6D:Destroy()
		self.ServerJointMotor6D.Enabled = true
		self.JointMotor6D = self.ServerJointMotor6D
		self.LocalControl = false
	else
		warn("Local control already disabled")
	end
end
--send the correct Motor6D to be tweened, and the current local jointMotor6D C0
function TurretController:GetLocalC0Orientation()
	if self.ServerJointMotor6D and self.LocalControl then
		return self.ServerJointMotor6D, self.JointMotor6D.C0:ToOrientation()
	end
end

Edit: If you are confused if self and tables you can replace it with local variables like the below code

No self here just variables to store the motor6D instances
--in the client script
local neckJoint : Motor6D = --path to neck joint in character
local serverNeckJoint = neckJoint --store it in another variable
serverNeckJoint .Enabled = false -- disable the server neck joint
neckJoint = neckJoint:Clone() -- clone it locally
neckJoint .Enabled = true -- enable it
neckJoint.Parent = serverNeckJoint .Parent -- reparent it

Also here is a better video showcasing the issue for anyone else watching, incoming replication lag is set to 0.5 to really show the client-server delay causing the “jitter”.

8 Likes

Thank you, it replicates to the server perfectly!

Hi, I need help with the same issue, but I don’t get what “self” is referring to in the code, alongside the colon in the function naming. Could you please explain?

Self is lua syntax/keyword to get variables in a table if the function is also “inside” that table.

The variables in this case is just the current Motor6D Joint being used by the script to do movement stuff self.JointMotor6D and the server instance of the motor6D self.ServerJointMotor6D that is being disabled and put away.

Check it out more in-depth in this post:

2 Likes

How to use it! I’m having the same problem!
you can get an example by rotating the character’s head with RunService

You can prolly just replace the self with a variable like so.

--in the client script
local neckJoint : Motor6D = --path to neck joint in character
local serverNeckJoint = neckJoint --store it in another variable
serverNeckJoint .Enabled = false -- disable the server neck joint
neckJoint = neckJoint:Clone() -- clone it locally
neckJoint .Enabled = true -- enable it
neckJoint.Parent = serverNeckJoint .Parent -- reparent it

--feel free to use neckJoint to do runservice CFrame stuff locally
2 Likes

does this give client network ownership over motor6d.
Does it replicate to server?

No,

Network ownership only apply to physics so position, velocity, and angular velocity.

Not for properties such as C0 of Motor6D.

In that case, I will just cry.

Do you know any way to get around this?

:frowning:
I will just use a workaround I came up with.

I’m having a similar predicament to the creator of this thread, it’s just that I’m trying to make a gun have a visual recoil when shooting, which is visible to other players in the server. I also need to orient the arms of the user so that the gun looks more appropriately held.

I tried using your method (creating local joint via cloning original joint, disabling original joint), but nothing different seems to happen and the joint still doesn’t replicate. I’m testing it one of my character’s joints by the way.

I ran this in the client through the Command Bar:

local neckJoint = workspace.IxGamerXL.Torso["Right Hip"]
local serverNeckJoint = neckJoint
serverNeckJoint.Enabled = false
neckJoint = neckJoint:Clone()
neckJoint.Enabled = true
neckJoint.Parent = serverNeckJoint.Parent
neckJoint.Name = "Local Joint"

I then edited the local joint from the client, but nothing happened on the server.

Does this work on all types of joints, or what specific conditions need to be met? Or is the way I’m doing this just not correct?

His method apparently doesn’t replicate. It just makes it smooth on one client.

If i were you I would do what roblox does.

Fire a remote event every 1/10 of a second and interpolate between the changes that occurred.

Then if it doesn’t replicate, then there’s one script that might, and without a jittery effect.

I’ve seen the Grab Knife script plenty of times, and usually gets used by exploiters, which means it is a local script. I also point this script out in particular because it includes seemingly perfect control over the user’s character Motor6Ds. It also seems to continue being FE supported, so whatever it did back then should still be the same or similar to what it does now.

If I’m correct and the script controls the rig using a method I can work with, we likely have a true answer for this problem.

I’m going to check for any places the script can be at, and if I find one with a good method, I’ll try to salvage and place the working method here.

I would assume that the people doing that just manually set the position of their arms. That would replicate. I guess the best answer might be to not even use motor6ds.

it dont work, can i delete the server one?

hello, may I ask if you make a motor6d.transform or are you changing it’s c0?

I er, quit programming and am not equipped to answer this question anymore.