My original intention was to simply play through undo’s using the ChangeHistoryService, allowing for a visual “timelapse” of a build being created, without having to watch a camera moving around rapidly but this is capped to 250 undo’s, and I can’t find a setting or fast flag to increase this.
Another option would be to have a second studio window open with team create, and use that to position a camera that wouldn’t be flying around while I build, but this still wouldn’t allow for me to go back and get a better camera angle of part of the building process.
Essentially I’m looking for suggestions on how to accomplish this, right now the only option I see is creating an entirely custom undo/redo system.
(The reason I don’t want to just record the studio window I’m building in is once you start speeding that up more than 3-4 times, the camera moves so fast it is not pleasant to watch.)
(Sorta thing I want to be able to do, but without a 250 action limit)
That might work, but it’s common to also remove parts, so you’d have to listen for DescendantRemoved, too. And it’s also common to move things to different Parents to keep things organized. Maybe the simplest way would be to keep track of all descendants of Workspace with DescendantAdded, and then listen for AncestryChanged on all of those? But then you also need to listen for Changed, because parts will be resized and change color and such Sounds pretty complicated TBH. It’s an interesting problem though
That’s exactly what I was thinking. Hook onto .Changed may not even need to hook on to .AncestryChanged if you do that because the .Parent property would change and fire .Changed.
Instead of making a super complicated system for saving every change in the model, I tried this much simpler solution:
Bind a hotkey to move the camera to a specific CFrame, and then move it back to where it was shortly after
Bind the same hotkey in my screenshot app (sharex) to take a screenshot after 0.1 seconds (the shortest possible delay)
Unfortunately it doesn’t work :C When the hotkey is set in sharex, it doesn’t “let the hotkey through” to whichever application is active, meaning Roblox Studio never sees that I’ve pressed the hotkey.
Welp, never figured it out. Here’s my janky workaround
I use AutoHotkey to send Alt + C followed by PrtSc whenever I press Alt + C. This way, my Studio plugin can detect the Alt + C shortcut and ShareX just detects PrtSc and takes a screenshot after 0.1 seconds. It saves all screenshots with an incrementing filename, so that I can import them to GIMP and export them as a GIF.
I also made a shortcut for the studio plugin to “save” whatever position the camera is currently in. I set it to Ctrl+Alt+C.
ahk script
~!c::
Send, {PrintScreen}
Plugin script
local InputS = game:GetService("UserInputService")
local RunS = game:GetService("RunService")
local savedCFrame = CFrame.new()
local loadAction = plugin:CreatePluginAction(
"camjam_load_cam", "CamJam: Load (previously saved) camera position", "", "", true
)
local saveAction = plugin:CreatePluginAction(
"camjam_set_cam", "CamJam: Save camera position", "", "", true
)
saveAction.Triggered:Connect(function()
print("CamJam: Saved camera location")
prevCFrame = game.Workspace.CurrentCamera.CFrame
savedCFrame = game.Workspace.CurrentCamera.CFrame
end)
loadAction.Triggered:Connect(function()
local cam = game.Workspace.CurrentCamera
prevCFrame = cam.CFrame
cam.CameraType = Enum.CameraType.Scriptable
cam.CFrame = savedCFrame
wait(0.15)
cam.CFrame = prevCFrame
wait()
cam.CameraType = Enum.CameraType.Fixed
end)
To “install” the plugin, just paste the code into a script, right click the script in Explorer and “Save as Local Plugin”. Go to File ->Advanced → Customize Shortcuts, search for “CamJam” and set “Load” to Ctrl+C. Set “Save” to whatever you want. to You’ll need to install autohotkey for the ahk script to work. Once installed, just save a text file with the script, and save it with the “.ahk” extension. Follow this guide to turn images into GIFs. In ShareX, modify the existing hotkey like so: Screenshot delay 0.1 s. Name pattern for window capture: “Screenshot %i”. After capture: save image to file.
Yeah the problem with just hooking onto DescendantAdded is all of the other things you would need to hook to, and be able to then undo. If there was a way to take the undo waypoints out of ChangeHistoryService it would be a lot easier, but I can’t find a way of doing this either. If ChangeHistoryService saved to the place file you could atleast automatically make a new autosave every 250 actions, then have separate place files for each section of the timelapse (which would also be a pain yeah).
That’s definitely a good method if you are okay with one static camera angle, which works well for builds like that. When I have wanted that in the past I’ve opened a second studio window on a different account with team create, bit less hassle that way. I guess another option would be to take multiple screenshots from different angles each time you press the keybind. Definitely not a bad way, I just want something a bit more versatile, might try experimenting with something similar though thanks.
Like it would be great if after I’ve finished building, I could go back through the process, and pick the camera angle at that point, which essentially means a plugin would need to know the entire history of the build.
Just to add, also can’t find a way of hiding the “player” models (the little transparent sphere and arrows) in team create which would help some of the alternate methods work.
If it were possible to access these, having a second “Player” to use as a camera, and being able to set that camera to your own current camera position could allow for a pretty easy way of timelapsing.
I track every object created/destroyed and keep up to date with their property changes. I also add a timestamp so it plays back in the speed it was recorded, and lets me play it back faster/slower if I so choose.
My concern from the testing I’ve done so far, is just dragging a part around can result in hundreds of property changes as it updates the position, orientation, rotation and CFrame, I guess the obvious thing to do would be to only “track” the CFrame and size properties (out of those atleast). I guess it makes sense, this was always going to involve an extreme amount of data.
Not to mention the visual indicators from stuff like the ResizeAlign plugin in themselves causing numerous changes per use.
In order for this to be anywhere close to optimised it would need lots of backlisted properties and part names, and in order to do that it would in itself become less efficient.
Just creating that simple shape creates 10066 logs total.
I guess ChangeHistoryService has the advantage of working based on a users inputs, and as such it can group things as an action, and all the things it applies to. (So in it’s case recolouring 100 parts would be little different to recolouring one, whereas doing it like this would result in significantly more steps.
If ChangeHistoryService atleast had an event when something new was done, these changes could be grouped up to the ChangeHistory waypoints, but unfortunately not.
After a few hours and the advice of the wonderful @Alkan got the base of it working.
Essentially tracks the creation, property change, and removal of parts in the place, saves those to a script, that script can then be read to “replay” the build.