How do I set camera cFrame to a part, and move that part freely?

Hello all!
I am extremely new to scripting but I’m seeing some progress on niche projects, and this has stumped me on how the script would work.

What I wish to achieve is a camera that functions like this:

Game loads, camera starts facing out over a part (like shown)

Player clicks on the button I have set, this tweens the camera to the CFrame of this part (camera angle shown below)

Currently, though, I’m just trying to get the basic script right of setting the player camera to a part. I just need to make this work, then I can tween it around. Here is my current code that doesn’t work:

local Players = game:GetService("Players")
local Workspace = game:GetService("Workspace")

local cameraPart = Workspace:FindFirstChild("Camera_Part_Main")

local function setCameraToPart()
    local player = Players.LocalPlayer
    local camera = Workspace.CurrentCamera

    if cameraPart then
        camera.CFrame = CFrame.new(cameraPart.Position)
    else
        warn("Camera_Part_Main not found in Workspace, did you change the directory?")
    end
end

Players.PlayerAdded:Connect(function(player)
    player.CharacterAdded:Connect(setCameraToPart)
end)

local player = Players.LocalPlayer
if player.Character then
    setCameraToPart()
else
    player.CharacterAdded:Connect(setCameraToPart)
end

The output is spitting out the warning I set, which is saying my Camera_Part_Main cannot be found in workspace. Yes it can! No, but it isn’t locating it, and I checked in the script to make sure I defined it correctly.

I looked for other soloutions, but I couldn’t find anything similar to my issue. Please link me to them if this is a super obvious issue I shouldn’t have, lol.

2 Likes
local cameraPart = Workspace:FindFirstChild("Camera_Part_Main")

Sometimes, your script can run before parts in your game even loads. In this case, your cameraPart becomes nil because it doesn’t exist in Workspace yet, at least it’s when the script started running. You can fix this by using :WaitForChild() to wait for the part to load.

local cameraPart = Workspace:WaitForChild("Camera_Part_Main")

Secondly, you need to set the camera’s CameraType property to ‘Scriptable’ in order to set where will the camera look. You can do so by putting:

camera.CameraType = Enum.CameraType.Scriptable
camera:GetPropertyChangedSignal("CameraType"):Wait()
camera.CameraType = Enum.CameraType.Scriptable

right under the line where you defined camera. This is kinda a hacky way to do it, but it is just in case if Roblox changes the camera’s CameraType after you spawn. I don’t really know the best method to deal with this yet though.

Anyway, after applying these changes, try it and let me know if it works or not!

2 Likes

It didn’t work exactly how I wanted, but I feel like it’s getting somewhere.
It didn’t print any warnings to the console, and set my camera to the default one that starts when you join. Looks like this:


(i’m dancing in the picture but i took it weird so it looks like i’m climbing)

As I said, I’m new, so maybe I applied the changes here wrong in some way? My script is now:

local Players = game:GetService("Players")
local Workspace = game:GetService("Workspace")

local cameraPart = Workspace:WaitForChild("Camera_Part_Main")

local function setCameraToPart()
    local player = Players.LocalPlayer
    local camera = Workspace.CurrentCamera
	camera.CameraType = Enum.CameraType.Scriptable
	camera:GetPropertyChangedSignal("CameraType"):Wait()
	camera.CameraType = Enum.CameraType.Scriptable
	
    if cameraPart then
        camera.CFrame = CFrame.new(cameraPart.Position)
    else
        warn("Camera_Part_Main not found in Workspace, did you change the directory?")
    end
end

Players.PlayerAdded:Connect(function(player)
    player.CharacterAdded:Connect(setCameraToPart)
end)

local player = Players.LocalPlayer
if player.Character then
    setCameraToPart()
else
    player.CharacterAdded:Connect(setCameraToPart)
end
2 Likes

After you hit play, can you go to Workspace.Camera and see if the CameraType is Custom or Scriptable?

1 Like

The CameraType is scriptable, yes.

Also, how do I do the thing you did when you mentioned CameraType that formatted it specially? I just got my forum post privelige today.

1 Like

Oh you just do this: `Hello!` and it will turn into Hello!. This is called codeblock, you can find other formatting features if you click on these buttons here:

image

Anyway, I’m not really sure what’s causing the issue. CameraType is painful to deal with sometimes because Roblox scripts can overwrite them anytime. Can you put a print statement under like this:

And see if it prints anything? If it does print the text and the camera’s CameraType is still custom, then I think it’s because the camera variable is not updated maybe.

1 Like

It’s odd what’s truly happening here. It doesn’t print anything during playing, but the cameratype changes to Scriptable and is stuck in the same general area each load. Code is this now, honestly I wouldn’t put it past me to use print wrong but here’s what it looks like:

local Workspace = game:GetService("Workspace")

local cameraPart = Workspace:WaitForChild("Camera_Part_Main")

local function setCameraToPart()
    local player = Players.LocalPlayer
    local camera = Workspace.CurrentCamera
	camera.CameraType = Enum.CameraType.Scriptable
	camera:GetPropertyChangedSignal("CameraType"):Wait()
	camera.CameraType = Enum.CameraType.Scriptable
	print("CameraType changed successfully")
	
	if cameraPart then
        camera.CFrame = CFrame.new(cameraPart.Position)
    else
        warn("Camera_Part_Main not found in Workspace, did you change the directory?")
    end
end

Players.PlayerAdded:Connect(function(player)
    player.CharacterAdded:Connect(setCameraToPart)
end)

local player = Players.LocalPlayer
if player.Character then
    setCameraToPart()
else
    player.CharacterAdded:Connect(setCameraToPart)
end

1 Like

Sorry late reply, was doing something. The issue right now could be that you are doing:

camera.CFrame = CFrame.new(cameraPart.Position)

Which should instead be

camera.CFrame = cameraPart.CFrame

Also, I think you should replace this code:

local function setCameraToPart()
    local player = Players.LocalPlayer
    local camera = Workspace.CurrentCamera
	camera.CameraType = Enum.CameraType.Scriptable
	camera:GetPropertyChangedSignal("CameraType"):Wait()
	camera.CameraType = Enum.CameraType.Scriptable
	print("CameraType changed successfully")

to:

local function setCameraToPart()
    local player = Players.LocalPlayer
    local camera = Workspace.CurrentCamera
    task.wait(1)
	camera.CameraType = Enum.CameraType.Scriptable

This is a really hacky way (I don’t like this at all) but I’m not sure of other method where it’s more reliable way to set CameraType without being overridden. I think the issue is that camera:GetPropertyChangedSignal("CameraType"):Wait() can often times wait for a ‘change’ in CameraType, which sometime doesn’t happen. I think for now you should try the other version. Let me know if it works!

2 Likes

This was what did it! It was setting the cameratype successfully, but not correctly setting the CFrames to the part I wanted. It makes sense to me now, as the camera was being set at the player spawn. I’ll add a loading screen and that’ll do a bang-up job on the 1 second wait.

What I learned from this is to let your code breathe.

2 Likes

Congrats! Good luck on your project :slight_smile:

2 Likes

Thank you! :slight_smile: I’m reading more around good replay value features. I think my game is rather unorthodox but the platform will benefit from something like it! I also don’t think anyone has tried similar on Roblox (probably because of how daunting the game seems)

3 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.