Hi! I am trying to make my character’s arms, tool, and head to rotate to wherever they look, however, the left arm and tool’s rotations do not replicate quite right to other people’s clients. (I use MaximumADHD/CloneTrooper1019’s Realism Library)
For the record, the way my tools work is that they are connected to the torso via a Motor6D called “GunMotor6D” (I used HeadStackk’s animated tools devforum post for that)
Here’s what it looks like Client VS. Local Server:
I tried to mess around with various values and other stuff and such, but nothing really quite worked right.
Here’s the functions, maybe I wrote something incorrectly? If so then let me know and I will try to fix it myself.
The function for updating the Tool + Left arm rotation:
function CharacterRealism:UpdateToolAndArmOrientation(character, pitch, yaw)
if not character then return end
local torso = character:FindFirstChild("Torso")
local tool = character:FindFirstChildWhichIsA("Tool")
local head = character:FindFirstChild("Head")
if not (torso and head) then return end
-- Tool
local toolMotor = torso:FindFirstChild("GunMotor6D")
if tool and toolMotor and toolMotor:IsA("Motor6D") then
local isFirstPerson = (workspace.CurrentCamera.CFrame.Position - head.Position).Magnitude < 1
local adjustedPitch = isFirstPerson and pitch or -pitch
toolMotor.C0 = CFrame.new(toolMotor.C0.Position) * CFrame.Angles(adjustedPitch, 0, 0)
end
-- Left arm
local leftArmMotor = torso:FindFirstChild("Left Shoulder")
if leftArmMotor and leftArmMotor:IsA("Motor6D") then
local defaultC0 = CFrame.new(-1, 0.5, 0)
local defaultRotation = CFrame.Angles(0, math.rad(-90), 0)
local adjustedPitch = -pitch
if (workspace.CurrentCamera.Focus.Position - workspace.CurrentCamera.CFrame.Position).Magnitude > 1 then
adjustedPitch = pitch
end
leftArmMotor.C0 = defaultC0 * defaultRotation * CFrame.Angles(0, 0, adjustedPitch)
end
end
UpdateLookAngles:
function CharacterRealism:UpdateLookAngles(delta)
local pitch, yaw = self:ComputeLookAngle()
self:OnLookReceive(self.Player, pitch, yaw)
local lastUpdate = self.LastUpdate or 0
local now = os.clock()
if (now - lastUpdate) > .5 then
pitch = Util:RoundNearestInterval(pitch, .05)
yaw = Util:RoundNearestInterval(yaw, .05)
if pitch ~= self.Pitch then
self.Pitch = pitch
self.Dirty = true
end
if yaw ~= self.Yaw then
self.Yaw = yaw
self.Dirty = true
end
if self.Dirty then
self.Dirty = false
self.LastUpdate = now
self.SetLookAngles:FireServer(pitch, yaw)
end
end
local playerCharacter = self.Player.Character
if playerCharacter then
self:UpdateToolAndArmOrientation(playerCharacter, pitch, yaw)
end
local camera = workspace.CurrentCamera
local camPos = camera.CFrame.Position
local player = self.Player
local dropList
for character, rotator in pairs(self.Rotators) do
if not character.Parent then
if not dropList then
dropList = {}
end
dropList[character] = true
continue
end
local owner = Players:GetPlayerFromCharacter(character)
local dist = owner and owner:DistanceFromCharacter(camPos) or 0
if owner ~= player and dist > 30 then
continue
end
local lastStep = rotator.LastStep or 0
local stepDelta = now - lastStep
local humanoid = character:FindFirstChildOfClass("Humanoid")
local rootPart = humanoid and humanoid.RootPart
if not rootPart then
continue
end
local pitchState = rotator.Pitch
self:StepValue(pitchState, stepDelta)
local yawState = rotator.Yaw
self:StepValue(yawState, stepDelta)
local motors = rotator.Motors
rotator.LastStep = now
if not motors then
continue
end
for name, factors in pairs(self.RotationFactors) do
local data = motors and motors[name]
if not data then
continue
end
local motor = data.Motor
local origin = data.Origin
if origin then
local part0 = motor.Part0
local setPart0 = origin.Parent
if part0 and part0 ~= setPart0 then
local newOrigin = part0:FindFirstChild(origin.Name)
if newOrigin and newOrigin:IsA("Attachment") then
origin = newOrigin
data.Origin = newOrigin
end
end
origin = origin.CFrame
elseif data.C0 then
origin = data.C0
else
continue
end
local pitch = pitchState.Current or 0
local yaw = yawState.Current or 0
if rotator.SnapFirstPerson and name == "Head" then
if FpsCamera:IsInFirstPerson() then
pitch = pitchState.Goal
yaw = yawState.Goal
end
end
local fPitch = pitch * factors.Pitch
local fYaw = yaw * factors.Yaw
-- HACK: Make the arms rotate with a tool.
if name:sub(-4) == " Arm" or name:sub(-8) == "UpperArm" then
local tool = character:FindFirstChildOfClass("Tool")
if tool and not CollectionService:HasTag(tool, "NoArmRotation") then
if name:sub(1, 5) == "Right" and rootPart:GetRootPart() ~= rootPart then
fPitch = pitch * 1.3
fYaw = yaw * 1.3
else
fYaw = yaw * .8
end
end
end
local dirty = false
if fPitch ~= pitchState.Value then
pitchState.Value = fPitch
dirty = true
end
if fYaw ~= yawState.Value then
yawState.Value = fYaw
dirty = true
end
if dirty then
local rot = origin - origin.Position
local cf = CFrame.Angles(0, fPitch, 0)
* CFrame.Angles(fYaw, 0, 0)
motor.C0 = origin * rot:Inverse() * cf * rot
end
end
end
if dropList then
for character in pairs(dropList) do
local rotator = self.Rotators[character]
local listener = rotator and rotator.Listener
if listener then
listener:Disconnect()
end
self.Rotators[character] = nil
end
end
end