- Home /
(Solution) - Can't use GUILayout stuff in PropertyDrawer.OnGUI?
So, I was writing a property drawer for a type I had, everything went well, nothing out of the ordinary - everything is 'usual' - and by usual I mean I was writing everything using GUILayouts
! - I thought oh well, that's nice! they finally added support to GUILayout
stuff to property drawers! yay!
So I went ahead and asked a few friends just to confirm it, unfortunately, they didn't experience the same, they had ArgumentExceptions
, GUILayoutMismatch
and all sorts of nastiness.
I thought it was because they were using an older version of Unity, so I asked them to update, but still, the same results, GUILayout
is not working for them, but for me!
This is what I have:
[CustomPropertyDrawer(typeof(MyType))]
public class SerializedMBActionDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
GUILayout.Label("SOMETHING");
}
}
public class MyType : MonoBehaviour { }
Any idea why is this working for me, but not for them?
Answer by vexe · Mar 11, 2014 at 05:51 PM
EDIT: For a better solution altogether, I released my VFW for free. The framework contains a much better drawing API (which lets you write drawers for any object type) with a much better (allocation friendly) and faster GUI layout system.
Well, we made a little debugging session me and @Jamora - it's very obvious that I have something in my project, that is making it work.
So we started out from an empty project - I tried doing the same thing ^ - it didn't work! I got all the nasty stuff he got - and that proves it, there's something in my other project that made it work.
Next step was to import stuff step by step, I kept importing till I reached a point where I imported my Editor folder, and suddenly I got no errors!
So now it's definitely something in the editor folder from my old project, but what is it?
We kept deleting and deleting, util finally we figured it out!
It came down to this:
If you have a custom editor, for the MonoBehaviour
that contains an instance of the type you have the drawer for, it will work!
i.e.
public class Test : MonoBehaviour
{
public MyType type;
}
[CustomEditor(typeof(Test))]
public class TestEditor : Editor
{
// you don't even need to override OnInspectorGUI!
}
[System.Serializable]
public class MyType { }
[CustomDrawer(typeof(MyType))]
public class MyTypeDrawer : PropertyDrawer
{
public override void OnGUI(...)
{
GUILayout("WHO'S THE TOUGH GUY NOW, HUH?!");
}
}
And that's it! :)
I don't know if that's a bug in Unity or not, I don't know if other people know about this, but hey, it works :D
I'm not sure I have an explanation, other than: The property is being drawing inside the custom inspector of Test
?
Just thought I'd share.
Let me know if this worked for you or not.
But even if it didn't, we could still make our own GUILayouts
- if you look into any of the GUILayout
methods, like Button
for example you'll notice that the first thing they do, is just get the position of the button, and then call the corresponding GUI
method, in this case GUI.Button
and pass it the position - if we could get the position ourselves, then it's a piece of cake! - Unfortunately .NET Reflector is acting funny with me at the moment, if I manage to get it running and get my idea to life, I'll post it here as well.
I do not recommend however to 'heavily' depend on this 'hack'? I should say? - Because high chances are this wasn't intended - or maybe it was? who knows... It's subject to change, which if it does, breaks any code that depended on it. That's why it's better for one to make his own GUI
wrappers.
Very interesting - this does actually seem to work provided that, as you say, you have a custom Editor for the type that contains the property, otherwise the use of the layout methods in the property drawer will break it.
The really odd thing is that this will work even if the custom Editor does nothing but use the base implementation for OnInspectorGUI - makes you wonder what it could be doing differently from not defining an Editor at all. Hopefully Unity will soon add official support to layout methods in property drawers, this does make it seem like it could've been supported for some time now.
Good find vexe!
Has anyone discovered the reason for this? I need my class with a custom property drawer to draw itself in normal inspectors...I don't want to have to write a custom editor for every class!
@$$anonymous$$Orlando616 the reason? well, the only reason UT gave us is that GUILayout is slow and will cause performance issues if used in PropertyDrawers. So yeah... that's how they solve performance issues :) - I advice you to try VFW, you'll never look back.
I'll have to check that out...I don't think I have the time right now to incorporate any new plugins, but maybe next project. :)
similar question, with details on why having a CustomEditor for the monobehavior container resolves this: http://answers.unity3d.com/questions/1094473/strange-resolution-to-editor-error-explanation-req.html
Answer by crossfader64 · Sep 07, 2015 at 02:23 PM
@vexe: I stumbled upon this problem, too. But I didn't know that we usually can't use GUILayout. I created a custom Editor and property drawers for my serialized classes. When I added arrays of these classes I wondered, why the hell my array has so much empty space. (See picture) So after debugging I've found out, that if you don't use a custom Editor you'll get many errors when using GUILayout and I think the bug here is, that my custom Editor somehow let the errors disappear. In short: the combination of custom Editor and GUILayout seems to work but I think it is not intended to work. In my case the Editor for my array calculated its size for the amount of elements and because I used GUILayout in the property drawer my elements are getting rendered after the "reserved" space from my array.
Any solution on the extra space issue? I've been fighting this for 3 days now. I am using a custom PropertyDrawer to display a serialized class, and I am displaying an array of them inside a custom Editor. This is the ONLY reference I have been able to find about the extra space after the array index and I've spent many hours googling for it.
@$$anonymous$$adRobot: $$anonymous$$y solution for this was simply not using GUILayout, use GUI ins$$anonymous$$d. I know it's annoying to set the positions manually but at least I got rid of the extra spaces.
Just started with custom editor guis and stumbled across this. I guess its still as confusing as when this thread started...
Anyway i got rid of the spaces in an array of elements, drawn by a CustomPropertyDrawer, by adding
public override float GetPropertyHeight(SerializedProperty property, GUIContent label) { return 0f; }
Seems that GUI uses this info to add extra spaces, but GUILayout handles height separately.
Just started with custom editor guis and stumbled across this. I guess its still as confusing as when this thread started...
Anyway i got rid of the spaces in an array of elements, drawn by a CustomPropertyDrawer, by adding
public override float GetPropertyHeight(SerializedProperty property, GUIContent label) { return 0f; }
Seems that GUI uses this info to add extra spaces, but GUILayout handles height separately.
You can get rid of the space by doing:
GUILayout.Space(-position.height);
Actually, for the above that only works for the first element of an array. It causes issues otherwise. I'd suggest just overriding the height method:
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
return -2f; // this seems to match closest to non-property drawer version
}
Your answer
Follow this Question
Related Questions
EditorGUI like light explorer window 1 Answer
How to fix ArgumentException? 3 Answers
Fade out GUILayout Area? 1 Answer