/// <summary> /// Returns all instances matching pathName /// </summary> /// <param name="pathName">is interpreted as either a path or a name</param> /// <returns></returns> /// <remarks> /// Counterpart to GameObject.Find(string) this returns all matching instances, instead of one. /// Names beginning with '/' indicate objects at the root of the scene. /// Names including '/' will be traversed as a path beginning from the first matched object. /// </remarks> public static GameObject[] FindAll(string pathName) { // PROBLEM: Actually, empty names are allowed... // Empty object names are not allowed if (pathName.Length == 0) { return(new GameObject[0]); } // This behavior is consistent with GameObject.Find() if (pathName[0] != '/') { return(NameFind(pathName)); } // Search by path // IMPORTANT: PathName names begin with the name of a GameObject, so "/" is dropped var path = new PathName(pathName.Substring(1), PathName.PathStep.Step.Path); var transformList = path.Find(); var gameObjectList = new List <GameObject>(); foreach (var transform in transformList) { gameObjectList.Add(transform.gameObject); } return(gameObjectList.ToArray()); }
public EditGameObject(GameObject gameObject) { if (useEditorAction) { #if UNITY_EDITOR editObjectType = GetGameObjectType(gameObject); switch (editObjectType) { case GameObjectType.Persistent: { // Load as PreviewScene Object editAssetPath = AssetDatabase.GetAssetPath(gameObject); editPrefab = PrefabUtility.LoadPrefabContents(editAssetPath); editObject = editPrefab; break; } case GameObjectType.Connected: { // Path to gameObject relative to prefab // NOTE: EditorSceneManager.IsPreviewSceneObject(editPrefab) == true var prefab = PrefabUtility.GetNearestPrefabInstanceRoot(gameObject); var path = new PathName(gameObject, prefab); // Instantiate a copy of prefab and locate copy of gameObject var asset = PrefabUtility.GetCorrespondingObjectFromSource(prefab); editAssetPath = AssetDatabase.GetAssetPath(asset); editPrefab = PrefabUtility.InstantiatePrefab(asset) as GameObject; var editObjectList = path.Find(editPrefab.transform); if (editObjectList.Length == 1) { editObject = editObjectList[0].gameObject; } break; } case GameObjectType.Instance: editObject = gameObject; break; } if (Application.isBatchMode) { EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene()); } else { // QUESTION: Does this work for prefabs? Undo.RecordObject(gameObject, $"Edit {gameObject.name}"); } #endif } else { editObject = gameObject; } }
/// <returns>an array of all GameObjects identified by path from parent</returns> /// <remarks> /// When parent = null the search begins with the scene root. /// </remarks> public static GameObject[] PathFind(PathName path, Transform parent = null) { var transformList = path.Find(parent); var gameObjectList = new List <GameObject>(); foreach (var transform in transformList) { gameObjectList.Add(transform.gameObject); } return(gameObjectList.ToArray()); }
// WARNING: If there is a name override, PathName will not resolve! // TODO: Find a way to clone prefab with overrides intact. // QUESTION: Is there a way to accomplish instatiation using object serializations? // Ideally, this would handle the connection and override persistence. // https://docs.unity3d.com/ScriptReference/SerializedObject.html // Construct, then iterate & copy? static GameObject InstantiateChild(GameObject original, GameObject parent) { GameObject child = null; // IMPORTANT: PrefabUtility.InstantiatePrefab applies only to assets, not to instances // IMPORTANT: PrefabUtility.GetCorrespondingObjectFromSource applies only to instances, not to assets var asset = PrefabUtility.GetCorrespondingObjectFromSource(parent); GameObject copy_asset = null; if (asset) { copy_asset = asset; } else { copy_asset = original; } var copy = PrefabUtility.InstantiatePrefab(copy_asset) as GameObject; if (parent != original) { var path = new PathName(original, parent); var find = path.Find(copy.transform); if (find.Length == 1) { child = find[0].gameObject; // Unpack to enable orphaning, only once since nearest root was instantiated var unpack = PrefabUtility.GetOutermostPrefabInstanceRoot(child); while (unpack) { PrefabUtility.UnpackPrefabInstance(unpack, PrefabUnpackMode.OutermostRoot, InteractionMode.AutomatedAction); unpack = PrefabUtility.GetOutermostPrefabInstanceRoot(child); } child.transform.SetParent(null); } EP.Destroy(copy); } else { child = copy; } return(child); }