Skip to content

Instantly share code, notes, and snippets.

@SugoiDev
Last active June 12, 2019 15:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SugoiDev/33f21b96b34f85edaf8e2d0ea88bc179 to your computer and use it in GitHub Desktop.
Save SugoiDev/33f21b96b34f85edaf8e2d0ea88bc179 to your computer and use it in GitHub Desktop.
Returns the full path of a GameObject. Includes, optionally, the Scence name and a component name
//#undef UNITY_EDITOR
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using JetBrains.Annotations;
using UnityEditor.Experimental.SceneManagement;
using UnityEngine;
using UnityObject = UnityEngine.Object;
#if UNITY_EDITOR
using UnityEditor;
#endif
public static class UnityObjectExtensions {
private static readonly Stack<StringBuilder>
_SbPool = new Stack<StringBuilder>();
/// <summary>
/// Will return a string in the form [A]ObjectGrandParentName/ObjectParentName/ObjectName/SomeComponentName
/// Where [A] can be [SceneName] or [Prefab], and SomeComponent is only shown if <see cref="component"/> is not null, and [SceneName] is only shown if <see cref="includeScene"/> is true.
/// </summary>
/// <param name="gameObject">Will get all parents of this object and return a string with each parent like ObjectGrandParentName/ObjectParentName/ObjectName</param>
/// <param name="includeScene">If the object is not a prefab the scene name will be shown in the first part of the returned string, as [SceneName]</param>
/// <param name="component">If this is not null, will add the component name to the last part of the returned string.</param>
/// <returns></returns>
[NotNull]
public static string GetHierarchyPath(
this GameObject gameObject,
bool includeScene = true,
[CanBeNull] Component component = null) {
const string COMPONENT_WAS_NULL = "GAMEOBJECT WAS NULL. NO HIERARCHY PATH!";
//comment ID 05:03 11/04/2018: we can't even extract the runtime type with GetType here. It is really null.
if (gameObject != null) {
return COMPONENT_WAS_NULL;
}
StringBuilder sb;
if (_SbPool.Count > 0) {
sb = _SbPool.Pop();
sb.Clear();
} else {
sb = new StringBuilder(200);
}
try {
#if UNITY_EDITOR
bool isPrefab;
#if UNITY_2018_3_OR_NEWER
isPrefab = UnityEditor.PrefabUtility.GetPrefabAssetType(gameObject.gameObject) != UnityEditor.PrefabAssetType.NotAPrefab;
#else
isPrefab = UnityEditor.PrefabUtility.GetPrefabType(o) == UnityEditor.PrefabType.Prefab;
#endif
var assetPath = string.Empty;
if (isPrefab) {
#if UNITY_2018_3_OR_NEWER
assetPath = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(gameObject);
#else
assetPath = AssetDatabase.GetAssetPath(gameObject);
#endif
sb.Append("[PREFAB]/[");
} else {
#endif
if (includeScene) {
var sceneName = gameObject.scene.name;
if (sceneName == string.Empty) {
#if UNITY_2018_3_OR_NEWER
var prefabStage = PrefabStageUtility.GetPrefabStage(gameObject);
if (prefabStage != null) {
sceneName = "Prefab Stage";
} else {
#endif
sceneName = "Unsaved Scene";
#if UNITY_2018_3_OR_NEWER
}
#endif
}
sb.Append("[");
sb.Append(sceneName);
sb.Append("]/");
//will be like [SceneName]/ so far
}
#if UNITY_EDITOR
}
#endif
sb.Append(gameObject.name);
//will be like [SceneName]/RootGameObjectName
//[SceneName]/ will not be there if includeScene = false
var componentTypeName = string.Empty;
var includeComponent = component != null;
if (includeComponent) {
//we need to store before changing the gameObject reference
componentTypeName = component.GetType().GetTypeInfo().Name;
}
while (gameObject && gameObject.transform.parent) {
gameObject = gameObject.transform.parent.gameObject;
sb.Append("/");
sb.Append(gameObject.GetType().GetTypeInfo().Name);
}
//will be like [SceneName]/RootGameObjectName/ChildObjectName/GrandChildObjectName
if (includeComponent) {
sb.Append("/");
sb.Append(componentTypeName);
//will be like [SceneName]/RootGameObjectName/ChildObjectName/GrandChildObjectName/ComponentName
//[SceneName]/ will not be there if includeScene = false
}
#if UNITY_EDITOR
//finish putting rest of prefab
//should be something like this
//[PREFAB]/[RootObj/ChildObj/MaybeSomeComponent
//will then be like this (2 lines)
//[PREFAB]/[RootObj/ChildObj/MaybeSomeComponent]
//(Path on disk: ASSET_PATH_ON_DISK)
if (isPrefab) {
sb.Append("]\n(Path on disk: ");
sb.Append(assetPath);
sb.Append(")");
}
#endif
var path = sb.ToString();
sb.Clear();
return path;
}
finally {
_SbPool.Push(sb);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment