Source: Roblox Creator Hub · CC BY 4.0 · View source · Code samples: MIT Imported 2026-10-03. Formatting adapted for this site.
ChangeHistoryService
Inherits from: Instance → Object
Plugin developers must use ChangeHistoryService to tell Studio how to undo and redo changes that their plugins make to experiences by recording. Before making changes, a plugin calls ChangeHistoryService:TryBeginRecording(), remembering the identifier it assigns, then after making changes, the Plugin calls ChangeHistoryService:FinishRecording() to complete the recording.
Plugins may also programmatically invoke an undo or redo through ChangeHistoryService:Undo() or ChangeHistoryService:Redo().
ChangeHistoryService is not enabled at runtime, so calling its methods in a running experience has no effect.
Inherits from: Instance
Memory category: Instances
Tags: NotCreatable, Service
Methods
| Name | Type / Returns | Description |
|---|---|---|
| ChangeHistoryService:FinishRecording | () | Communicates to Studio that the identified recording is finished and to take the final operation to complete the recording. |
| ChangeHistoryService:GetCanRedo | Tuple | Returns whether there is an action available to redo and, if so, the name of that action. |
| ChangeHistoryService:GetCanUndo | Tuple | Returns whether there is an action available to undo and, if so, the name of that action. |
| ChangeHistoryService:IsRecordingInProgress | boolean | Returns whether the plugin currently has a recording in progress, optionally checking for a specific recording identifier. |
| ChangeHistoryService:Redo | () | Re-executes the most recently undone action, advancing forward through the undo/redo history. |
| ChangeHistoryService:ResetWaypoints | () | Clears the undo/redo history by collapsing it into a single base waypoint. |
| ChangeHistoryService:SetEnabled | () | Sets whether or not the ChangeHistoryService is enabled. |
| ChangeHistoryService:SetWaypoint | () | Sets a new waypoint which can be used as an undo or redo point. |
| ChangeHistoryService:TryBeginRecording | string? | Begins tracking changes made to the data model into a recording. |
| ChangeHistoryService:Undo | () | Reverts the most recent action, stepping backward through the undo/redo history. |
Inherited from Instance
| Name | Type / Returns | Description |
|---|---|---|
| Instance:AddTag | () | Applies a tag to the instance. |
| Instance:children | Instances | Returns an array of the object's children. |
| Instance:ClearAllChildren | () | This method destroys all of an instance's children. |
| Instance:Clone | Instance | Create a copy of an instance and all its descendants, ignoring instances that are not Archivable. |
| Instance:clone | Instance | |
| Instance:Destroy | () | Sets the Instance.Parent property to nil, locks the Instance.Parent property, disconnects all connections, and calls Destroy() on all children. |
| Instance:destroy | () | |
| Instance:FindFirstAncestor | Instance? | Returns the first ancestor of the Instance whose Instance.Name is equal to the given name. |
| Instance:FindFirstAncestorOfClass | Instance? | Returns the first ancestor of the Instance whose Object.ClassName is equal to the given className. |
| Instance:FindFirstAncestorWhichIsA | Instance? | Returns the first ancestor of the Instance for whom Object:IsA() returns true for the given className. |
| Instance:FindFirstChild | Instance? | Returns the first child of the Instance found with the given name. |
| Instance:findFirstChild | Instance | |
| Instance:FindFirstChildOfClass | Instance? | Returns the first child of the Instance whose ClassName is equal to the given class name. |
| Instance:FindFirstChildWhichIsA | Instance? | Returns the first child of the Instance for whom Object:IsA() returns true for the given className. |
| Instance:FindFirstDescendant | Instance? | Returns the first descendant found with the given Instance.Name. |
| Instance:GetActor | Actor? | Returns the Actor associated with the Instance, if any. |
| Instance:GetAttribute | Variant | Returns the value which has been assigned to the given attribute name. |
| Instance:GetAttributeChangedSignal | RBXScriptSignal | Returns an event that fires when the given attribute changes. |
| Instance:GetAttributes | Dictionary | Returns a dictionary of the instance's attributes. |
| Instance:GetChildren | Instances | Returns an array containing all of the instance's children. |
| Instance:getChildren | Instances | |
| Instance:GetDebugId | string | Returns a coded string of the debug ID used internally by Roblox. |
| Instance:GetDescendants | Instances | Returns an array containing all of the descendants of the instance. |
| Instance:GetFullName | string | Returns a string describing the instance's ancestry. |
| Instance:GetStyled | Variant | Returns the styled or explicitly modified value of the specified property, or else the default property value if it hasn't been styled/modified. |
| Instance:GetStyledPropertyChangedSignal | RBXScriptSignal | Returns an event that fires when the given style property changes on the instance. |
| Instance:GetTags | Array | Gets an array of all tags applied to the instance. |
| Instance:HasTag | boolean | Check whether the instance has a given tag. |
| Instance:IsAncestorOf | boolean | Returns true if an Instance is an ancestor of the given descendant. |
| Instance:IsDescendantOf | boolean | Returns true if an Instance is a descendant of the given ancestor. |
| Instance:isDescendantOf | boolean | |
| Instance:IsPropertyModified | boolean | Returns true if the value stored in the specified property is not equal to the code-instantiated default. |
| Instance:QueryDescendants | Instances | Returns an array containing all descendants of the instance that match the selector string. |
| Instance:Remove | () | Sets the object's Parent to nil, and does the same for all its descendants. |
| Instance:remove | () | |
| Instance:RemoveTag | () | Removes a tag from the instance. |
| Instance:ResetPropertyToDefault | () | Resets a property to its default value. |
| Instance:SetAttribute | () | Sets the attribute with the given name to the given value. |
| Instance:WaitForChild | Instance | Returns the child of the Instance with the given name. If the child does not exist, it will yield the current thread until it does. |
Inherited from Object
| Name | Type / Returns | Description |
|---|---|---|
| Object:GetPropertyChangedSignal | RBXScriptSignal | Get an event that fires when a given property of the object changes. |
| Object:IsA | boolean | Returns true if an object's class matches or inherits from a given class. |
| Object:isA | boolean |
ChangeHistoryService:FinishRecording
Completes a recording that was started with TryBeginRecording(). Pass the identifier returned by that call along with an FinishRecordingOperation describing what to do with the recorded changes:
FinishRecordingOperation.Commitadds the changes to the undo/redo history as a new waypoint.FinishRecordingOperation.Canceldiscards the recording and reverts the changes it captured. Theidentifieris ignored for this operation, so a plugin can cancel its own in-progress recording without knowing the identifier.FinishRecordingOperation.Appendmerges the recording into the waypoint that immediately precedes it rather than creating a new one.
When the recording finishes, this method fires OnRecordingFinished, forwarding the finalOptions table. It raises an error if the calling plugin has no recording in progress, or if operation is not FinishRecordingOperation.Cancel and identifier does not match the active recording. It has no effect when the service is disabled or while an undo or redo is in progress.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
| identifier | string | Identifies the recording from the previous call to TryBeginRecording(). If the operation is FinishRecordingOperation.Cancel, this value is ignored, and the recording is determined by context. | |
| operation | FinishRecordingOperation | Specifies the operation to take. | |
| finalOptions | Dictionary? | Optional table of values to pass to OnFinishRecording. |
Returns
| Type | Description |
|---|---|
| () |
| Field | Value |
|---|---|
| security | PluginSecurity |
| thread safety | Unsafe |
Code samples: View on Creator Hub (ChangeHistoryService-TryBeginRecording1).
ChangeHistoryService:GetCanRedo
Reports whether Redo() currently has an action available to replay. It returns a boolean that is true when a redoable waypoint exists ahead of the current position in the undo/redo history; when that boolean is true, it also returns the name of the waypoint that the next redo would replay.
The boolean is false, with no name returned, when the redo stack is empty because the newest waypoint is already the current one, or when the service is disabled (which is always the case at runtime).
Returns
| Type | Description |
|---|---|
| Tuple | true followed by the name of the action that would be redone when a redo is available; otherwise false. |
| Field | Value |
|---|---|
| security | PluginSecurity |
| thread safety | Unsafe |
ChangeHistoryService:GetCanUndo
Reports whether Undo() currently has an action available to revert. It returns a boolean that is true when an undoable waypoint exists at the current position in the undo/redo history; when that boolean is true, it also returns the name of the waypoint that the next undo would revert.
The boolean is false, with no name returned, when the undo stack is empty because the position is already at the base waypoint, or when the service is disabled (which is always the case at runtime).
Returns
| Type | Description |
|---|---|
| Tuple | true followed by the name of the action that would be undone when an undo is available; otherwise false. |
| Field | Value |
|---|---|
| security | PluginSecurity |
| thread safety | Unsafe |
ChangeHistoryService:IsRecordingInProgress
Reports whether the calling plugin has a recording in progress that was started with TryBeginRecording().
When called without an identifier, it returns true if any recording is active for the plugin. When an identifier is supplied, it returns true only if the active recording's identifier matches that value. It returns false when the service is disabled or when the plugin has no active recording.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
| identifier | string? | Optional identifier of a specific recording to check for. When omitted, the method reports whether any recording is in progress for the plugin. |
Returns
| Type | Description |
|---|---|
| boolean | true if a matching recording is in progress; otherwise false. |
| Field | Value |
|---|---|
| security | PluginSecurity |
| thread safety | Unsafe |
ChangeHistoryService:Redo
Replays the waypoint immediately ahead of the current position in the undo/redo history, redoing the action that a matching Undo() had reverted, and advances the redo pointer forward by one waypoint. After the waypoint is replayed, it fires OnRedo with the name of the redone waypoint.
This method raises an error if a play is already in progress, if the service is disabled (which is always the case at runtime), or if there is nothing left to redo. Call GetCanRedo() first to confirm a redo is available.
Returns
| Type | Description |
|---|---|
| () |
| Field | Value |
|---|---|
| security | PluginSecurity |
| thread safety | Unsafe |
ChangeHistoryService:ResetWaypoints
Records the current state as a waypoint named base and then merges every existing waypoint into that single waypoint, leaving no actions to undo or redo. Use this to establish a clean starting point so that later Undo() calls cannot revert past the current state.
This method has no effect when the service is disabled (which is always the case at runtime).
Returns
| Type | Description |
|---|---|
| () |
| Field | Value |
|---|---|
| security | PluginSecurity |
| thread safety | Unsafe |
ChangeHistoryService:SetEnabled
Sets whether or not the ChangeHistoryService is enabled. When set to false, the undo/redo list is cleared, and does not repopulate. When set to true again, the original list is not restored, but further operations append to the list once more
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
| state | boolean | Whether to enable (true) or disable (false) the service. |
Returns
| Type | Description |
|---|---|
| () |
| Field | Value |
|---|---|
| security | PluginSecurity |
| thread safety | Unsafe |
ChangeHistoryService:SetWaypoint
This method will be deprecated soon in favor of TryBeginRecording().
ChangeHistoryService tracks plugin history as a stream of property changes. SetWaypoint() creates a cut in that stream of property changes so that the undo and redo actions know where to stop.
By convention, user-invoked actions in Studio must call SetWaypoint() after completing their set of changes to the experience. Calling it before a set of changes may clean up another misbehaving plugin which failed to set a waypoint, but it's a poor reason to justify such usage in your own plugin.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
| name | string | The name to assign to the new waypoint, which appears in the undo/redo history. |
Returns
| Type | Description |
|---|---|
| () |
| Field | Value |
|---|---|
| security | PluginSecurity |
| thread safety | Unsafe |
Code samples: View on Creator Hub (ChangeHistoryService-SetWaypoint1).
ChangeHistoryService:TryBeginRecording
This method begins a recording to track changes to the data model. You must call it prior to making changes to avoid future warnings or errors.
When the recording is completed, you call FinishRecording() with the returned recording identifier to complete the recording and update the undo/redo stack.
This method will return nil if it fails to begin a recording. Recordings fail if the plugin already has a recording in progress, or if the user is in a solo playtest.
You may use IsRecordingInProgress() to check the recording status of the plugin.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
| name | string | Name of the action being performed suitable for logging and coding purposes. | |
| displayName | string? | Name of the action being performed to display to the user. |
Returns
| Type | Description |
|---|---|
| string? | A unique string identifier for the recording on success, or nil if the recording could not be started. |
| Field | Value |
|---|---|
| security | PluginSecurity |
| thread safety | Unsafe |
Code samples: View on Creator Hub (ChangeHistoryService-TryBeginRecording1).
ChangeHistoryService:Undo
Unplays the waypoint at the current position in the undo/redo history, reverting the most recent recorded action, and steps the undo pointer back by one waypoint. After the waypoint is reverted, it fires OnUndo with the name of the undone waypoint.
This method raises an error if a play is already in progress, if the service is disabled (which is always the case at runtime), or if there is nothing left to undo. Call GetCanUndo() first to confirm an undo is available.
Returns
| Type | Description |
|---|---|
| () |
| Field | Value |
|---|---|
| security | PluginSecurity |
| thread safety | Unsafe |
Events
| Name | Type / Returns | Description |
|---|---|---|
| ChangeHistoryService.OnRecordingFinished | Fired when the user completes an action. Parameters come from TryBeginRecording() and FinishRecording(). | |
| ChangeHistoryService.OnRecordingStarted | Fired when the user begins an action. Parameters come from TryBeginRecording(). | |
| ChangeHistoryService.OnRedo | Fires after an action is redone, reporting the name of the action that was replayed. | |
| ChangeHistoryService.OnUndo | Fires after an action is undone, reporting the name of the action that was reverted. |
Inherited from Instance
| Name | Type / Returns | Description |
|---|---|---|
| Instance.AncestryChanged | Fires when the Instance.Parent property of this object or one of its ancestors is changed. | |
| Instance.AttributeChanged | Fires whenever an attribute is changed on the Instance. | |
| Instance.ChildAdded | Fires after an object is parented to this Instance. | |
| Instance.childAdded | ||
| Instance.ChildRemoved | Fires after a child is removed from this Instance. | |
| Instance.DescendantAdded | Fires after a descendant is added to the Instance. | |
| Instance.DescendantRemoving | Fires immediately before a descendant of the Instance is removed. | |
| Instance.Destroying | Fires immediately before (or is deferred until after) the instance is destroyed via Instance:Destroy(). | |
| Instance.StyledPropertiesChanged | Fires whenever any style property is changed on the instance, including when a property is set to nil. |
Inherited from Object
| Name | Type / Returns | Description |
|---|---|---|
| Object.Changed | Fires immediately after a property of the object changes, with some limitations. |
ChangeHistoryService.OnRecordingFinished
Fires when a recording started with TryBeginRecording() is completed through FinishRecording(). The operation argument reports how the recording was finished (Commit, Cancel, or Append), and finalOptions is the optional table that was passed to FinishRecording().
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
| name | string | Name of the action being performed suitable for logging and coding purposes. | |
| displayName | string? | Name of the action being performed to display to the user. | |
| identifier | string? | The identifier for the recording. | |
| operation | FinishRecordingOperation | The FinishRecordingOperation that completed the recording, either Commit, Cancel, or Append. | |
| finalOptions | Dictionary? | Optional table from FinishOperation(). |
| Field | Value |
|---|---|
| security | PluginSecurity |
ChangeHistoryService.OnRecordingStarted
Fires when a plugin begins a recording with TryBeginRecording(), carrying the same name and displayName values that were passed to that call.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
| name | string | Name of the action being performed suitable for logging and coding purposes. | |
| displayName | string? | Name of the action being performed to display to the user. |
| Field | Value |
|---|---|
| security | PluginSecurity |
ChangeHistoryService.OnRedo
Fires immediately after Redo() replays a waypoint, whether the redo was triggered by the user through Studio or invoked programmatically. The waypoint argument is the name of the action that was redone, matching the name that was recorded for that waypoint.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
| waypoint | string | The name of the waypoint (action) that was redone. |
| Field | Value |
|---|---|
| security | PluginSecurity |
ChangeHistoryService.OnUndo
Fires immediately after Undo() reverts a waypoint, whether the undo was triggered by the user through Studio or invoked programmatically. The waypoint argument is the name of the action that was undone, matching the name that was recorded for that waypoint.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
| waypoint | string | The name of the waypoint (action) that was undone. |
| Field | Value |
|---|---|
| security | PluginSecurity |
Properties
Inherited from Instance
| Name | Type / Returns | Description |
|---|---|---|
| Instance.Archivable | boolean | Determines if an Instance and its descendants can be cloned using Instance:Clone(), and can be saved/published. |
| Instance.archivable | boolean | |
| Instance.Capabilities | SecurityCapabilities | The set of capabilities allowed to be used for scripts inside this container. |
| Instance.IsInSandbox | boolean | Indicates whether the instance is inside a sandboxed container. |
| Instance.Name | string | A non-unique identifier of the Instance. |
| Instance.Parent | Instance | Determines the hierarchical parent of the Instance. |
| Instance.PredictionMode | PredictionMode | Reflects the client-side prediction mode applied to the instance under server-authoritative physics. |
| Instance.RobloxLocked | boolean | A deprecated property that used to protect CoreGui objects. |
| Instance.Sandboxed | boolean | When enabled, the instance can only access abilities in its Capabilities list. |
| Instance.UniqueId | UniqueId | A unique identifier for the instance. |
Inherited from Object
| Name | Type / Returns | Description |
|---|---|---|
| Object.ClassName | string | A read-only string representing the class this Object belongs to. |
| Object.className | string |