Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
3
Question by TheBikupan · Sep 15, 2014 at 02:54 PM · editorguilayout

How to tackle Mismatched LayoutGroup.DragPerform?

So I've done a Drag and Drop list for a custom inspector I'm working on, but I keep getting the error "GUILayout: Mismatched LayoutGroup.DragPerform" whenever I add an object through drag and drop. Locating the error leads me to a BeginHorizontal line. I guess it's related to how unity draws the inspector, but I'm pretty clueless as to how I should proceed.

Example code of the GUI:

 foldActivate = EditorGUILayout.Foldout (foldActivate, "Activate Elements: "+onTrigger.activate.Length.ToString());
         if (foldActivate)
         {
             onTrigger.activate = DragDrop (onTrigger.activate, "Drag'n'Drop\nActivate Object");
             for (int i = 0; i < onTrigger.activate.Length; i++)
             {
                 if (onTrigger.delayActivate.Length <= i)
                     onTrigger.delayActivate = addFloat (onTrigger.delayActivate);
                 EditorGUILayout.BeginHorizontal ();
                 onTrigger.activate[i] = EditorGUILayout.ObjectField (onTrigger.activate[i], typeof(Object), true);
                 onTrigger.delayActivate[i] = EditorGUILayout.FloatField (onTrigger.delayActivate[i], GUILayout.Width(30));
                 if (GUILayout.Button(deleteCon, GUILayout.Width (40)))
                 {
                     onTrigger.activate = deleteObj (onTrigger.activate, i);
                     onTrigger.delayActivate = deleteFloat (onTrigger.delayActivate, i);
                 }
                 EditorGUILayout.EndHorizontal ();
                 EditorGUILayout.Space ();
             }
             if (GUILayout.Button ("Add Activate"))
             {
                 onTrigger.activate = addObj (onTrigger.activate);
                 onTrigger.delayActivate = addFloat (onTrigger.delayActivate);
             }
 
         }

drag and drop function:

 private Object[] DragDrop(Object[] objList, string boxDesc)
     {
         var evt = Event.current;
         var dropArea = GUILayoutUtility.GetRect (0.0f, 35.0f, GUILayout.ExpandWidth (true));
         GUI.Box (dropArea, boxDesc);
         
         switch(evt.type)
         {
         case EventType.DragUpdated:
         case EventType.DragPerform:
             if (!dropArea.Contains (evt.mousePosition))
                 return objList;
             
             DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
             
             if (evt.type == EventType.DragPerform)
             {
                 DragAndDrop.AcceptDrag ();
                 
                 foreach (var draggedObject in DragAndDrop.objectReferences)
                 {
                     var go = draggedObject as GameObject;
                     if (!go)
                         continue;
 
                     List<Object> tempObj = new List<Object>();
                     tempObj.AddRange(objList);
                     tempObj.Add (go);
                     return tempObj.ToArray ();
                 }
             }
             Event.current.Use ();
             return objList;
         }
         return objList;
     }

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

3 Replies

· Add your reply
  • Sort: 
avatar image
1

Answer by ForceMagic · May 25, 2016 at 07:10 PM

I had the exact same error as you, found that thread on Unity forum that explain everything.

I thought I could only check for Event.current.type == EventType.Layout, but there's much more thing involved, so I had to maintain a bool _draggedFrame to ensure I do not draw the dynamic GUI on the same frame I filled my list...


See the Thread reference below (just in case the post got deleted/lost)

Originaly posted by UnLogic


This is a very common conceptual misunderstanding with immediate mode gui. It derives from the fact that OnGUI and OnInspectorGUI is called multiple times per frame. You can look at Event.current to see why OnGUI is called this time.

http://docs.unity3d.com/Documentation/ScriptReference/EventType.html

So each frame Unity starts with a Layout, does some Events(this is where your button code is triggered) and a Repaint. However the number and type of controls in the Repaint doesn't match the Layout and thats the problem.

What you're doing is adding a new gui control in the middle of a GUI pass. In general you should use the EventType.Layout for adding and removing controls.

 if (Event.current.type == EventType.Layout  _handle != null  _handle.status != RequestHandle.Status.Pending)
 {
      //Done...
      _loaded = true;
 }

So if you change _loaded(which effectively changes the gui layout) only when processing the Layout event everything should work as intended.

[2]: http://answers.unity3d.com/answers/1192419/view.html

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
0

Answer by Bunny83 · May 25, 2016 at 06:38 PM

Try putting this line:

 onTrigger.activate = DragDrop (onTrigger.activate, "Drag'n'Drop\nActivate Object");

after your for loop.

Since you're going to change the content of the array you get in trouble with the processing of the events.

As you might know every event that is handled by OnGUI / OnInspectorGUI is paired with a Layout event that is issued right before the event. During the layout event Unity collects information about all controls so it can calculate the size and position of every element. When the actual event is processed you have to ensure that you process the same elements as you did during the layout step.

By applying your changes to the object list at the end everything should be fine.

edit

If you want your drag&drop field to stay at the top, just make sure you do the changes at the end. You can simply use a temp variable for this:

 var newList = DragDrop (onTrigger.activate, "Drag'n'Drop\nActivate Object");
 for (int i = 0; i < onTrigger.activate.Length; i++)
 {
     // [...]
 }
 onTrigger.activate = newList;

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
0

Answer by warren- · Feb 10, 2017 at 04:34 AM

I'm not sure if this would work for everyone in all scenarios.

When I was getting the error Mismatched LayoutGroup.DragPerform it was due to the fact that I was updating a the Game Object array inside the Layout Event.

In an attempt to avoid the error Argument Exception: Getting control 1's position in a group with only 1 controls when doing DragPerform Aborting


I was using this code (After my GUI Game Object array change):

if (Event.current.type == EventType.DragPerform) { return; }

This worked fine, until I tried to incorporate EditorGUILayout.BeginHorizontal(); and its corresponding EditorGUILayout.EndHorizontal();

I can't speak for everyone elses code, but I think that might be part of the issue we've been having. (As I noticed the code above also utilizes the horizontal layouts.)

So my solution, was to only use the "Begin / End horizontal" calls, in all of the events, except for the Dragperform event.




if (Event.current.type != EventType.DragPerform) { EditorGUILayout.BeginHorizontal(); }
// Your Code to change GUI Content
if (Event.current.type != EventType.DragPerform) { EditorGUILayout.EndHorizontal(); }


if (Event.current.type == EventType.DragPerform) {
// Use this if you started your code with BeginVertical
// EditorGUILayout.EndVertical();
return;
}



This seemed to work fine for me, and I didn't have to store anything in arrays. Perhaps with more complicated drag/drop features though, you might have to do it differently.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

6 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Problem with editor layout on dual monitor setup 1 Answer

Drag & Drop EditorGUI 1 Answer

EditorGUILayout is cutting off my Toggle label 2 Answers

Get mouse position in Editor based on screen coordinates 1 Answer

Change the alingment of 2 GUILayout Label 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges