Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Applying ObjectOverrides by script sometimes does not work?

Discussion in 'Prefabs' started by KevinHagen, Mar 23, 2019.

  1. KevinHagen

    KevinHagen

    Joined:
    Jul 5, 2017
    Posts:
    3
    Hey!

    I want to apply all property overrides made to a certain script on a PrefabInstance. The script is a component on that Instance (and the prefab asset) and when you're done editing the values, you press a button on that component. I dont want to use the "Apply Overrides" button unity provides, as I need to react to the changes made to that component (it contains adjacency rules, which are then propagated to the neighbours).
    So, for applying the changes I first look for its corresponding object by:

    Code (CSharp):
    1.             MyScript templateAsset = this;
    2.             if (!PrefabUtility.IsPartOfPrefabAsset(gameObject))
    3.             {
    4.                 GameObject asset = PrefabUtility.GetCorrespondingObjectFromSource(gameObject);
    5.                 if (asset != null)
    6.                     templateAsset = asset.GetComponent<MyScript >();
    7.             }
    I seem to do get the correct object everytime by this, so I am pretty certain this piece does not cause the error.
    I then try to apply the overriden values by:

    Code (CSharp):
    1.             if (PrefabUtility.IsPartOfPrefabInstance(gameObject))
    2.             {
    3.                 PrefabUtility.ApplyObjectOverride(this, PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(templateAsset), InteractionMode.AutomatedAction);
    4.             }
    which apparently does not work. The property is still marked as an override in the inspector afterwards and it also is not set in the inspector.
    By using

    Code (CSharp):
    1.             bool hasOverrides = PrefabUtility.HasPrefabInstanceAnyOverrides(gameObject, false);
    2.             List<ObjectOverride> overrides = PrefabUtility.GetObjectOverrides(gameObject, false);
    directly beforehand, I can still see, that the override is technically there and available. For some reasons it just does not get saved.

    Any ideas?

    Edit: I have just tried using the default "Apply Override" Button on the script. It also marks the script with an available override, but its not applicable either. That means, it must be related to overridden properties with references of scene objects, which indeed is the case. But all scene objects referenced in there are prefabs as well.
    I try getting their prefab reference with the following code:

    Code (CSharp):
    1.         private bool TryGetPrefabForNeighbourData(NeighbourData neighbourData)
    2.         {
    3.             if (!neighbourData.Neighbour)
    4.             {
    5.                 Debug.LogError("Neighbour for data " + neighbourData + " is null. Check Setup");
    6.                 return false;
    7.             }
    8.  
    9.             //Object already is the prefab
    10.             if (!PrefabUtility.IsPartOfPrefabInstance(neighbourData.Neighbour))
    11.             {
    12.                 return true;
    13.             }
    14.  
    15.             GameObject asset = PrefabUtility.GetCorrespondingObjectFromSource(neighbourData.Neighbour.gameObject);
    16.             if (asset == null)
    17.             {
    18.                 Debug.LogError("Couldn't find the Object prefab for data " + neighbourData + ". Object name was " + neighbourData.Neighbour.gameObject.name);
    19.                 return false;
    20.             }
    21.            
    22.             neighbourData.Neighbour = asset.GetComponent<MyScript>();
    23.             return true;
    24.         }
    25.  
    and it seems to find the correct prefab indeed. Maybe I'm missing something with the corresponding object?
     
    Last edited: Mar 23, 2019
  2. SteenLund

    SteenLund

    Unity Technologies

    Joined:
    Jan 20, 2011
    Posts:
    639
    Hi,

    Override that refers to a scene object or even another prefab in the scene can't be applied.
    Only reference inside the prefab itself or references to other assets can be applied.
     
  3. KevinHagen

    KevinHagen

    Joined:
    Jul 5, 2017
    Posts:
    3
    Hey,

    good, then I figured it out correctly. If I have another prefab in the scene, is there a convenient way to get its prefab asset? I thought it works with GetCorrespondingObjectFromSource, but it seems it doesn't?
     
  4. SteenLund

    SteenLund

    Unity Technologies

    Joined:
    Jan 20, 2011
    Posts:
    639
    Hmm, that should work. Can you share a minimal project?