Setting CameraType to Custom does not maintain camera zoom distance

Reproduction Steps

  1. Run any empty project in Studio
  2. Move the camera as far away (middle mouse button)
  3. Save the current Camera Cframe (Run this on command bar): a = workspace.Camera.CFrame
  4. Change the camera position/zoom to anything:
  5. Recover the original Camera CFrame: workspace.Camera.CFrame = a
  6. The camera position and angle are recovered, but not the camera distance/zoom:
  7. Change the CameraType to Scriptable and do the same step 5 workspace.Camera.CFrame = a.
    Now the Camera CFrame is completely recovered:
  8. Change the CameraType back to Custom:

Expected Behavior

  1. Changing a Camera CFrame when CameraType is Custom, doesn’t preserve the current Camera zoom/distance (stored in CFrame)
  2. Changing CameraType from Scriptable to Custom will lose the current Camera zoom/distance .

Actual Behavior

  1. When a player leaves the game, I save 2 CFrame for him, in a DataStore: Player and Camera. And when the player re-enters the game, I retrieve these two values:
HumanoidRootPart.CFrame = Param.CFramePlayer -- Player CFrame (Param is the saved data from DS)
wait()
Camera.CameraType = Enum.CameraType.Scriptable -- to allow changing the Camera CFrame
Camera.CFrame = Param.CFrameCamera -- change Camera CFrame
Camera.CameraType = Enum.CameraType.Custom -- back to "Custom" default value to allow default Camera behavior
  1. As I described in the OP, this should work, but unfortunately, Changing CameraType from Scriptable to Custom will lose the current Camera zoom/distance

Issue Area: Engine
Issue Type: Other
Impact: High
Frequency: Constantly

7 Likes

Thanks for the report! We’ve filed a ticket to our internal database and we’ll follow up when we have an update for you.

3 Likes

Just to clarify my bug report, the problem is that I CANNOT RECALL THE EXACT ZOOM OF THE CAMERA after saving the game.

I am saving the player position/orientation (CFrame) and the camera position/orientation/zoom (also CFrame) in the DataStore when the player exits the game.
When the player returns to the game, I can recover everything EXCEPT the zoom.

After almost 1 YEAR, this problem STILL HAS NOT BEEN FIXED.
I repeat, I need to save the CFrame and Zoom of the camera, but this bug prevents me from saving the Zoom.

1 Like

I guess I can reproduce this, but here’s some additional details about the camera documentation you might find useful:

I’m unsure about the documentation for this, but there’s a function called Camera:GetRenderCFrame() which is for getting the actual CFrame of the camera, specifically for VR enabled devices (with HeadLocked disabled), but it might work for your case.


Actually, now that I see this, I believe this is intentional behavior. This is probably for compatibility with custom camera systems which require the Roblox camera module for zooming.

But what I don’t understand is why when sitting in a VehicleSeat, the VehicleSeat changes the camera type to a certain mode, but when changing it back to Custom the mode disappears. This is probably unrelated, but I thought I’d put it out there (since it is a new feature that relies on the technology listed above, but as described here, has a few bugs).


Anyways,

I believe that the internal Roblox CameraModule does not rely on changing the Camera CFrame directly, as that would be slower. Instead, it probably caches the CFrame into a variable which isn’t updated (but I can’t be sure). This variable is not changed or updated in the Scriptable CameraType, since that one is not managed by the CameraModule.

