Search Unity

Hahaha - selection order

Discussion in 'Scripting' started by sam_g, Jul 31, 2008.

  1. sam_g

    sam_g

    Joined:
    Mar 26, 2008
    Posts:
    10
    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
     
  2. seth_illgard

    seth_illgard

    Joined:
    Jul 22, 2008
    Posts:
    11
    ++ On this, I need this too.
     
  3. sam_g

    sam_g

    Joined:
    Mar 26, 2008
    Posts:
    10
    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):
    1. @MenuItem("GameObject/Align Objects")
    2. //align the first object with the second
    3.  
    4. static function AlignObjects ()
    5. {      
    6.     var selectedObjects = Selection.transforms;
    7.     if(selectedObjects.length == 2)
    8.     {
    9.         var moved : Transform;
    10.         var target : Transform;
    11.         if(selectedObjects[0] == Selection.activeTransform)
    12.         {  
    13.             moved =         selectedObjects[0];
    14.             target =        selectedObjects[1];
    15.         }else
    16.         {  
    17.             moved =         selectedObjects[1];
    18.             target =        selectedObjects[0];
    19.         }  
    20.         moved.position = target.position;
    21.         moved.rotation = target.rotation;
    22.     }
    23. }
     
    pengyq and D31 like this.
  4. Soviut

    Soviut

    Joined:
    Sep 17, 2012
    Posts:
    9
    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
     
    booferei likes this.
  5. n1ckfg

    n1ckfg

    Joined:
    Aug 11, 2014
    Posts:
    1
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEditor;
    3. using System.Collections;
    4.  
    5. public class MoveToPos : EditorWindow {
    6.    
    7.     [MenuItem("GameObject/MoveToPosition")]
    8.     static void MoveToPosition() {
    9.  
    10.         // first figure out which object was selected last.
    11.         int last = 0;
    12.         for (int i=0; i<Selection.transforms.Length; i++) {
    13.             if (Selection.transforms[i] ==  Selection.activeTransform) {
    14.                 last = i;
    15.             }
    16.         }
    17.  
    18.         // next move all selected objects to the location of the last one.
    19.         for (int i=0; i<Selection.transforms.Length; i++) {
    20.             if (i != last) {
    21.                 Selection.transforms[i].position = Selection.transforms[last].position;              
    22.             }
    23.         }
    24.  
    25.     }
    26.    
    27. }
     
    samana1407 likes this.
  6. xmanoux

    xmanoux

    Joined:
    Jul 9, 2015
    Posts:
    19
    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):
    1. using System.Collections.Generic;
    2. using UnityEditor;
    3. using UnityEngine;
    4. using Object = UnityEngine.Object;
    5.  
    6. namespace Assets._Temple_One.Scripts.Editor
    7. {
    8.  
    9.     [ExecuteInEditMode]
    10.     public class OrderSelection : EditorWindow {
    11.  
    12.         private readonly List<int>  _listOrderedSelection= new List<int>();
    13.  
    14.         [MenuItem ("TempleOne/Activate Selection Order Tracking")]
    15.         static void Init () {
    16.             var utilInstance = (OrderSelection) GetWindow (typeof (OrderSelection));
    17.             utilInstance.Show();
    18.         }
    19.  
    20.         public static OrderSelection Instance
    21.         {
    22.             get { return GetWindow< OrderSelection >(); }
    23.         }
    24.  
    25.         public List<int> ListOrderedSelection
    26.         {
    27.             get { return _listOrderedSelection; }
    28.         }
    29.  
    30.         public void OnSelectionChange()
    31.         {
    32.             var listIdObjectsCurrentSelection = new List<int>();
    33.             foreach (var iObject in Selection.instanceIDs)
    34.             {
    35.                 listIdObjectsCurrentSelection.Add(iObject);
    36.             }
    37.  
    38.             var listIdIndexesToDelete = new List<int>();
    39.             var count = -1;
    40.             foreach (var iObject in _listOrderedSelection)
    41.             {
    42.                 count += 1;
    43.                 if (! listIdObjectsCurrentSelection.Contains(iObject))
    44.                 {
    45.                     listIdIndexesToDelete.Add(count);
    46.                 }
    47.             }
    48.             int indexPenalty = 0;
    49.             foreach (var indexToDelete in listIdIndexesToDelete)
    50.             {
    51.                 _listOrderedSelection.RemoveAt(indexToDelete-indexPenalty);
    52.                 indexPenalty ++;
    53.             }
    54.             foreach (var iObject in Selection.instanceIDs)
    55.             {
    56.                 if (! _listOrderedSelection.Contains(iObject))
    57.                 {
    58.                     _listOrderedSelection.Add(iObject);
    59.                 }
    60.             }
    61.         }
    62.  
    63.    
    64.        public List<GameObject> OrderedSelection()
    65.        {
    66.               var ret = new List<GameObject>();
    67.               foreach (var iObject in _listOrderedSelection)
    68.               {
    69.                      var obj = EditorUtility.InstanceIDToObject(iObject) ;
    70.                      var gameObj = GameObject.Find(obj.name);
    71.                      if (gameObj)
    72.                      {
    73.                             ret.Add(gameObj);}
    74.                      }
    75.                      return ret ;
    76.               }
    77.       }
    78. }
    79.  
     
    Last edited: Dec 3, 2016
    alperen-adastec, Lohaz and doq like this.
  7. doq

    doq

    Joined:
    Aug 17, 2015
    Posts:
    121
    Here's another implementation using HashSets for diffing.
    Code (CSharp):
    1.         // for ordered selection
    2.         HashSet<GameObject> selectionSet = new HashSet<GameObject>();
    3.         HashSet<GameObject> newSet = new HashSet<GameObject>();
    4.         HashSet<GameObject> deleteSet = new HashSet<GameObject>();
    5.         List<GameObject> selectionOrdered = new List<GameObject>();
    6.  
    7.         private void OnSelectionChange()
    8.         {
    9.             newSet.Clear();
    10.             newSet.UnionWith(Selection.gameObjects);
    11.  
    12.             deleteSet.Clear();
    13.             deleteSet.UnionWith(selectionSet);
    14.             deleteSet.ExceptWith(newSet);
    15.  
    16.             foreach (var g in deleteSet)
    17.             {
    18.                 selectionSet.Remove(g);
    19.                 selectionOrdered.Remove(g);
    20.             }
    21.  
    22.             newSet.ExceptWith(selectionSet);
    23.             foreach (var g in newSet)
    24.             {
    25.                 selectionSet.Add(g);
    26.                 selectionOrdered.Add(g);
    27.             }
    28.  
    29.             for (var i = 0; i < selectionOrdered.Count; ++i)
    30.             {
    31.                 Debug.Log(i + " " + selectionOrdered[i].name);
    32.             }
    33.         }
    34.  
     
  8. NoiseFloorDev

    NoiseFloorDev

    Joined:
    May 13, 2017
    Posts:
    104
    It's definitely nice to search for why my script isn't working to find a topic titled "Hahaha"...
     
    Shrubokrant likes this.
  9. pointcache

    pointcache

    Joined:
    Sep 22, 2012
    Posts:
    579
    10 years later, still no selection order?
     
  10. halley

    halley

    Joined:
    Aug 26, 2013
    Posts:
    2,433
    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.
     
    Bunny83 likes this.
  11. Deeeds

    Deeeds

    Joined:
    Mar 15, 2018
    Posts:
    739
    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.
     
  12. CyRaid

    CyRaid

    Joined:
    Mar 31, 2015
    Posts:
    134
    *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.
     
  13. FiveXGames

    FiveXGames

    Joined:
    Apr 27, 2016
    Posts:
    43
    Just If someone came here for a short answer.

    Code (CSharp):
    1.  
    2. GameObject[] localSelection = Selection.gameObjects;
    3. localSelection = localSelection.OrderBy(go => go.transform.GetSiblingIndex()).ToArray();
    4.  
     
    Mandigondo likes this.
  14. lghfoo

    lghfoo

    Joined:
    Jul 10, 2019
    Posts:
    4
    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):
    1. public static GameObject[] GetOrderedSelectedGameobjects()
    2. {
    3.     return Selection.objects.OfType<GameObject>().ToArray();
    4. }
     
    Last edited: Oct 21, 2022
    Frump likes this.
  15. mookfasa

    mookfasa

    Joined:
    Dec 21, 2016
    Posts:
    46
    For anyone else wondering why this isnt working be sure to add

    Code (CSharp):
    1. using System.Linq;