Roblox's CameraScript is spaghetti code – I want to propose a solution

The Problem

At RDC 2017, I recall that we were asked to stop forking Roblox’s Camera code during one of the presentations. The reason was something along the lines of: “It prevents new features and fixes from being introduced, and theres no source control system in place to know when these changes happen if you fork the code.”

I’ve looked into some of the recent changes, and I’ve found that there are a lot of bad practices in the CameraScript:

  • Spaghetti code everywhere.
  • Input handling is hard-coded directly into the RootCamera.
  • The CameraScript requires very specific modules instead of having some generic module package system.
  • Not possible to externally communicate with the active RootCamera instance, or anything else really.

Thus, I think they should create a new system, which splits up the camera into an extendable framework.
The framework would have three phases:

Pre-Update

The Pre-Update phase provides an entry point to a folder of ModuleScripts that each provides a feed of input into the Camera’s panning.

This could be divided up into several individual input handlers:

  • Keyboard
  • Mouse
  • Touch
  • Gamepad
  • VR

Update

The Update phase runs the update function of the active camera behavior module, and that module applies the base camera transformation through the RootCamera using the provided input feed.

Post-Update

The Post-Update phase is used to apply some post-processing to the camera after it applies the base transformation.

This can include stuff like:

  • Transforming the camera when in shift-lock mode.
  • Auto-rotating the camera while in a vehicle.
  • Handling camera occlusion (PopperCam, Invisicam).
  • Updating the transparency of the character.

Rationale for this proposal

With a system like this, Roblox could just introduce new module packages whenever they want to introduce new input behaviors, and as long as they established a strong foundation framework, they wouldn’t need to worry so much about people forking their code. Developers could simply write extensions upon the framework instead of having to fork and edit the base code itself. The in-game chat system does a pretty good job at providing support for custom behaviors, and I think the Camera code could do it just as nicely with a proper redesign.

Ideally there would be access points where developers could register their own handlers in separate LocalScripts. These access points could also provide access to other behavior handlers, so that developers could adjust settings pertaining to these behaviors.
Some examples could include:

  • Adjusting the offset applied by the Shift Lock.
  • Tweaking the behavior of the vehicle camera, so that it can be disabled entirely, or certain aspects can be tuned like the rotation speed and the idle time it takes for it to start rotating on its own.
  • Changing the mode of the Invisicam, as well as the transparency it applies, the speed that things fade out, etc.

In Conclusion

This is a large undertaking, of course, but Roblox should really consider doing something like this if they want us to stop forking the camera code. I think it would really pay off in the long run.

(cc @Rototally, @darthskrill, @AllYourBlox, @0xBAADF00D)


36 Likes

I was literally looking at the CameraScript just before, and I can only say I totally agree with this.

The ControlScript, while not on the same level of the CameraScript, could also do with a total overhaul.

7 Likes

As a small footnote, I wanted to note an example of a very simple change that still requires me to fork the entire CameraScript because of how closed off the code is to external modification:

4 Likes

@AllYourBlox is in the middle of rewriting the camera scripts to be much more managable, and we plan on doing the same thing for the control scripts.

One of the features we’ve been toying with is adding an easy way for a dev to insert a new camera module. We are also looking at exposing a good number of variables to tweak various camera settings.

16 Likes

Well thats good to hear! I hope you guys take some of these suggestions if they haven’t been considered :slight_smile:

Yessss kill me all that clutter.
It’s been awakening to try to edit the camera script so much.

1 Like

Will you notify us beforehand if this changes the hierarchy/API of these scripts? In one of my projects I currently rely on the hierarchy ControlScript > MasterControl and that I can call certain methods of MasterControl (:GetMoveVector(), :Enable(), :Disable(), jump enabling/disabling…).

As @darthskrill notes, I’m well into this project. I agree wholeheartedly with your assessment, and have been working towards PlayerScripts 2.0, a complete system re-write where everything is highly modular and allows developers to replace as much or as little Roblox-supplied code as they need, without sacrificing automatic updates to anything they don’t explicitly override.

This turned out to be a fairly large project that I’m already a couple of months into. We don’t want to compromise the new system with legacy compatibility issues, so what’s likely to happen is that there will be a final, end-of-life update for the ControlScript/CameraScript system, that receives only bug fixes thereafter. Developers not wishing to immediately refactor their game will be able to keep going with this, nursing it SP2 still for a very long time. But for all new projects, there will be a new playerscript paradigm.

In a nutshell, there will still be a top-level entry point LocalScript, probably called something like RobloxPlayerScript, which will be little more than a module discoverer/loader and some bindings to top-level services like Players, RunService, etc. It will load modules for character control, camera control, occlusion and transparency modifiers. Each of these majors classes of modules will have what is effectively an abstract base class from which they derive and then override a few key functions like Init(), Update(), that sort of thing.

There are still a lot of details to be worked out an finalized for how this will interface to game Lua scripts, and what the recommended pattern for user-added modules will be. One big piece of this is that we’ll be embracing the idea of external Lua parameters, implemented similar to ValueObjects, which will be used for developer tuning parameters (analogous to class static initializers), but also for per-instance properties with runtime change listener bindings. Much of what I’m introducing is inspired by UI and modular code “Components” from other environments I’ve worked in across a lot of platforms over my game programming career.

I can promise you that at the end of my project, we’ll no longer have mom’s spaghetti.

41 Likes

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