Here’s a quick script I wrote in about 15 minutes and have been trying to polish up for the last 45ish minutes. Note that I’ve never worked with Motor6Ds before, aside from basic rigging so feel free to inform me of anything I might not know.
Script works standalone so just paste it in StarterCharacterScripts in a LocalScript.
Or if you want a video,
Looking on improvement on:
- Repetition
- Variable names
- Normal or micro-optimizations
Here’s the script:
local runService = game:GetService('RunService')
local tweenService = game:GetService('TweenService')
local neck = script.Parent:WaitForChild('Head').Neck :: Motor6D
local humanoidRootPart = script.Parent:WaitForChild('HumanoidRootPart') :: BasePart
local upperTorso = script.Parent:WaitForChild('UpperTorso') :: BasePart
local waist = upperTorso:WaitForChild('Waist') :: Motor6D
local initWaist = waist.C1
local initNeck = neck.C1
local function getCameraIsOutOfBounds(y)
y = math.deg(y)
if math.clamp(y, -90, 90) ~= y then
return true
end
end
runService.RenderStepped:Connect(function()
local cameraRelativeToHRP = humanoidRootPart.CFrame:ToObjectSpace(workspace.CurrentCamera.CFrame):Inverse()
local x,y,z = cameraRelativeToHRP:ToOrientation()
if not getCameraIsOutOfBounds(y) then
local goalNeckC1 = initNeck * CFrame.fromOrientation(cameraRelativeToHRP:ToOrientation())
local halfPoint = goalNeckC1:Lerp(initNeck, 0.75)
local neckPoint = goalNeckC1:Lerp(initNeck, 0.4)
tweenService:Create(waist, TweenInfo.new(0.5), {C1 = CFrame.new(waist.C1.Position) * CFrame.fromOrientation(halfPoint:ToOrientation())}):Play()
tweenService:Create(neck, TweenInfo.new(0.5), {C1 = CFrame.new(neck.C1.Position) * CFrame.fromOrientation(neckPoint:ToOrientation())}):Play()
else
tweenService:Create(waist, TweenInfo.new(0.5), {C1 = initWaist}):Play()
tweenService:Create(neck, TweenInfo.new(0.5), {C1 = initNeck}):Play()
end
end)