Quick answer: Prefab changes may not save if you are editing a scene instance but never applying the overrides back to the prefab asset. Changes made to an instance in the scene are local overrides that only exist in that scene.
Here is how to fix Unity prefab changes not saving. You modify a prefab instance in the scene — change a material, tweak a transform value, add a child object — and everything looks correct. But when you drag the prefab into another scene or instantiate it at runtime, your changes are gone. The prefab reverts to its original state as if you never touched it. Or you open Prefab Mode, make edits, and exit, only to find the changes did not persist. Unity’s prefab workflow has specific rules about where edits are stored and how they propagate, and breaking those rules means losing work.
The Symptom
You select a prefab instance in the Hierarchy, modify one or more properties in the Inspector, and the changes appear immediately in the Scene view. But when you instantiate a fresh copy of the prefab (via code or by dragging from the Project window), the new instance does not reflect your changes. The original scene instance still shows your modifications, but no other instance does.
Alternatively, you make changes in Prefab Mode (the isolated editing environment) and then exit. The next time you open the prefab or check instances in scenes, the changes are not there. Sometimes the changes appear to save but are reverted after restarting the Unity editor or after a version control pull.
With nested prefabs, the problem gets more confusing: you edit a child prefab inside a parent prefab and the change shows up in some contexts but not others. Or applying overrides on a nested prefab causes unexpected changes to cascade through your project.
What Causes This
The prefab system distinguishes between the prefab asset (the .prefab file in your Project window) and prefab instances (copies of that asset placed in scenes or inside other prefabs). Changes to instances are "overrides" that only live in the scene file unless you explicitly apply them back to the asset.
1. Editing an instance without applying overrides. When you change a property on a prefab instance in the scene, Unity tracks it as an override. The blue highlight on the property label in the Inspector indicates an override. These overrides are stored in the scene file, not the prefab file. If you want other instances and future instantiations to have the change, you must apply the override to the prefab asset.
2. Making changes during Play mode. All changes made during Play mode are discarded when you exit Play mode. This is by design — Play mode is a temporary sandbox. If you modify a prefab instance or even open Prefab Mode during Play mode, everything reverts when you stop playing. Many developers have lost hours of work to this.
3. Serialization not triggered on custom editor scripts. If you modify prefab data programmatically in a custom editor script or EditorWindow, Unity does not automatically know that the data has changed. Without calling EditorUtility.SetDirty() and saving, the changes exist only in memory and are lost when the editor reloads or the asset is reloaded from disk.
4. Nested prefab override confusion. In a nested prefab setup (prefab A contains an instance of prefab B), modifications to the inner instance are overrides of the outer prefab. They do not change prefab B itself. If you later modify prefab B directly, your overrides in prefab A may conflict or be lost if you choose "Revert" instead of "Apply" on the wrong level.
5. ScriptableObject references not persisting. If a prefab has a serialized field pointing to a ScriptableObject, that reference can break if the ScriptableObject asset is moved outside of Unity (via the file system or version control), or if a runtime-created ScriptableObject instance is assigned to a prefab field (runtime instances are not saved as assets).
The Fix
Step 1: Apply instance overrides to the prefab asset using the Overrides dropdown.
Select the modified prefab instance in the Hierarchy. In the Inspector header, you will see an Overrides dropdown. Click it to see all modified properties, added components, and added/removed child objects. Click Apply All to write everything back to the prefab asset. You can also right-click individual properties and select Apply to Prefab for selective applying.
For programmatic apply in editor scripts:
using UnityEngine;
using UnityEditor;
public class PrefabApplyHelper
{
[MenuItem("Tools/Apply Selected Prefab Overrides")]
static void ApplySelectedPrefabOverrides()
{
GameObject selected = Selection.activeGameObject;
if (selected == null)
{
Debug.LogWarning("No GameObject selected.");
return;
}
// Check if the selected object is a prefab instance
if (PrefabUtility.GetPrefabInstanceStatus(selected) !=
PrefabInstanceStatus.Connected)
{
Debug.LogWarning("Selected object is not a connected prefab instance.");
return;
}
// Apply all overrides to the prefab asset
string prefabPath = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(selected);
PrefabUtility.ApplyPrefabInstance(selected, InteractionMode.UserAction);
Debug.Log($"Applied overrides to prefab at: {prefabPath}");
}
}
Step 2: Edit prefabs in Prefab Mode for direct, persistent changes.
Instead of editing instances in scenes, double-click the prefab asset in the Project window to enter Prefab Mode. All changes here are written directly to the prefab file when you save (Ctrl+S). This eliminates the override-apply workflow entirely and is the safest way to edit prefabs.
For scripts that need to modify prefab assets programmatically, load and edit the asset directly:
using UnityEngine;
using UnityEditor;
public class PrefabBatchEditor
{
[MenuItem("Tools/Batch Update Enemy Prefabs")]
static void BatchUpdateEnemyPrefabs()
{
// Find all prefab assets in a specific folder
string[] guids = AssetDatabase.FindAssets(
"t:Prefab", new[] { "Assets/Prefabs/Enemies" });
foreach (string guid in guids)
{
string path = AssetDatabase.GUIDToAssetPath(guid);
// Load the prefab contents for editing
using (var editScope = new PrefabUtility.EditPrefabContentsScope(path))
{
GameObject root = editScope.prefabContentsRoot;
// Modify the prefab contents
var health = root.GetComponent<EnemyHealth>();
if (health != null)
{
health.maxHealth = 150;
}
}
// Changes are saved automatically when the scope is disposed
}
AssetDatabase.SaveAssets();
Debug.Log($"Updated {guids.Length} enemy prefabs.");
}
}
The EditPrefabContentsScope (available since Unity 2021.2) automatically loads the prefab for editing and saves the changes when the scope exits. This is the cleanest way to modify prefab assets from editor scripts.
Step 3: Mark modified objects as dirty and save assets in custom editor code.
If you modify serialized data through custom inspectors, property drawers, or editor windows, you must tell Unity that the data changed:
using UnityEngine;
using UnityEditor;
[CustomEditor(typeof(WeaponStats))]
public class WeaponStatsEditor : Editor
{
public override void OnInspectorGUI()
{
WeaponStats stats = (WeaponStats)target;
// Use SerializedProperty for automatic undo and dirty marking
serializedObject.Update();
EditorGUILayout.PropertyField(serializedObject.FindProperty("damage"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("fireRate"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("ammoType"));
if (serializedObject.ApplyModifiedProperties())
{
// Changes were made - ApplyModifiedProperties handles dirty marking
Debug.Log("Weapon stats updated and marked for saving.");
}
// If you modify the object directly (not via SerializedProperty),
// you MUST call SetDirty manually:
if (GUILayout.Button("Reset to Defaults"))
{
Undo.RecordObject(stats, "Reset Weapon Stats");
stats.damage = 10;
stats.fireRate = 0.5f;
EditorUtility.SetDirty(stats);
}
}
}
The key rule: if you use SerializedProperty and ApplyModifiedProperties, dirty marking is handled automatically. If you modify the object directly (setting fields on the target), you must call EditorUtility.SetDirty() and ideally Undo.RecordObject() for undo support.
Why This Works
Applying overrides writes the modified data from the scene file into the prefab asset file. Until you apply, the changes only exist as delta overrides in the scene. This is Unity’s intentional design to let you have per-scene variations of a prefab without modifying the shared asset.
Prefab Mode bypasses the override system entirely. You are editing the source asset directly, so there is nothing to apply. It is the equivalent of opening a .prefab file in a text editor and changing values — except Unity provides a visual scene for it.
SetDirty tells Unity’s serialization system that an asset’s in-memory state has diverged from its on-disk state. Without this flag, Unity assumes nothing changed and will not write the asset when you save. This is an optimization — Unity does not re-serialize every asset every time you save — but it means manual modifications must explicitly opt in to saving.
"Every time you modify a prefab instance in the scene, ask yourself: is this a per-scene override, or should this be the new default? If the latter, apply it."
Related Issues
If your prefab references are becoming null at runtime (especially component references), the problem may be broader than prefabs — see NullReferenceException on GetComponent for serialized field debugging techniques. If changes in your Animator Controller are not persisting across prefab instances, check Animation Not Playing in Animator for Animator-specific configuration that affects prefab instances differently than scene objects.
Never edit prefabs in Play mode. Ever. You will lose everything.