So, this makes the Fixed camera type a possibility, since it’s managed by the CameraModule. However, in some cases, this didn’t work for me and I’m not sure why (probably because I don’t know any other notable differences between this and the Scriptable CameraType`, so this might not work for you either, but it’s worth a try).

Just FYI this post is very poorly titled and might lead to it being overlooked in search and in internal systems because it’s not immediately clear what’s wrong at a glance of the title. Maybe you can ask mods to retitle it to something specifically about “Setting CameraType to Custom does not maintain camera zoom distance”.

2 Likes

The title is the final diagnosis of the problem.
Even so, the bug has been open for 1 year.
If changing the title would help fix the bug faster, I would put something more appealing there.

1 Like

More than 1 year and nothing so far.

With the current bug, I can’t save the current camera zoom!

1 Like

Isn’t this the intended behavior?

If this became the behavior, each time the camera was set to custom the cframe would also need to be calculated and set. (So the zoom distance isn’t just the distance between the scriptable camera and the character.)

Additionally, what even is the zoom distance of a scriptable camera? Obviously if the scriptable camera is looking at a humanoid it seems very clear, but more generally what would that be in other cases? If it were always the distance to the subject then the problem above would be very significant.

This change would break a lot of games with no significant return.

A better request might be to have a function to set the zoom of the custom controller in the module (or built into the API). Currently it’s quite complicated and undocumented.

I think a more descriptive title would be something like “Setting the custom camera’s CFrame does not change the zoom distance”, because you can quite easily save the camera’s zoom distance as a number.

How are engineers meant to find this if your title has nothing to do with the actual problem?

If you’re interested in doing this without forking the camera module, you can require the modules that make up the camera and control the camera using the functions in those modules. The zoom is stored internally and controlled by a spring-like interpolator (to make zoom changes smooth). I did that in one of my projects but I forgot the specific functions.

You must read before write:

1 Like

I think you might not understand my post.

You are completely able to save the CFrame the camera is in:

This means the CFrame stored is the CFrame that you tried to save, so there is no problem saving the CFrame.

Your problem is that setting the CFrame of the camera while the camera is set to custom only uses the direction of the CFrame, not it’s position relative to the character.

tl;dr:
You might need to re-read my post. Your problem has nothing to do with saving the CFrame or zoom: your problem is trying to restore the camera zoom with a CFrame or zoom distance.

Edit:

Here is a picture to explain the problem with the behavior you expect/want:

The top comparison is the behavior you describe in your post. The bottom shows how that would break existing games. (For example, games with cut scenes or title screens would break.) Changing behavior like this would break games that only use the direction of the CFrame when setting the camera direction (ex: workspace.CurrentCamera.CFrame = CFrame.Angles(0, math.rad(90), 0) sets the camera direction but doesn’t work with your desired behavior).

Do you have a real solution for this bug, or are you only questioning the title?

1 Like

It’s not a bug. It’s the intended behavior for a logical reason.

I do actually have a solution, it’s in my first reply:

Either do that, fork the camera module, or make a new camera controller.

Edit:
You can also set the max zoom distance and the min zoom distance to the same values then return them to their regular values (on the client) to set the zoom. That’s interpolated/smoothed out though.

@rogeriodec_games here is an example with code:

(Notice how it’s smoothed out. If it can’t be smoothed out for your use case you’ll need to use one of the other options.)

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

local player = Players.LocalPlayer
local camera = Workspace.CurrentCamera

local function setZoomDistance(zoomDistance)
	local oldMin = player.CameraMinZoomDistance
	local oldMax = player.CameraMaxZoomDistance
	
	player.CameraMinZoomDistance = zoomDistance
	player.CameraMaxZoomDistance = zoomDistance
	
	player.CameraMinZoomDistance = oldMin
	player.CameraMaxZoomDistance = oldMax
end

local function setCameraCFrame(cframe)
	if camera.CameraType == Enum.CameraType.Custom then
		local zoomDistance = (cframe.Position - camera.Focus.Position).Magnitude
		
		camera.CFrame = cframe
		setZoomDistance(zoomDistance)
	end
end

while task.wait(1) do
	local randomCFrame = CFrame.Angles(0, math.rad(math.random() * 360), 0)
	
	local randomZoom = math.random(1, 100)
	randomCFrame -= randomCFrame.LookVector * randomZoom
	
	setCameraCFrame(randomCFrame)
end

I appreciate your effort and interest in crafting such elaborate responses to try to help. Yesterday I was very busy, so I couldn’t give you enough attention, I apologize.
This post is old and until today I couldn’t solve the problem.

Ironically, until yesterday the title was different: “CameraType.Custom changes the current Camera.CFrame”. But following @buildthomas’s suggestion, yesterday I switched to a more appealing title, precisely to call the engineers’ attention to correct this problem that has existed for almost 2 years; but looking at your comments, I realized that the new title generated more confusion than attention from the Roblox team. So today I requested the title change again, this time literally following @buildthomas’ suggestion.

On review, the original situation is as follows:

  1. When a player leaves the game, I save 2 CFrame for him, in a DataStore: Player and Camera. And when the player re-enters the game, I retrieve these two values:
HumanoidRootPart.CFrame = Param.CFramePlayer -- Player CFrame (Param is the saved data from DS)
wait()
Camera.CameraType = Enum.CameraType.Scriptable -- to allow changing the Camera CFrame
Camera.CFrame = Param.CFrameCamera -- change Camera CFrame
Camera.CameraType = Enum.CameraType.Custom -- back to "Custom" default value to allow default Camera behavior
  1. As I described in the OP, this should work, but unfortunately, Changing CameraType from Scriptable to Custom will lose the current Camera zoom/distance

Despite everything you wrote, I really couldn’t understand if there is a solution to this simple situation.

PS: I edited the OP to put the information above; maybe this will help make it clearer.

2 Likes

I thank to @BendsSpace, who sent me a script in PM, which I was able to adapt to solve the problem:

HumanoidRootPart.CFrame = Param.CFramePlayer -- retrieves the player position 
wait() -- to allow CameraType manipulation

-- change the camera's CFrame
Camera.CameraType = Enum.CameraType.Scriptable -- to allow switching camera CFrame
local ZoomDistance = (Param.CFrameCamera.Position - Camera.Focus.Position).Magnitude -- saves the Zoom distance
Camera.CFrame = Param.CFrameCamera -- retrieves camera position

-- recovers the zoom (which is lost when you return the camera to "Custom")
local OldZoomMin = Player.CameraMinZoomDistance
local OldZoomMax = Player.CameraMaxZoomDistance
Player.CameraMinZoomDistance = ZoomDistance
Player.CameraMaxZoomDistance = ZoomDistance
Player.CameraMinZoomDistance = OldZoomMin
Player.CameraMaxZoomDistance = OldZoomMax

-- fall back to camera default
Camera.CameraType = Enum.CameraType.Custom 

Since Roblox engineers ignore this thread and since I got the solution, I am closing this bug report.

3 Likes

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