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

  1. 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));
    }

Add comment

Log in to post comment

All about bugs

View bugs we have successfully reproduced, and vote for the bugs you want to see fixed most urgently.