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
- Prefab override popup is cropped/positioned incorrectly when more than one display is used and a higher display Scale is set
- Opening a dropdown on a small screen results in its instant closing when mouse cursor is pressed where the dropdown is going to be opened
- Only "ArgumentNullException: Value cannot be null" is displayed instead of all the actual errors when opening a project with numerous compilation errors
- MultiColumnListView and MultiColumnTreeView do not change selection on first input when focus is set by code
- SerializedProperty.DataEquals is returning false when SerializedProperty.EqualContents return true
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));
}