Why won't it let me move my camera?

https://developer.roblox.com/en-us/api-reference/property/Camera/FieldOfView

The offset is because since i made the local transprency modifier of the body 0 regarding accessories the top of the Upper torso is visible if you look straight down. So i added an offset to make it look down from upper torso to lower torso

I think I understand what they’re trying to do: make the limbs visible, but make it so you can’t glitch through the limbs and all that, realistically “offsetting” it

1 Like

Im trying to make a camera like the one in JUDY or any other horror game thats relaistic

Never played JUDY but I think I have an idea on what you’re looking for.

This requires a decent understanding of CFrames.

Let me explain my thought process:

First for this custom camera, to make the player able to look around, we need to use their mouse position somehow.

We can use UserInputService:GetMouseDelta() to detect changes in the mouse position, and add that to a stored variable (even if the change is negative, 5 + (-5) = 0, just like 5-5 = 0, so all we need to do is add)

From there we can create angles using those positions relative to the screen, by using some sort of multiplier like 0.15 on Delta.X here. It won’t matter how large their screen is, because we’re using GetMouseDelta, so as long as they keep moving their mouse positive or negative, the value will be adjusted accordingly.

Using those angles we can then multiply that from the character’s root part, and use an offset to get their head position. We don’t want to use the head itself because that could look weird while moving, although you can change the code for your own needs.

local Player = game.Players.LocalPlayer
local Char = Player.Character or Player.CharacterAdded:Wait()

local UIS = game:GetService("UserInputService")

local X, Y, AngleX, AngleY = 0,0, CFrame.Angles(0,0,0), CFrame.Angles(0,0,0) -- Base values 

local Camera = workspace.CurrentCamera

local Offset = CFrame.new(0, 2, -1) -- You might want to change this to suit your game better 

function Update()
	UIS.MouseBehavior = Enum.MouseBehavior.LockCenter
	Camera.CameraType = Enum.CameraType.Scriptable 
	local Delta = UIS:GetMouseDelta() -- Get change in mouse position 

	X = X + (Delta.X*0.15) -- Set X value accordingly (mouse left/right)
	Y = math.clamp(Y + (Delta.Y*0.15),-89.99,89.99) -- Set value Y value accordingly (mouse up/down, clamped to prevent glitch where camera rotates at 90) 

	AngleX = CFrame.Angles(0, math.rad(-X), 0) -- Create angles using X on Y 
	AngleY = CFrame.Angles(math.rad(-Y),0,0) -- Create angles using Y on X 

	Camera.CFrame = CFrame.new((Char.HumanoidRootPart.CFrame).p)* AngleX * Offset * AngleY
end


game:GetService("RunService"):BindToRenderStep("Update",Enum.RenderPriority.Camera.Value, Update) -- Use BindToRenderStep so it updates compared to Roblox's default camera 

And here is the end result:

So remember to plan.

If it doesn’t work or you have any questions please let me know!

1 Like

Wow! It works all i had to change is a few variables and the humanoidRootPart to head because of what i wanted initially; but when i turn the body doesn’t turn with it. Anyway to fix that?

The thing about Roblox math and me is that i know a lot of math! Unfortunately i don’t know how to put it all together, like how i should use this or where i should put that.

1 Like

Sure, we can simply add some code to make the player turn towards the direction of the camera. To make a part look at another part we simply do CFrame.new(Origin, LookAt), but here we need to limit the rotation to the Y axis only, because we want the player’s body to rotate side to side only, not rotate all over the place!

So first we set a variable GoalRotate to equal CFrame.new(Origin, LookAt), in this case the origin being the HumanoidRootPart’s position, and the LookAt to the Camera’s position. Now to get the Y orientation value of the GoalRotate, we use GoalRotate:ToOrientation() on it.

The reason we do local _, RotY, _ = GoalRotate:ToOrientation() is because the function returns the X,Y, and Z values, and we only want the Y orientation value.

With this Y orientation value, we can then use CFrame.fromOrientation() to construct a new CFrame with just that Y orientation value while setting the X and Z to 0. Sorry if I’m bad at explaining this.

The code would look like this:

local Position = Char.HumanoidRootPart.CFrame.p 
local GoalRotate = CFrame.new(Position, Camera.CFrame.Position)
local _, RotY, _= GoalRotate:ToOrientation()
	
Char.HumanoidRootPart.CFrame = CFrame.new(Position) * CFrame.fromOrientation(0, RotY, 0)

And this would be ran after setting the Camera.CFrame

So for example in my script I made earlier it would be like this:

local Player = game.Players.LocalPlayer
local Char = Player.Character or Player.CharacterAdded:Wait()

