Ok, I've been bitten by this twice now, so I should ask. Coming from a Maya background I've written Editor scripts that use the order in which the objects were selected. However, in Unity, Selection.[any] returns the list in alphabetical order. Is there a builtin way (that I'm missing) to return the objects in the order that I selected them? Sam
Here's what I've got: the first object you select stays as the Active object (shows in Inspector). The upshot is you can determine the order when you're selecting two objects. Sam Code (csharp): @MenuItem("GameObject/Align Objects") //align the first object with the second static function AlignObjects () { var selectedObjects = Selection.transforms; if(selectedObjects.length == 2) { var moved : Transform; var target : Transform; if(selectedObjects[0] == Selection.activeTransform) { moved = selectedObjects[0]; target = selectedObjects[1]; }else { moved = selectedObjects[1]; target = selectedObjects[0]; } moved.position = target.position; moved.rotation = target.rotation; } }
I have also been bitten by this. I've been building some editor scripts to do alignment and even distribution of multiple selected objects. So far the alignment is working fine, but without a selection order, distribution often creates incorrect results. The only possible solution would be to track EditorWindow.OnSelectionChange events and manually keep track of the order within my script. I have created a feature request a proper selection order. Be sure to vote if you need this sort of thing: http://feedback.unity3d.com/unity/all-categories/1/hot/active/selection-order
Code (CSharp): using UnityEngine; using UnityEditor; using System.Collections; public class MoveToPos : EditorWindow { [MenuItem("GameObject/MoveToPosition")] static void MoveToPosition() { // first figure out which object was selected last. int last = 0; for (int i=0; i<Selection.transforms.Length; i++) { if (Selection.transforms[i] == Selection.activeTransform) { last = i; } } // next move all selected objects to the location of the last one. for (int i=0; i<Selection.transforms.Length; i++) { if (i != last) { Selection.transforms[i].position = Selection.transforms[last].position; } } } }
Hi there 8 years have pass, and still not native order selection.. Here is my editor windows contribution. You cant get a ordered selection everywhere. First launch the "TempleOne/Activate Selection Order Tracking" to create a windows intended to track selection change. Hide it where you want. Then use OrderSelection.Instance.OrderedSelection() where you want to get a ordered selection. It's my first Unity contribution, hope it will help. Ok with unity 5.4.1 Code (CSharp): using System.Collections.Generic; using UnityEditor; using UnityEngine; using Object = UnityEngine.Object; namespace Assets._Temple_One.Scripts.Editor { [ExecuteInEditMode] public class OrderSelection : EditorWindow { private readonly List<int> _listOrderedSelection= new List<int>(); [MenuItem ("TempleOne/Activate Selection Order Tracking")] static void Init () { var utilInstance = (OrderSelection) GetWindow (typeof (OrderSelection)); utilInstance.Show(); } public static OrderSelection Instance { get { return GetWindow< OrderSelection >(); } } public List<int> ListOrderedSelection { get { return _listOrderedSelection; } } public void OnSelectionChange() { var listIdObjectsCurrentSelection = new List<int>(); foreach (var iObject in Selection.instanceIDs) { listIdObjectsCurrentSelection.Add(iObject); } var listIdIndexesToDelete = new List<int>(); var count = -1; foreach (var iObject in _listOrderedSelection) { count += 1; if (! listIdObjectsCurrentSelection.Contains(iObject)) { listIdIndexesToDelete.Add(count); } } int indexPenalty = 0; foreach (var indexToDelete in listIdIndexesToDelete) { _listOrderedSelection.RemoveAt(indexToDelete-indexPenalty); indexPenalty ++; } foreach (var iObject in Selection.instanceIDs) { if (! _listOrderedSelection.Contains(iObject)) { _listOrderedSelection.Add(iObject); } } } public List<GameObject> OrderedSelection() { var ret = new List<GameObject>(); foreach (var iObject in _listOrderedSelection) { var obj = EditorUtility.InstanceIDToObject(iObject) ; var gameObj = GameObject.Find(obj.name); if (gameObj) { ret.Add(gameObj);} } return ret ; } } }
Here's another implementation using HashSets for diffing. Code (CSharp): // for ordered selection HashSet<GameObject> selectionSet = new HashSet<GameObject>(); HashSet<GameObject> newSet = new HashSet<GameObject>(); HashSet<GameObject> deleteSet = new HashSet<GameObject>(); List<GameObject> selectionOrdered = new List<GameObject>(); private void OnSelectionChange() { newSet.Clear(); newSet.UnionWith(Selection.gameObjects); deleteSet.Clear(); deleteSet.UnionWith(selectionSet); deleteSet.ExceptWith(newSet); foreach (var g in deleteSet) { selectionSet.Remove(g); selectionOrdered.Remove(g); } newSet.ExceptWith(selectionSet); foreach (var g in newSet) { selectionSet.Add(g); selectionOrdered.Add(g); } for (var i = 0; i < selectionOrdered.Count; ++i) { Debug.Log(i + " " + selectionOrdered[i].name); } }
They're clearly not going to fix it. There's really nothing else in the interface which considers selection order to be a useful concept, so there's no priority. I see how it's a useful concept in Blender, Maya or other apps. It just isn't in the architecture for Unity. On editor scripts I have written, I inspect all the items selected to figure out which one is the appropriate candidate to fill/update all the others. This inspection could be looking at parentage, number or types of components, hints in the names, or even where they are positioned.
There's nothing else in the interface which considers selection order to be useful because they don't have selection order. Boolean operations, Animation Sequencing, Layer sorting and management, alignment, structural sorting, call sorting, effect processing settings, render sorting... just to name a few... could all benefit from its existence and consideration. So could modelling, drawing and painting plugins. And all manner of other customisations users might want to create. But, more than that, any copy and paste operation would greatly benefit from the ability to pick/select in an order, cut/copy and then paste in that order. This is a feature just about everyone that's ever used After Effects has come to know and love.
*Sigh* came across this now too.. Doing a custom editor where I am sequencing timing "spawn delays" where I select the order and it increases based on the amount I select (in the order) but apparently not possible. So if delay is set to 0.5, obj 1 = 0 delay, obj 2 = 0.5, obj 3 = 1.0, etc. Would have been nice.
Just If someone came here for a short answer. Code (CSharp): GameObject[] localSelection = Selection.gameObjects; localSelection = localSelection.OrderBy(go => go.transform.GetSiblingIndex()).ToArray();
If you want to get the order of CTRL+CLICK, you may use Selection.objects instead of Selection.gameObjects and filter the object array by yourself. Selection.objects is the actual unfiltered selection from the Scene. https://docs.unity3d.com/ScriptReference/Selection.html Here is an example: Code (CSharp): public static GameObject[] GetOrderedSelectedGameobjects() { return Selection.objects.OfType<GameObject>().ToArray(); }