Skip to content

Instantly share code, notes, and snippets.

@kraj0t
Created April 28, 2022 08:11
Show Gist options
  • Save kraj0t/41997eeaa5c7c12cc953056a93f28bd6 to your computer and use it in GitHub Desktop.
Save kraj0t/41997eeaa5c7c12cc953056a93f28bd6 to your computer and use it in GitHub Desktop.
[Unity] Retrieve a component's fileId and its gameObject's asset guid (if any)
/// <summary>Universal method for retrieving the fileId of a component inside a saved gameObject, and the guid to the file that contains the gameObject.
/// The gameObject could live in a prefab or in a scene, and the component does not need to be at the root gameObject of the prefab.</summary>
/// <param name="comp"></param>
/// <returns>A tuple containing the guid and the fileId of the component. Returns null if the component's gameObject has not been saved to a scene or a prefab.</returns>
public static Tuple<string, long> GetComponentIdentifiers(Component comp)
{
// Check if the component is the direct instance from the prefab.
// In the Editor, this means that the prefab asset is selected and the component is showing in the Inspector.
if (AssetDatabase.TryGetGUIDAndLocalFileIdentifier(comp, out string guid, out long fileId))
{
return new Tuple<string, long>(guid, fileId);
}
// Check if the component comes from a prefab that has been added to a scene.
var origComp = PrefabUtility.GetCorrespondingObjectFromSource(comp);
if (origComp != null && AssetDatabase.TryGetGUIDAndLocalFileIdentifier(origComp, out guid, out fileId))
{
return new Tuple<string, long>(guid, fileId);
}
// Last resort: check if the component comes from a prefab that is being edited in the prefab mode.
var prefabStage = PrefabStageUtility.GetPrefabStage(comp.gameObject);
if (prefabStage != null)
{
guid = AssetDatabase.AssetPathToGUID(prefabStage.prefabAssetPath);
if (!guid.IsNullOrEmpty())
{
fileId = GetLocalIdentifierInFile(comp);
return new Tuple<string, long>(guid, fileId);
}
}
Log.Error($"Have you saved the prefab? Is it a prefab? Component {comp.GetType().Name} in gameObject {comp.gameObject.name} has no GUID or fileID assigned!");
return null;
}
/// <summary>Also called fileID.</summary>
/// <param name="o"></param>
/// <returns>0 if not part of an asset. Otherwise, the fileID.</returns>
public static long GetLocalIdentifierInFile(UnityEngine.Object o)
{
// This code was downloaded from https://gist.github.com/peposso/4aa72435771d29ed20971916bdb6c12a
// That link contains other potentially useful methods that we might need in the future.
var inspectorModeInfo = typeof(SerializedObject).GetProperty("inspectorMode", BindingFlags.NonPublic | BindingFlags.Instance);
if (inspectorModeInfo != null)
{
var so = new SerializedObject(o);
inspectorModeInfo.SetValue(so, InspectorMode.Debug, null);
var prop = so.FindProperty("m_LocalIdentfierInFile");
return prop.longValue;
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment