Search Issue Tracker
By Design
Votes
0
Found in
2021.3.46f1
2022.3.52f1
6000.0.27f1
6000.1.0a4
Issue ID
UUM-87076
Regression
No
"PrefabUtility.ApplyPropertyOverride" method works only every second time when a property value is changed within the same script
How to reproduce:
1. Open the “OverrideBug.zip“ project
2. Open the “SampleScene”
3. Select the “Test“ Prefab in the Hierarchy
4. Press the three vertical dots on the “Test“ Script Component in the Inspector
5. Click the “PrefabTest“ button in the Context menu
6. Observe the last log of the Console
Expected result: The last Console message reads “Has Prefab Overrides After: False“
Actual result: The last Console message reads “Has Prefab Overrides Before: True”
Reproducible in: 2021.3.46f1, 2022.3.52f1, 6000.0.27f1, 6000.1.0a4
Reproduced on: Windows 11 Pro (23H2)
Not reproduced on: No other environment tested
Notes:
- Does not reproduce on a non-prefab Asset
- The second time the “PrefabTest“ button is clicked it applies the overrides and returns the expected result
- The behavior can be observed in the Inspector tab as well. When the overrides are not applied, a blue strip appears to the left of the changed field
Add comment
All about bugs
View bugs we have successfully reproduced, and vote for the bugs you want to see fixed most urgently.
Latest issues
- “Readme” Asset is unreadable in the Inspector window when switching Editor Theme to Light
- “NullReferenceException” error thrown when switching Editor Theme to Light if “Unity Version Control” tab is enabled
- A Warning is displayed in the Inspector when a Mesh with any Material is added as a Terrain Detail
- [Android][Vulkan] Memory leak when playing and stopping a video using the Video Player on some devices
- Caret moves by a character when typing "." and any number into 'Grid and Snap' toolbar's input field
Resolution Note:
The user tests is wrongly assuming what our API is doing - please find below my comments on the user code with fixes followed by simplified example:
[ContextMenu("PrefabTest")]
private void PrefabTest()
{
// Create a serialized representation of "this" object
SerializedObject so = new SerializedObject(this);
// Find the serialized representation of TestString property
var property = so.FindProperty(nameof(TestString));
// Set the serialized representation of TestString to Time.time.ToString()
property.stringValue = Time.time.ToString();
// Apply the serialized representation of TestString to "this" object
// NOTE:
// This doesn't record the override in the Prefab instance and HasPrefabInstanceAnyOverrides will return false!
// To record the property override in the Prefab instance one needs to call PrefabUtility.RecordPrefabInstancePropertyModifications
so.ApplyModifiedProperties();
// Record the modifications in the Prefab instance
PrefabUtility.RecordPrefabInstancePropertyModifications(this);
Debug.Assert(PrefabUtility.HasPrefabInstanceAnyOverrides(PrefabUtility.GetOutermostPrefabInstanceRoot(this), false));
// Apply Prefab instance modification to the Prefab asset
PrefabUtility.ApplyPrefabInstance(PrefabUtility.GetOutermostPrefabInstanceRoot(this), InteractionMode.AutomatedAction);
Debug.Assert(!PrefabUtility.HasPrefabInstanceAnyOverrides(PrefabUtility.GetOutermostPrefabInstanceRoot(this), false));
}
Simplified version:
Please find below a simplified working example:
[ContextMenu("PrefabTest")]
private void PrefabTest()
{
var prefabInstanceRoot = PrefabUtility.GetOutermostPrefabInstanceRoot(this);
TestString = Time.time.ToString();
PrefabUtility.RecordPrefabInstancePropertyModifications(this);
Debug.Assert(PrefabUtility.HasPrefabInstanceAnyOverrides(prefabInstanceRoot, false));
PrefabUtility.ApplyPrefabInstance(prefabInstanceRoot, InteractionMode.AutomatedAction);
Debug.Assert(!PrefabUtility.HasPrefabInstanceAnyOverrides(prefabInstanceRoot, false));
}