Search Unity

[Solved, but not thanks to Unity] How can we find variants of base prefab from Editor script

Discussion in 'Prefabs' started by EvilGeorge, May 4, 2021.

?

Would you like to actually receive an answer to a clearly formulated question you post on the forum?

  1. Yes

    8 vote(s)
    33.3%
  2. Yes but with emphasis

    16 vote(s)
    66.7%
  1. EvilGeorge

    EvilGeorge

    Joined:
    Jun 22, 2019
    Posts:
    3
    See title - is there a way to detect if the prefab currently open in the PrefabStage has any existing variants? As in variant prefabs which are in the Assets. I'm sure Unity has this information because when updating the base prefab it needs to update the variant prefabs as well.

    I do not mind a hacky solution (e.g. parsing the prefab file itself) but would prefer a clean API call (though that is a tall order with the new prefab system...).

    Any ideas?

    Thanks in advance.
     
  2. EvilGeorge

    EvilGeorge

    Joined:
    Jun 22, 2019
    Posts:
    3
    Nevermind, found a solution to this myself. For any other inquisitive minds:
    • go through all the prefab assets;
    • check their type
      Code (CSharp):
      1. PrefabUtility.GetPrefabAssetType(yourLoadedPrefab)
    • if the prefab is a variant, get its parent
      Code (CSharp):
      1. PrefabUtility.GetCorrespondingObjectFromSource(yourLoadedPrefab)
    • (you can get the parent's asset path as well
      Code (CSharp):
      1. var parentPath = AssetDatabase.GetAssetPath(parentAsset)
    • collect this info as nodes for your table/tree (e.g. prefabPath, parentAssetPath, anything else you need/want);
    • build the table/tree from this information (i.e. parent variants to their bases);
    • now you can query the tree/table and find any prefab's variants.
     
  3. aydin_khp

    aydin_khp

    Joined:
    May 15, 2020
    Posts:
    29
    Hi!

    Where do you get parent's asset path? How do you find the parent in "if the prefab is a variant, get its parent"?
     
    sago3 likes this.
  4. najati

    najati

    Joined:
    Oct 23, 2017
    Posts:
    44
    Putting together the above response into the following worked for me:

    Code (CSharp):
    1.  
    2. public static IEnumerable<GameObject> FindAllPrefabVariants(string parentAssetPath) {
    3.    return FindAllPrefabVariants(AssetDatabase.LoadAssetAtPath<GameObject>(parentAssetPath));
    4. }
    5.  
    6. public static IEnumerable<GameObject> FindAllPrefabVariants(GameObject parent) {
    7.    return AssetDatabase.FindAssets("t:prefab").
    8.        Select(AssetDatabase.GUIDToAssetPath).
    9.        Select(AssetDatabase.LoadAssetAtPath<GameObject>).
    10.        Where(go => go != null).
    11.        Where(go => PrefabUtility.GetPrefabAssetType(go) == PrefabAssetType.Variant).
    12.        Where(go => PrefabUtility.GetCorrespondingObjectFromSource(go) == parent);
    13. }
    14.  
     
  5. halo123proplem

    halo123proplem

    Joined:
    Nov 26, 2019
    Posts:
    2
    Another could be to use the resources folder.

    var prefab = Resources.Load<GameObject>("Prefabs/" + name);

    Then you only need to define the name of the object instead of having a reference to it, then you could just append [1...10], melee, fast if you have different variations of the prefab.