Do *NOT* remove the CameraModule API?

I recently observed the following change to the CameraModule that Roblox distributes to the StarterPlayerScripts:

https://github.com/CloneTrooper1019/Roblox-Client-Tracker/blob/roblox/scripts/PlayerScripts/StarterPlayerScripts_NewStructure/PlayerModule.module/CameraModule.lua#L548-L555

FFlagUserRemoveTheCameraApi forces the state of the CameraModule to be private instead of allowing for external modification.

To my understanding, the whole point of this system refactor was to avoid having to fork Roblox’s CameraScript to make changes to it, so this change is very unusual.

I know for a fact that one of my games is actively overloading some methods in the camera API so that I can extend its state. My game’s code loads in late so I can’t overload the camera module, and its very hard to get rid of its behavior once its executed.

Admittedly, the current state of the module API seems a bit volatile, but to completely cut off access with no warning or consideration that people might have hooked into it doesn’t seem like a good idea.

(cc @AllYourBlox?)

56 Likes

Can you provide info about what changes to the camera module API you make?

I think originally these functions were not intended to be exposed and when modifying them from outside the CameraModule there is a pretty big chance of something breaking due to future camera changes either when a method is removed or changed.

6 Likes

My alarm was more theoretical than anything else, assuming I’m not the only one who hooked into this module. An entry point was provided for it in the PlayerModule, so I wasn’t under the impression it was unintended. It’s odd that the plug would be pulled without running analytics and making sure it doesn’t break stuff.

In Super Nostalgia Zone I think I’m overloading the update function right now because I couldn’t disable the default behavior without forking the PlayerModule. Trouble is, the code in that is loaded at runtime through a MainModule, so unless I go out of my way to put a forked PlayerModule into every place, the default one will always be loaded. Its difficult to get rid of it at runtime, and that would especially hold true if it’s impossible to access the state of the module.

The current game I’m working on also overloads some functions in the BaseCamera and TransparencyController, but I use a different entry point to modify those which shouldn’t break with this change.

I recognize the risk of doing things like this, but there’s really no clean way to go about it.

9 Likes

For my game, I need to grab a variable called “inFirstPerson” to know if the player is in first person or not, in order to trigger aiming when the right mouse button is clicked based on that variable.
Fortunately, I knew that camera scripts can change anytime, even without notice, so I also wrote a backup function that tells if the player is in first person, but it’s worse, because it’s based on a distance.

-- camera object detector for first person detection (preventions in case of Roblox updates !!!)
local is_first_person = nil
do
	local cam_script_updated = true
	local player_module = player:WaitForChild("PlayerScripts"):FindFirstChild("PlayerModule")
	if player_module then
		pcall(function()
			local camera_obj = require(player_module):GetCameras()
			local is_fp = camera_obj.activeCameraController.inFirstPerson
			if is_fp ~= nil then
				cam_script_updated = false
				is_first_person = function()
					if camera_obj.activeCameraController then
						return camera_obj.activeCameraController.inFirstPerson
					end
				end
			end
		end)
	end
	if cam_script_updated then
		is_first_person = function()
			return (camera.CFrame.p - camera.Focus.p).Magnitude < 2 -- worse than getting first person from camera script
		end
	end
end

The removal of the API made my game use the other function, but the camera CFrame being less than 2 studs away from the focus doesn’t necessarily mean the player is in first person.
Maybe I’m missing a better way to detect that, but using the camera API is definitely the best way to know that.

4 Likes

In Adventure Up! we use this code to check if the mouse lock is enabled:

local function isMouseLocked()
	if playerModule and playerModule.GetCameras then
		local cameraModule = playerModule:GetCameras()
		if cameraModule and cameraModule.activeMouseLockController then
			local mouseLocked = cameraModule.activeMouseLockController:GetIsMouseLocked()
			if type(mouseLocked) == "boolean" then
				return mouseLocked
			end
		end
	end
	return false
end

This is necessary for us because disabling the mouse cursor and all the core gui disables any gui related to mouse lock. We have to make our own cursors and indicators for mouse lock, but still want to use the built in setting for it.
There are some safe guards in place as you can see, and this is probably pretty common with anyone who is doing this, but this API change would most definitely break things in games.

7 Likes

To elaborate a little more on my use cases here, it would be nice if there was an API to set the filter for what parts the TransparencyController targets.

Right now I try to target the ModuleScript as a descendant of the PlayerModule and attempt to overload TransparencyController:IsValidPartToModify(part) using the following logic:

image

I also overload BaseCamera:GetSubjectPosition() so I can make the camera snap to the player’s head in first person. I could probably just use the Humanoid’s CameraOffset to accomplish this instead.

(cc @TheGamer101)

4 Likes

One of my really old scripts relied completely on the CameraModule API and I think that it’s completely broken with this change… I additionally was also never under the impression that I shouldn’t be using it. I think a very nice change would be to convert all Roblox code to packages (preferably already on auto update) such as requested in this post so diffs can be viewed/merged easier, meaning merging updates with forked code is much easier to do and it’s much easier to asses the changes Roblox makes.

Additionally, there should definitely be an easier way to modify functionality of the camera before it has run, or at the very least allow us to force it to only start when we want it to, that way even very large games can even use it.

4 Likes

I use the API to force enable/disable shiftlock mode, since the method which uses UserInputService doesn’t seem to work as intended for me.

In general, I’d really like to see better documentation and support for the camera - It’s always been a pain point for me, and sooner or later I am forced to write my own since Roblox’s default settings never seem to work well for me. The worse part is that the camera itself is quite good - it’s only the lack of configuration that is a deal breaker for me.

4 Likes

I just noticed that this changed. Here is the use case I had implemented:

When the Camera switches CameraType from Scriptable to Custom, it tends to snap to some zoom level different than its current distance from the subject. If this CameraType change is made at the end of Tweening the Camera, it makes for a not so smooth experience. The Camera changes like this somewhat frequently in my game.

To mitigate this, I accessed CameraModule.activeCameraController and took advantage of the following functions:

:GetSubjectPosition()
:GetCameraToSubjectDistance()
:SetCameraToSubjectDistance()

All of this was of course wrapped in a pcall so that, worst case, the Camera would just be janky again. I just now noticed it, started digging, and discovered FFlagUserRemoveTheCameraApi. I would appreciate some kind of public access to the functions mentioned above.

Edit:
I also used the same functions to make a custom Gamepad zoom function when clicking the RightStick.

4 Likes

Nice to see that it was done anyway despite multiple people pointing out that it was a bad idea :pensive:

This broke Super Nostalgia Zone’s camera until I patched it today. Now if I want to overload the camera’s behavior without forking it AND still support using the CameraType property, I have to nuke it via this:

RunService:UnbindFromRenderStep("cameraRenderUpdate")
14 Likes

I just dug through the code in my work-in-progress project, and noticed this change broke the the camera for me. My use-case to access the CameraModule API is to force-enable ShiftLock and change some of its variables such as the offset from the Character.

Accessing the Camera API is supposed to be officially supported, and was announced to developers with the introduction of the updated PlayerScripts.

Ended up just forking the playerscripts entirely, but hey… this change is extremely backwards and only makes official Roblox code less accessible for Developers. Not a great move.

15 Likes

This is still a problem. Get rid of FFlagUserRemoveTheCameraApi or turn it off so that I don’t have to replace the camera modules with a fixed version that never updates. I need access to the shift lock controls.

14 Likes

I need to be able to change the active MouseLockController’s savedMouseCursor so that the mouse icon isn’t reverted to an old one if I change it while shift lock is enabled. This change prevents me from doing so.

3 Likes