Issue with Camera Rotating Screenshake

  1. What do you want to achieve?
    I’m trying to create a screenshake effect using tweenservice and camera rotation.

  2. What is the issue?
    Whenever I try to tween the camera’s rotation, it appears to “snap” itself back into
    its original position. How would I tween the rotation without having it snap the position?

3. Example:

Code:

local function offset(rotation,duration)
	local propertieschanged = {
		CFrame = rotation
	}
	local info = TweenInfo.new(duration,Enum.EasingStyle.Linear,Enum.EasingDirection.Out,0,false,0)
	local tween = tweening:Create(cam,info,propertieschanged)
	tween:Play()
end
offset(cam.CFrame * CFrame.Angles(0,-0.02,0),0.05)

(only a small segment of the actual code, but i only included the important bits)

  1. What solutions have you tried so far?
    I’ve attempted to search for solutions regarding this issue, however I struggle with finding anything related to my exact situation or anything I can properly apply to my situation.
1 Like

There’s actually a really well-made module made by Crazyman that does this exact same thing.

Heres the link:

It’s actually very smooth and easy to use. Suggest you take a look :slight_smile:

2 Likes

Hi, thanks for the help and reference to the cool module. However, I’d prefer to find out how to code screenshake myself rather than using a free module :smile:

Thanks anyways, though.

Can you show more of the code please. Especially the loop to make it shake and then the code that follows the loop to reset the cameras CFrame.

delay(0,function()
	local original = cam.CFrame
	offset(cam.CFrame * CFrame.Angles(0,-0.02,0),0.05)
	wait(0.05)
	offset(cam.CFrame * CFrame.Angles(0,0.03,0),0.05)
	wait(0.05)
	offset(cam.CFrame * CFrame.Angles(0,-0.01,0),0.06)
	wait(0.06)
	offset(cam.CFrame * CFrame.Angles(0,0.02,0),0.07)
	wait(0.07)
	offset(cam.CFrame * CFrame.Angles(0,0.02,0),0.05)
	wait(0.05)
	offset(original,0.1)
end)

I also forgot to mention that cam is the variable of the current camera in the workspace.

I would recommend a longer duration on the reset offset function

1 Like

I set the final offset(original,0.1) function call’s duration to 1. It caused the camera to just linger there for a bit.

In my opinion that already looks smoother!

I recommend tweening to the players HRP instead of the cameras old position.
Here’s what that looks like with your code!

delay(0,function()
	offset(cam.CFrame * CFrame.Angles(0,-0.02,0),0.05)
	wait(0.05)
	offset(cam.CFrame * CFrame.Angles(0,0.03,0),0.05)
	wait(0.05)
	offset(cam.CFrame * CFrame.Angles(0,-0.01,0),0.06)
	wait(0.06)
	offset(cam.CFrame * CFrame.Angles(0,0.02,0),0.07)
	wait(0.07)
	offset(cam.CFrame * CFrame.Angles(0,0.02,0),0.05)
	wait(0.05)
	offset(character.HumanoidRootPart.CFrame,1) -- define character
end)

Doing that made it tween weirdly into the character’s torso and then snap back to its normal position.

What do you do with the camera after you call the delay function?

Nothing, the function is just ends from there.

Do you set the cameras subject or focus at all?

Nope, this is completely default. The only other thing that possibly could be related to the camera is that I have the mouse targetfilter set to a folder called “Effects” in the workspace which holds effects. However, this wouldn’t and shouldn’t cause anything.

Alright. I think this is the most “smooth” that you’re going to get this.
However, you could save the Y component of the camera CFrame before the “effect” occurs and then tween to that Y as well as new X and Z after the effect has finished. But that is very hacky and may not result in a smooth effect.

Glad I could help!

1 Like

Thanks for trying to help anyways. This doesn’t really satisfy me as it’s super wonky looking, but thank you.

I can’t tell you exactly why this is happening, seeing as all the other CFrames tween just fine I see no reason why it wouldn’t tween to the original.

After playing with the script a bit, I found that setting the CameraType to Scriptable while the screen is shaking and reverting back to Custom afterwards worked perfectly.

delay(0,function()
	cam.CameraType = Enum.CameraType.Scriptable
	local original = cam.CFrame
	offset(cam.CFrame * CFrame.Angles(0,-0.02,0),0.05)
	wait(0.05)
	offset(cam.CFrame * CFrame.Angles(0,0.03,0),0.05)
	wait(0.05)
	offset(cam.CFrame * CFrame.Angles(0,-0.01,0),0.06)
	wait(0.06)
	offset(cam.CFrame * CFrame.Angles(0,0.02,0),0.07)
	wait(0.07)
	offset(cam.CFrame * CFrame.Angles(0,0.02,0),0.05)
	wait(0.05)
	offset(original,0.1)
	wait(0.1)
	cam.CameraType = Enum.CameraType.Custom
end)

When modifying the camera in any way via scripts, I’d always recommend using the Custom option as this will ensure no other behaviour will affect your desired result.

Hope this helps!

1 Like

I just realised - you should tween the camera back to normal before dropping the player down. I’m pretty sure that will make it smoother.

1 Like

CameraType has to be Scriptable to roll the camera at all. All other modes will internally “correct” the camera to be level with the horizon. The exception is if you use Camera:SetRoll() which uses an additional transform applied after the Camera.CFrame, but this is essentially deprecated so not recommended for new work. Scriptable is the way to go.

2 Likes

Hi! Thanks for trying to help, but when I do this the camera just ends up getting stuck in place again.

delay(0,function()
	cam.CameraType = Enum.CameraType.Scriptable
	local original = cam.CFrame
	offset(cam.CFrame * CFrame.Angles(0,-0.02,0),0.05)
	wait(0.05)
	offset(cam.CFrame * CFrame.Angles(0,0.03,0),0.05)
	wait(0.05)
	offset(cam.CFrame * CFrame.Angles(0,-0.01,0),0.06)
	wait(0.06)
	offset(cam.CFrame * CFrame.Angles(0,0.02,0),0.07)
	wait(0.07)
	offset(cam.CFrame * CFrame.Angles(0,0.02,0),0.05)
	wait(0.05)
	offset(original,0.1)
	delay(0.1,function()
		cam.CameraType = Enum.CameraType.Custom
	end)
end)

Thank you too for trying to help, but this screenshake system won’t be just for this single move. I will have to have a less situational fix.