Is it client sided? Does it use RenderStepped, Stepped, Heartbeat or what?
it doesnt use any of them, again all it does, is set the cameraOffset, and the cameraMode to LockFirstPerson
It’s likely Roblox’s issue. I’ve had the same problem with CameraOffset and can’t do anything to fix it.
well yeah I assumed as much, just hoped I could find a way to fix it
You need to Lerp from one orientation to another over multiple frames. Every time you move your mouse right now your character instantly faces it
The camera will move exponentially faster the farther you offset it from the character. I think because of this, the camera is moving around so quickly that it looks choppy. You might be able to fix it by lowering the players mouse sensitivity when they get put in 3rd person. Check out this post that did it.
It helps, but the screen is still jittering some.
Wouldnt this require custom coding the camera? AKA setting the CameraType to scriptable
A coincidence that I just had a post including this script. Note that this is me taking the core parts of my script and removing all the extras, so it may not be fully functional and the indents are goofy, but you should be able to get some inspiration on how a custom system would work.
local RunService = game:GetService("RunService")
camera.CameraType = Enum.CameraType.Scriptable
local cameraSensitivity = 0.3
cameraOffset = Vector3.new(1.3, 2, 10)
local player = game.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
--Update the camera every frame
local function updateCamera()
--Get the player's mouse values
local delta = UserInputService:GetMouseDelta()
cameraRotationX = cameraRotationX - delta.Y * cameraSensitivity
cameraRotationY = cameraRotationY - delta.X * cameraSensitivity
cameraRotationX = math.clamp(cameraRotationX, -45, 45)
--Rotate the HRP
local targetPart = thePartYouWantToRotateAround (usually the humanoidrootpart)
if targetPart then
targetPart.CFrame = CFrame.new(targetPart.Position) * CFrame.Angles(0,math.rad(cameraRotationY),0)
end
--Calculate the new camera position and rotation
local desiredCameraCFrame = CFrame.new(targetPart.Position)
* CFrame.Angles(0, math.rad(cameraRotationY), 0)
* CFrame.Angles(math.rad(cameraRotationX), 0, 0)
* CFrame.new(cameraOffset)
--Adjust the camera
camera.CFrame = desiredCameraCFrame
end
--Loop call
RunService.RenderStepped:Connect(updateCamera)
--Handle character respawn
local function onCharacterAdded(newCharacter)
camera.CameraSubject = newCharacter:WaitForChild("Humanoid")
character = newCharacter
hrp = character:WaitForChild("HumanoidRootPart")
end
--
player.CharacterAdded:Connect(onCharacterAdded)
Hey so I got most of the code ready to go, my only question is what would cameraRotationX and cameraRotationY be?
Those decide how much the camera should rotate around the X and Y axis.
I’m not sure on the math, but you can see the values are being used when rotating both the targetPart and the camera. It is derived from your mouse’s delta which seems to be some sort of pre-frame calculation that the engine does, and of course the sensitivity which is multiplied on the rotation value so that makes sense: higher sensitivity = more rotation when it’s multiplied on the rotation calculation.
Edit: and as you can see you also need to have mouselockcenter on.
This causes the camera to go through objects, so you’ll need a raycast to create a hitbox for the camera, which is what I’m using. The good news is that this also allows you to block parts you’d normally be able to see through like non-collidable parts.
Ok so incase I was like struggling to figure out what all of that meant, could you explain this in very simple terms?
Ooo that sounds like fun to make lol
I don’t understand the math fully. It’s not needed, but useful yes.
I consider it enough to understand the steps to the script and what each variable is used for, so that this;
cameraRotationX = cameraRotationX - delta.Y * cameraSensitivity
cameraRotationY = cameraRotationY - delta.X * cameraSensitivity
sets the rotation by using the 3 values we know what are. Delta being the movement distance of the mouse and sensitivity being the multiplier like any camera has. Why is it using the “-” operator instead of “+” I cannot tell you, but I’ve decided that it’s not worth it for me to understand all the math.
The latter part is just applying the rotation values of the objects with the CFrame.Angles(). Math.rad() is to translate the values from angles 0-360. It’s using the Y rotation here because for some reason when you rotate a character the Y value is the horizontal rotation value, which is what we need to change on the humanoidrootpart.
if targetPart then
targetPart.CFrame = CFrame.new(targetPart.Position) * CFrame.Angles(0,math.rad(cameraRotationY),0)
end
Oh wait I see, ok so I wasnt worried about what the math was doing, more of um:
yeah you reference this here and subtract delta.Y from it:
But its never defined, so like what should it be?
This is indeed defined as 0 at the top of the script yes. Forgot to include it.
-- Variables to keep track of camera angles
local cameraRotationX = 0
local cameraRotationY = 0
Well the cameras smoother. New problem, the camera doesnt move any more
From looking at it the post, this requires setting the CameraType to scriptable, which I kinda, dont want to do, so this will be my last resort
Do you not have the cameratype as scriptable right now?
It should be, because else it can’t be positioned by script.
Other than that you can print the humaoidrootpart’s parent and camera.CameraSubject
to make sure your script is handling the correct object.
Yeah uh . . . .
Anyhow from attempting to do what you said, I created this, which doesnt work, and honestly dont know what im doing at this point lol
local RunService = game:GetService("RunService")
local UserInputService = game:GetService('UserInputService')
local camera = workspace.CurrentCamera
camera.CameraType = Enum.CameraType.Scriptable
local cameraSensitivity = 0.3
cameraOffset = Vector3.new(1.3, 2, 10)
local player = game.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local hrp = character:FindFirstChild('HumanoidRootPart')
--Update the camera every frame
local function updateCamera()
--Get the player's mouse values
local delta = UserInputService:GetMouseDelta()
local cameraRotationX = 0
local cameraRotationY = 0
cameraRotationX = cameraRotationX - delta.Y * cameraSensitivity
cameraRotationY = cameraRotationY - delta.X * cameraSensitivity
cameraRotationX = math.clamp(cameraRotationX, -45, 45)
--Rotate the HRP
local targetPart = hrp
camera.CameraSubject = targetPart
if targetPart then
targetPart.CFrame = CFrame.new(targetPart.Position) * CFrame.Angles(0,math.rad(cameraRotationY),0)
end
--Calculate the new camera position and rotation
local desiredCameraCFrame = CFrame.new(targetPart.Position)
* CFrame.Angles(0, math.rad(cameraRotationY), 0)
* CFrame.Angles(math.rad(cameraRotationX), 0, 0)
* CFrame.new(cameraOffset)
--Adjust the camera
camera.CFrame = desiredCameraCFrame
end
--Loop call
RunService.RenderStepped:Connect(updateCamera)
--Handle character respawn
local function onCharacterAdded(newCharacter)
camera.CameraSubject = newCharacter:WaitForChild("Humanoid")
character = newCharacter
hrp = character:WaitForChild("HumanoidRootPart")
end
--
player.CharacterAdded:Connect(onCharacterAdded)
repeat
camera.CameraType = Enum.CameraType.Scriptable
task.wait()
until camera.CameraType == Enum.CameraType.Scriptable
RunService.RenderStepped:Connect(updateCamera)
yes this should work, so you’ll have to debug by printing. The math is math, so it can’t really be wrong, so it has to be either somewhere else in your project that stops the script from functioning, or some value in the script is not being set to what it should.