0
\$\begingroup\$

The script is EditorWindow type.

private void OnGUI()
{
var selections = Selection.objects.OfType<GameObject>().ToList();
        if (selections.Count > 0)
        {
            for (var i = selections.Count - 1; i >= 0; --i)
            {
                var selected = selections[i];
                transformSelection.Add(selected.transform);
            }

            TransformSaver.SaveTransform(transformSelection.ToArray());

            tempTransformSelection = transformSelection;
            transformSelection = new List<Transform>();
        }
}

When I select with the mouse a object in the Editor Hierarchy it will keep making the loop nonstop since selections.Count is large then 0.

I tried to add after the loop:

selections = new List<GameObject>();

But it didn't help.

I want that it will make the loop and the whole code inside the if (selections.Count > 0) only once each time when selecting one or more objects in the editor.

If I select one object make the whole code once if I then selected another more object make the whole code over again for the two selected objects and so on but make it once. Now it will keep making the loop over and over again even if I didn't select more other objects.

Since in the editor the first object is still selected it will keep making the code the loop over and over again.

This is what I tried:

var selections = Selection.objects.OfType<GameObject>().ToList();
        if (selections.Count > 0 && isSelected == false)
        {
            for (var i = selections.Count - 1; i >= 0; --i)
            {
                var selected = selections[i];
                transformSelection.Add(selected.transform);
            }

            TransformSaver.SaveTransform(transformSelection.ToArray());

            tempTransformSelection = transformSelection;
            transformSelection = new List<Transform>();

            isSelected = true;
        }

The flag boolean isSelected is global variable and set to false as init.

UPDATE what I tried:

var selections = Selection.objects.OfType<GameObject>().ToList();
        int currentSelectionCount = selections.Count;
        if (currentSelectionCount != lastSelectionCount)
        {
            lastSelectionCount = currentSelectionCount;
            for (var i = 0; i < currentSelectionCount; ++i)
            {
                var selected = selections[i];
                transformSelection.Add(selected.transform);
            }

            TransformSaver.SaveTransform(transformSelection.ToArray());

            tempTransformSelection = transformSelection;
            transformSelection = new List<Transform>();

            Selection.objects = new UnityEngine.Object[0];
        }

But when I select object in the editor in hierarchy it's immediately unselecting the object since the line:

Selection.objects = new UnityEngine.Object[0];
\$\endgroup\$
  • 1
    \$\begingroup\$ A simple boolean could help. Set it to true once your loop is done, and enter the if scope if the boolean is false. \$\endgroup\$ – LifGwaethrakindo Aug 28 '18 at 21:14
  • 1
    \$\begingroup\$ @LinkWindcrafter I think that's worth sharing as an answer. Simple solutions are often good solutions. :) \$\endgroup\$ – DMGregory Aug 28 '18 at 22:05
  • \$\begingroup\$ @LinkWindcrafter I did it but the problem now is that the boolean flag is all the time true. The EditorWindow is still open and now when I select more other objects and using a break point I see that selections contains more objects but since the flag is true it will not enter to the loop when selecting new objects. The idea should be that if I selected one object and then selected more other objects enter to the loop and loop over only the objects that it didn't loop so far. \$\endgroup\$ – BenBen Shmil Aug 28 '18 at 22:33
  • \$\begingroup\$ @LinkWindcrafter I mean that it's working for a single object selection but what if I want to make a multiple selections ? So before using the flag it was working fine but then also making the loop nonstop. \$\endgroup\$ – BenBen Shmil Aug 28 '18 at 22:36
  • \$\begingroup\$ That happens because you don`t set isSelected flag back to false anywhere. That flag is false by default, when you select anything, it becomes true and then it never goes back to false which leads to infinite loop again because selections.Count is greater than 0 if any objects were selected. \$\endgroup\$ – RiotBr3aker Aug 29 '18 at 10:12
1
\$\begingroup\$

I don`t know what are you really trying to archive in OnGUI method logic but you problem can be solved easily by saving previous OnGUI call selection object count.

The main idea is to process same selection only once, to solve this we just need to compare previous and current selection size so we will need extra int variable:

public class FooBar : EditorWindow {

    [MenuItem("Window/Foobar")]
    public static void ShowWindow() {
        GetWindow<FooBar>("Foobar");
    }

    int lastSelectionCount = 0;

    private void OnGUI() {
        var selections = Selection.objects.OfType<GameObject>().ToList();
        int currentSelectionCount = selections.Count;
        if (currentSelectionCount != lastSelectionCount) {
            lastSelectionCount = currentSelectionCount;

            // your logic with loop and other stuff goes here
            for (var i = 0; i < currentSelectionCount; ++i) {
                Debug.Log(selections[i]);
            }
        }
    }
}

I just log selected objects here - you obviously can change everything to what you need.


But there's one major problem here - when you select 1 object and processed it, you'll have lastSelectionCount equal to 1 and when you select another object, selections.Count would be equal to 1, so it wouldn't be processed in OnGUI callback. In general, that won't work for any same number of selected objects.

The most trivial solution is to cancel current selection simply by clicking anywhere on the scene view but sometimes there's no place in your scene without objects so you can cancel selection after processing in OnGUI callback:

private void OnGUI() {
    var selections = Selection.objects.OfType<GameObject>().ToList();
    // your logic here, loops, file ops, anything
    for (var i = 0; i < selections.Count; ++i) {
        Debug.Log(selections[i]);
    }

    // after selected objects processing you can cancel selection with this
    Selection.objects = new Object[0];
}

As you can see, you don't need any checks at all. When selected objects are processed, selection is canceled and selections.Count would be equal to 0 on the next OnGUI call, so for-loop won`t be executed.


You also can cancel selection by button via first variant with saving selection count:

private void OnGUI() {
    var selections = Selection.objects.OfType<GameObject>().ToList();
    int currentSelectionCount = selections.Count;
    if (currentSelectionCount != lastSelectionCount) {
        lastSelectionCount = currentSelectionCount;

        // your logic with loop and other stuff goes here
        for (var i = 0; i < currentSelectionCount; ++i) {
            Debug.Log(selections[i]);
        }
    }

    if (GUILayout.Button("Cancel selection")) {
        Selection.objects = new Object[0];
    }
}
| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ The main idea is to save to a json file every object I select in the editor in the hierarchy save each object data like rotation position scale name parent...The saving part is working fine. The idea is to make something like undo for deleted objects. When deleted objects and closed the editor and then open the editor again to be able to re create the deleted objects. \$\endgroup\$ – BenBen Shmil Aug 29 '18 at 10:31
  • \$\begingroup\$ @BenBenShmil It doesn't change anything in OnGUI logic in my answer. You can do whatever you want after currentSelectionCount != lastSelectionCount check :) \$\endgroup\$ – RiotBr3aker Aug 29 '18 at 10:34
  • 1
    \$\begingroup\$ @BenBenShmil but there's a problem with selection, I'll update my answer, wait a bit. \$\endgroup\$ – RiotBr3aker Aug 29 '18 at 10:35
  • \$\begingroup\$ @BenBenShmil, updated, hope it helps, if you have any questions - feel free to ask :) \$\endgroup\$ – RiotBr3aker Aug 29 '18 at 10:47
  • \$\begingroup\$ I tried you updated code but the problem is with the line in the end: When I select object in the editor in hierarchy it's immediately unselecting the object since the line: Selection.objects = new UnityEngine.Object[0]; I see the object inspector for less then a second then it's unselected. \$\endgroup\$ – BenBen Shmil Aug 29 '18 at 10:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.