Simulate first person behavior while making camera scriptable and changing its CFrame

Hey, everyone.
I’ve been trying to make a first person camera for my fps game, but, when adding crouching, I’ve run into some problems. I want to change the camera’s CFrame but in order to do that, I have to change the camera type to scriptable. Once I do that, the first person behavior goes away.
To attempt to fix this problem, I’ve tried multiple things. What got me the farthest was setting up a renderStepped event when the player crouches.
The problem with this solution is that the camera keeps rotating on its own.
Here’s a video demonstration:

robloxapp-20210906-0848578.wmv (2.7 MB)

Here are scripts related to the problem:

Local script:

game:GetService("RunService").RenderStepped:Connect(function(dt)
    gunModule.update(viewmodel, dt, recoilSpring, bobbleSpring, swayingSpring, gunModel, isAiming)
    player.CameraMode = Enum.CameraMode.LockFirstPerson
    UserSettings():GetService("UserGameSettings").RotationType = Enum.RotationType.CameraRelative
    game:GetService("UserInputService").MouseBehavior = Enum.MouseBehavior.LockCenter
end)

Module script:

local loop
function module.crouch(viewmodel, gun, isCrouching, isSprinting)
	
	workspace.Camera.CameraType = Enum.CameraType.Scriptable --This is the problem. The camera mode can't be scriptable
	
	local crouch = viewmodel.AnimationController:LoadAnimation(game.ReplicatedStorage.Animations.Crouch)
	local hold = viewmodel.AnimationController:LoadAnimation(gun.GunAnims.Hold)
	
	if isCrouching and not isSprinting then
		TweenService:Create(workspace.Camera, TweenInfo.new(0.5, Enum.EasingStyle.Linear), {CFrame = workspace.Camera.CFrame * CFrame.new(0, -2, 0)}):Play()
		task.wait(0.5)
		loop = game:GetService("RunService").Heartbeat:Connect(function()
			workspace.Camera.CFrame = game.Players.LocalPlayer.Character.Head.CFrame * CFrame.new(0, -2, 0)
		end)
	elseif not isCrouching then
		loop:Disconnect()
		TweenService:Create(workspace.Camera, TweenInfo.new(0.5, Enum.EasingStyle.Linear), {CFrame = workspace.Camera.CFrame * CFrame.new(0, 2, 0)}):Play()
		task.wait(0.5)
		workspace.Camera.CameraType = Enum.CameraType.Custom
	end
end

return module

Does anyone know a way that I can get rid of this rotating?

Maybe you could try welding the camera to the player’s head.

I don’t think that would solve the problem, since I want the camera to be 2 studs down from the head, and even welding the camera wouldn’t solve this rotating problem, since it has the same effect has setting the CFrame of the camera

The way you can do it is to simply don’t change it to scriptable.

All you just have to do is keep the camera locked in firstp then Offet the Camera CFrame by a vector.
You will have to use Bind to Render stepped for it to work.

Edit: I did this in literally 1 min

local Camera = workspace.CurrentCamera

local Mouse = game.Players.LocalPlayer:GetMouse()

local RunService = game:GetService("RunService")

Mouse.Button1Down:Connect(function()
	RunService:BindToRenderStep("CrouchCamera",
        Enum.RenderPriority.Camera.Value + 1, -- Priority is set right after the camera updates by the CameraScript
        function()
		Camera.CFrame -= Vector3.new(0,2,0)
	    end
    )
	
end)

Mouse.Button1Up:Connect(function()
	RunService:UnbindFromRenderStep("CrouchCamera")

end)


https://gyazo.com/cebed33d04a272c7425445a5943db859

1 Like

Thanks, it works wonderfully! I just replaced the loop with this code and made some minor adjustments to fit my needs

1 Like