local UIS = game:GetService("UserInputService")

local X, Y, AngleX, AngleY = 0,0, CFrame.Angles(0,0,0), CFrame.Angles(0,0,0) -- Base values 

local Camera = workspace.CurrentCamera

local Offset = CFrame.new(0, 2, -1) -- You might want to change this to suit your game better 

function Update()
	UIS.MouseBehavior = Enum.MouseBehavior.LockCenter
	Camera.CameraType = Enum.CameraType.Scriptable 
	local Delta = UIS:GetMouseDelta() -- Get change in mouse position 

	X = X + (Delta.X*0.15) -- Set X value accordingly (mouse left/right)
	Y = math.clamp(Y + (Delta.Y*0.15),-89.99,89.99) -- Set value Y value accordingly (mouse up/down, clamped to prevent glitch where camera rotates at 90) 

	AngleX = CFrame.Angles(0, math.rad(-X), 0) -- Create angles using X on Y 
	AngleY = CFrame.Angles(math.rad(-Y),0,0) -- Create angles using Y on X 

	Camera.CFrame = CFrame.new((Char.HumanoidRootPart.CFrame).p)* AngleX * Offset * AngleY

	local Position = Char.HumanoidRootPart.CFrame.p -- Set to the root part's position 
	local GoalRotate = CFrame.new(Position, Camera.CFrame.Position) -- Faces the camera from the root part's position 
	local _, RotY, _= GoalRotate:ToOrientation() -- Stores the Y orientation value, which we will then use in CFrame.fromOrientation to set the X and Z to 0, limiting it to Y (rotating side to side)  
	
	Char.HumanoidRootPart.CFrame = CFrame.new(Position) * CFrame.fromOrientation(0, RotY, 0) 
end


game:GetService("RunService"):BindToRenderStep("Update",Enum.RenderPriority.Camera.Value, Update) -- Use BindToRenderStep so it updates compared to Roblox's default camera 

Hopefully this helps!

1 Like

for the RotY variable why did you put ,RotY, ?

It works! but when my cartoony animation plays one of the idle animations it glitched but then fixes back why does that happen? Sorry if its taking too much of your time

Ah yeah I understand that looks confusing so I explained it here

The reason we do local _, RotY, _ = GoalRotate:ToOrientation() is because the function returns the X,Y, and Z values, and we only want the Y orientation value.

Basically you can try this on your own function as well

local function ReturnThreeValues()
    return 1,2,3
end 

local One, Two, Three = ReturnThreeValues()
print(One) -- 1 
print(Two) -- 2
print(Three) -- 3 

So if we only wanted Three (3), we could do

local _, _, Three = ReturnThreeValues()
print(Three) -- 3 

Or if we only wanted One (1), we could do

local One, _, _ = ReturnThreeValues()
print(One) -- 1

“_” is basically a placeholder that replaces variables you won’t use, which is thought to be more organized as you’re only storing variables you need, and could be 0.0001% better for performance

I’m not sure, I would have to see the animation and things like that. Can you send a video?

Ohhhhh so it returns 3 values and you need only 1 just making a random character as placeholders?

Yeah pretty much, helps to stay organized in my opinion, but if you wanted to you could do

local RotX, RotY, RotZ = GoalRotate:ToOrientation() 

even if you’re just using RotY, and that’s totally fine as well.

I have an idea: because the origin of the camera system uses the HumanoidRootPart, and animations never move it. So if your animation moves the character’s limbs around a lot it could cause lots of clipping, or if you move the LowerTorso it would cause the player to move away from the camera, etc.

There are a few ways to prevent this but unfortunately I am running out of time right now. If you still haven’t marked a solution later, maybe tomorrow, if I have the time I could help. What I am thinking of is either using the head as the origin and limiting the axis with :ToOrientation() and .fromOrientation(), or changing the character offset based on animations (limb transformations).

Glad I could help you fix most of your camera issues though, good luck :smiley:

Yes i will try to find a way to limit the rotation on Y so they wont look directly down, thank for your help! Still a few things i don’t understand but if i don’t find a solution until tomorrow ill @ you.

Turns out that i was mistaken, it glitches when I look up and down but I want the players to be able to look directly up

@Luacrative When i swam in the water it didnt look right so i tried fixing it using this:

humanoid.StateChanged:Connect(function(old, new)
		local x, y, z = camera.CFrame:ToEulerAnglesXYZ()
		if new == Enum.HumanoidStateType.Swimming then
			character.HumanoidRootPart.CFrame = camera.CFrame:ToWorldSpace() * CFrame.Angles(0, math.deg(y) * math.rad(45), 0)
		end
	end)

but it doesnt work :frowning: