Hello im working on a aiming system with the character.
but there is one problem the upper the torso and arms look up a little bit when i look a certain direction can anyone help me fix this issue
Edit: i think it has something to do with
the waist
function GunModule:Aim(Aiming)
if Aiming then
AimRemote:FireServer("AimIn")
MobileCameraFramework.ToggleShiftLock(self.Player, true)
if self.AimingAnimation then
self.AimingAnimation:Play()
self.AimingAnimation.KeyframeReached:Connect(function(keyframe)
if keyframe == "CanShoot" then
self.CanShoot = true
end
end)
end
-- Start/replace RenderStepped loop
if self.AimConnection then
self.AimConnection:Disconnect()
end
self.AimConnection = RunService.RenderStepped:Connect(function()
-- If gun is no longer equipped or valid, just exit — but DO NOT reset C0s here
if not self.Equipped then
if self.AimConnection then
self.AimConnection:Disconnect()
self.AimConnection = nil
end
return
end
-- Still update aim even if animation stopped
local camLook = workspace.CurrentCamera.CFrame.LookVector
local pitch = math.asin(camLook.Y) / 2
local pitchOffset = 0.1
local adjustedPitch = pitch + pitchOffset
local hrp = self.HMR or self.Character:FindFirstChild("HumanoidRootPart")
local hrpCF = hrp and hrp.CFrame or CFrame.new()
local _, camYaw, _ = hrpCF.Rotation:ToEulerAnglesYXZ()
local D = (hrpCF * CFrame.Angles(0, math.pi / 2, 0)).LookVector:Dot(camLook)
local waistAnimTransform = self.Character.LowerTorso.CFrame * self.Waist.C1
local animPitch, animYaw, animRoll = waistAnimTransform:ToEulerAnglesYXZ()
local cancelAnimRotation = CFrame.Angles(-animPitch, -animYaw, -animRoll)
local finalRotation = cancelAnimRotation * CFrame.Angles(0, camYaw, 0) * CFrame.Angles(adjustedPitch, 0, 0)
local desiredWaistWorld = self.Character.LowerTorso.CFrame * finalRotation * self.WCFRAME
local adjustedWaistC0 = self.Character.LowerTorso.CFrame:ToObjectSpace(desiredWaistWorld)
local adjustedRootC0 = self.Root.C0
local neckC0 = CFrame.new(self.Neck.C0.Position) * CFrame.Angles(adjustedPitch, -D / 4, -D / 4)
local rightArmC0 = CFrame.new(self.RightArm.C0.Position) * CFrame.Angles(adjustedPitch, 0, 0)
local leftArmC0 = CFrame.new(self.LeftArm.C0.Position) * CFrame.Angles(adjustedPitch, 0, 0)
self.Neck.C0 = neckC0
self.LeftArm.C0 = leftArmC0
self.RightArm.C0 = rightArmC0
self.Waist.C0 = adjustedWaistC0
self.Root.C0 = adjustedRootC0
UpdateMotorC0:FireServer({
Neck = neckC0,
LeftArm = leftArmC0,
RightArm = rightArmC0,
Waist = adjustedWaistC0,
Root = adjustedRootC0
})
end)
else
-- Disable shooting, shift lock, and disconnect loop
self.CanShoot = false
AimRemote:FireServer("AimOut")
MobileCameraFramework.ToggleShiftLock(self.Player, false)
if self.AimConnection then
self.AimConnection:Disconnect()
self.AimConnection = nil
end
-- âś… Always reset C0s here, not in the loop
if self.Waist then self.Waist.C0 = self.WCFRAME end
if self.Neck then self.Neck.C0 = self.NCFRAME end
if self.LeftArm then self.LeftArm.C0 = self.LACFRAME end
if self.RightArm then self.RightArm.C0 = self.RACFRAME end
if self.Root then self.Root.C0 = self.RCFRAME end
UpdateMotorC0:FireServer({
Neck = self.Neck.C0,
LeftArm = self.LeftArm.C0,
RightArm = self.RightArm.C0,
Waist = self.Waist.C0,
Root = self.Root.C0
})
end
end
i see, i think this has to do with how funky rotation is in places like roblox
is using CFrame.lookAt with the mouse hit position feasible for what you want to do?
euler angles require rotation order iirc which becomes advanced annoying and hard to deal with
so this is the problem?
local animPitch, animYaw, animRoll = waistAnimTransform:ToEulerAnglesYXZ()
local cancelAnimRotation = CFrame.fromOrientation(-animPitch, -animYaw, -animRoll)
“You know the YXZ and XYZ order thing.” and what about that?
Oh for this I never use CFrame.Angles ever again for this reason, angles is XYZ order CFrame.fromOrientation is YXZ order they will generate different end results given the same 3 angles.
Your aim is using pitch math.asin, which is not going to be normalized based off where your root part’s euler angles will update to. So that means your pitch will be based off the relative direction of euler angles world space, not the relative direction of your root part.
You have to normalize the pitch to the root part:
local function GetNormalizedPitch(cameraCFrame, characterCFrame)
local relativeLookVector = characterCFrame:ToObjectSpace(cameraCFrame).LookVector
return math.asin(math.clamp(relativeLookVector.Y, -1, 1))
end
then you apply the normalized pitch to your use-case, and it should no longer bob up and down like a sin wave.
and of course, it will not work unless you adapt normalization to all of your adjacent angle updates. So that includes everything else inside the aim connection, you have to normalize all of your angles to root part’s euler angles object space.
So the solution was not working with the motor it was against it by positioning torso to motor with offset so it stays there
-- Still update aim even if animation stopped
local camLook = workspace.CurrentCamera.CFrame.LookVector
local pitch = math.asin(camLook.Y) / 2
local pitchOffset = 0.04
local adjustedPitch = pitch + pitchOffset -- Apply the pitch offset
local hrp = self.HMR or self.Character:FindFirstChild("HumanoidRootPart")
local hrpCF = hrp and hrp.CFrame or CFrame.new()
-- Get the current camera yaw
local _, camYaw, _ = hrpCF.Rotation:ToEulerAnglesYXZ()
-- Calculate D value for lateral (side) influence based on HRP look vector and camera direction
local D = (hrpCF * CFrame.Angles(0, math.pi / 2, 0)).LookVector:Dot(camLook)
-- Get the waist transform from animation (world space)
local waistAnimTransform = self.Character.LowerTorso.CFrame * self.Waist.C1
-- Extract the position from the animation transform
local animPosition = waistAnimTransform.Position
-- Add the desired offset (0, 0.803, 0)
local offset = Vector3.new(0, 0.803, 0)
local finalPosition = animPosition + offset
-- Construct a CFrame at the same position, but with no rotation
local cancelAnimRotation = CFrame.new(finalPosition)
-- Apply the final CFrame with no rotation
local desiredWaistWorld = cancelAnimRotation * CFrame.Angles(0, camYaw + -0.02, 0) * CFrame.Angles(adjustedPitch, 0, 0)
local adjustedWaistC0 = self.Character.LowerTorso.CFrame:ToObjectSpace(desiredWaistWorld)
local adjustedRootC0 = self.Root.C0 -- Keep the root C0 as it is
-- Adjust the neck, arms, and waist with the calculated rotations
local neckC0 = CFrame.new(self.Neck.C0.Position) * CFrame.Angles(adjustedPitch, -D / 4, -D / 4)
local rightArmC0 = CFrame.new(self.RightArm.C0.Position) * CFrame.Angles(adjustedPitch, 0, 0)
local leftArmC0 = CFrame.new(self.LeftArm.C0.Position) * CFrame.Angles(adjustedPitch, 0, 0)
-- Apply the transformations to the character's body parts
self.Neck.C0 = neckC0
self.LeftArm.C0 = leftArmC0
self.RightArm.C0 = rightArmC0
self.Waist.C0 = adjustedWaistC0
self.Root.C0 = adjustedRootC0