This is an unfortunate part of how Roblox tracks changes to the data model. It’d be impossible for Roblox to know how to track edits in a way that doesn’t interfere with what you’re doing.
In order for your edits to be properly logged to the undo stack, take a look at ChangeHistoryService | Documentation - Roblox Creator Hub. Slapping this at the end of most command bar scripts will suffice:
game:GetService("ChangeHistoryService"):SetWaypoint("Did something")
Examples as to why this isn't particularly a bug
Let’s pretend Roblox created an undo waypoint every time a new instance was parented.
This code is now impossible to undo:
for i = 1, 1000 do
local part = Instance.new("Part")
-- Pretend this does something important with the parts
part.Parent = workspace
end
“Okay, create the waypoint after the script is done running.”
Then this code will not undo properly, creating a waypoint before it’s actually done editing things:
workspace:SetAttribute('SomeProperty', false)
-- Spawn a thread that will finish after main thread
task.delay(5, function()
workspace:SetAttribute('SomeProperty', true)
end)
“Okay, create the waypoint after EVERY thread is done running.”
Then this code would never create a waypoint at all:
-- Create a monitoring thread that never ends
-- This could also be something like an event connection
-- that listens to RenderStepped or property changes
task.spawn(function()
while true do
print("Still monitoring...")
task.wait(1)
end
end)
-- Create 100 parts that should be undoable as a single operation
for i = 1, 100 do
local part = Instance.new("Part")
part.Position = Vector3.new(i, 0, 0)
part.Parent = workspace
end
These parts end up being impossible to undo, and get batched with some other edit, and we’re back to square one.
Alternatively, I’d suggest opening a feature request for an automatic waypoint system, with some examples of how it’d make your life easier.