#↕️┃editor-extensions

1 messages · Page 78 of 1

fickle copper
#

I would preferably use CreateEditor as it seems to draw an entire different editor which should allow me to nest PropertyDrawers.

#

But i cant figure out how to move said editor to a desired position.

patent pebble
#

to control how an inspector looks, you need to use a Custom Editor

#

otherwise you are just gonna have Unity drawing everything in the default way

fickle copper
patent pebble
#

I mean it depends on what you want to do exactly

#

by the sound of it, you not only want to modify a single property, you want to also customize how other properties/fields are drawn on your inspector

patent pebble
#

and you also want to affect how lists are drawn, which I guess is gonna be a little bit more tricky than just moving fields around

#

hopefully someone with more knowledge can help, I'm kinda rusty on this topic

fickle copper
onyx harness
#

Have you tried using BeginArea?

fickle copper
#

Dont even know what BeginArea is

#

Ima google, give me a sec

onyx harness
#

It allows to draw GUILayout stuff in a given Rect

onyx harness
fickle copper
#

... Im actually crying rn..

onyx harness
#

Dont cry now, you might cry after if it does not work

#

BeginArea is not something I would call easy to use

onyx harness
#

It can kinda easily misbehave

fickle copper
#
private void ExposeScriptableObject(SerializedProperty property, Rect position)
{
            // Rect areaRect = new Rect(position.x, position.y + EditorGUIUtility.singleLineHeight, position.width,
            //     position.height * 10f);
            // GUILayout.BeginArea(areaRect);
            EditorGUILayout.BeginVertical("box");
            var e = UnityEditor.Editor.CreateEditor(property.objectReferenceValue);
            e.OnInspectorGUI();
            EditorGUILayout.EndVertical();
            // GUILayout.EndArea();
}

The commented out stuff is what i tried which resulted in the above image

onyx harness
#

Have you overload GetPropertyHeight?

fickle copper
onyx harness
#

The relevant child height is the Editor you want to draw

#

But start with tests, to make sure BeginArea behaves correctly

#

put a button in there

fickle copper
#

Inside the BeginArea?

onyx harness
#

yep

#

You have 2 ways of drawing an Editor, either by using its OnInspector() (GUILayout), or by using its SerializedProperty (GUI or GUILayout)

onyx harness
#

Show me the code

fickle copper
#

The code in question:

private void ExposeScriptableObject(SerializedProperty property, Rect position)
        {
            areaRect = new Rect(position.x, position.y + EditorGUIUtility.singleLineHeight, position.width,
                position.height * 10f);
            GUILayout.BeginArea(areaRect);
            GUILayout.Button("Test");
            GUILayout.EndArea();
        }
#

The height is massive but it shouldnt result into that

#

Here is the Height method too:

public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
        {
            SerializedObject serializedObject = new SerializedObject(property.objectReferenceValue);
            float baseHeight = base.GetPropertyHeight(property, label) + areaRect.height;
            return baseHeight;
        }
onyx harness
#

I guess its time to choose the 2nd way then

fickle copper
onyx harness
#

Draw its fields?

fickle copper
onyx harness
#

I think drawing through SerializedProperty is the easiest (Maybe the only) and most reliable way

#

Editor would have been nice, but it has one big issue

fickle copper
#

Thats what i think as well

onyx harness
#

If the Object targeted is being itself, you have infinite recursion

fickle copper
#

And targeting itself should be impossible in that field.

onyx harness
#

Even if you prevent this recusion with a if, I just need to point to a copy B, which will point to origin, kaboom

fickle copper
onyx harness
#
using UnityEditor;
using UnityEngine;

[CustomPropertyDrawer(typeof(NestedAttribute))]
public class NestedDrawer : PropertyDrawer
{
    SerializedObject so;

    public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
    {
        if (property.objectReferenceValue != null)
            this.so = new SerializedObject(property.objectReferenceValue);
        else
            this.so = null;

        if (this.so != null)
        {
            SerializedProperty it = this.so.GetIterator();

            it.Next(true);

            float totalHeight = 0F;

            while (it.NextVisible(false))
                totalHeight += EditorGUI.GetPropertyHeight(it, false);

            return base.GetPropertyHeight(property, label) + totalHeight;
        }

        return base.GetPropertyHeight(property, label);
    }

    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        Rect r = position;

        r.height = EditorGUI.GetPropertyHeight(property, false);
        EditorGUI.PropertyField(r, property, false);
        r.y += r.height;

        if (this.so == null)
            return;

        SerializedProperty it = this.so.GetIterator();

        it.Next(true);

        while (it.NextVisible(false))
        {
            r.height = EditorGUI.GetPropertyHeight(it, false);
            EditorGUI.PropertyField(r, it, false);
            r.y += r.height;
        }
    }
}```
#
using UnityEngine;

public class NestedAttribute : PropertyAttribute
{
}
#

Here is a basic example

patent pebble
#

I got curious about how what he wants could be implemented and this seems to work

#

(it's a bit messy and probably has some stuff that doesn't work 100% correctly) i haven't fully tested it

#

then you just use the attribute like this

[InsertNestedEditor] public Transform _transformForInsertedEditor;
#

@onyx harness oh I just saw yours, seems fairly similar

#

😅

onyx harness
#

🙂

patent pebble
#

@fickle copper seems like the example we both showed is the way to go. Unity doesn't seem to let us manually position nested editors created with CreateEditor

#

so you are gonna have to "mimic" the editor you want to insert, which tbh seems like a better option because you have more control and can customize better what data you want to show and how you show it

fickle copper
#

Also, i didnt think of using while loops to iterate through the properties.

#

@onyx harness Ill implement something similar to your solution later and report back what i get.

patent pebble
#

also remember to keep this properties in mind

EditorGUIUtility.standardVerticalSpacing
EditorGUIUtility.singleLineHeight
EditorStyles.inspectorDefaultMargins.padding.left
EditorStyles.inspectorFullWidthMargins.padding.left
#

very useful for getting correct spacing and positioning on inspectors

fickle copper
#

I know the first two

#

Didnt know the last two

patent pebble
#

yeah those 2 EditorStyles I use more for when I pop out inspectors into EditorWindows, but in some cases they are useful too for Drawers and Custom Editors

#

@onyx harness question, he mentioned he wanted to insert the nested editors in between elements of lists

#

is that possible with the examples we gave him?

onyx harness
#

I think not

patent pebble
#

yeah I was worried about that one, since I haven't messed around a lot with custom collections in the editor

#

but remaking the list to make it work should be possible, right? @onyx harness

onyx harness
#

Drawing an Editor means using GUILayout, to transpose GUILayout into the GUI world we need BeginArea.
In the picture below where I tried to understand the hell was happening, it seems it is drawing, but beneath everything.

patent pebble
#

oh lol

#

i was squinting at the image trying to decipher it 😅

onyx harness
#

Yeah yeah I know XD

patent pebble
#

I'm not really a fan of GUILayout.BeginArea

onyx harness
#

Me neither, it is a pain in the ass and unreliable

#

Useful for quick proto & test

patent pebble
#

i usually handle layout space with GUILayoutUtility.GetRect

#

but it's a little bit messy aswell

#

or just go full manual with GUI or EditorGUI

onyx harness
#

I dont use Layout at all for production 🙂

patent pebble
#

yeah haha i was gonna say

patent pebble
onyx harness
#

Perf and precision

patent pebble
#

hmmm

#

for the most part I just wing it with layout, since most of the stuff I make is tools for making my games

#

they are quite ugly and the positioning is... a little bit yikes xD

onyx harness
#

They are customize to your need and only you (or team) will use it, totally undestandable

patent pebble
#

yeah pretty much

#

if I was actually working with a team I'd polish them more

onyx harness
#

I publish them, I don't have much room for garbage ⛑️

fickle copper
#

@onyx harness The example you made works, but as you mentioned afterwards, it cant render any custom property drawers, so stacking the attribute is a big nono It can apparently draw other property drawers from a normal variable, but not on lists. (Im blind apparently)

#

But the other parts work

#

i have some very weird spacing in some variables

#

Not sure how to solve that part

onyx harness
fickle copper
#

Huh

onyx harness
#

The way PropertyDrawer deals with List.
It applies on the element itself not the contaning List

#

So you might want to handle that part yourself

fickle copper
#

Like how this scriptable object, being the property drawer, contains a list inside of it

#

From how i understand the system, it should treat it the same way editors do.

#

Since this is basically a nested editor

#

It makes sense with the scriptable object variables as they can actually stack

#

And as you said, property drawers draw an element in a list.

#

Which means that each element in said list should have a nested editor

#

But i digress. I am working on making said lists fancier with ReorderableLists

fickle copper
#

The current problem is; Im getting type is not a supported pptr value and a InvalidOperationException: The operation is not possible when moved past all properties (Next returned false) in these methods

 private void DrawReorderableList(bool disableFirstElement, ref Rect rect,
            SerializedProperty it)
        {
            //This if statement throws the type error
            if (!_reorderableListDictionary.ContainsKey(it.Copy().objectReferenceInstanceIDValue))
            {
                ReorderableList list = new ReorderableList(_so, it, true, true, true, true);
                list.elementHeightCallback += index => ElementHeightCallback(list, index);
                list.drawElementCallback += (elementRect, index, isActive, isFocused) =>
                    DrawElementCallback(elementRect, index, isActive, isFocused, list);
                list.drawHeaderCallback += (headerRect) => DrawHeaderCallback(headerRect, it);
                _reorderableListDictionary.Add(it.Copy().objectReferenceInstanceIDValue, list);
            }

            //This DoList call also throws the type error as well as the operation thingy.
            _reorderableListDictionary[it.Copy().objectReferenceInstanceIDValue].DoList(rect);
        }
onyx harness
#

I would bet the problem is earlier than this method

fickle copper
#

Not really, all the aformentioned errors lead to the if statements

#

The IsCorrectType() method works on the FieldType but not on the GetType() one,

#

Which makes me believe that i did something wrong

onyx harness
#

It is not because an error appears at this location that the error is the instruction at this line

fickle copper
#

Hmm

onyx harness
#

This property element.objectReferenceValue is throwing the error

fickle copper
#

Yes

onyx harness
#

Because you are calling it, while apparently the SerializedProperty (SP) is not suppose to be an Object

fickle copper
#

How would i check if it is an Object then?

#

By type?

onyx harness
#

PropertyType

#

from the SP

fickle copper
#

Hmm

#

Id like to draw this list in all arrays

#

Not just Object ones

#

So id need another ID property to use for the dictionary

#

Context; Im storing the ReorderableLists in a dictionary that contains an ID of said list. This way i can property Draw each list while also allowing for more lists to be created.

#

I have implemented something similar in some other part of my code base so i know this method works.

#

Not sure how i am going to do it in this context

#

Wondering if GetHashCode() works as an altenative for GetInstanceID()

#

Question: If i where to use GetHashCode() and change any variable in the type, will the HashCode stay the same?

waxen sandal
#

Depends on your hashcode implementation

#

But probably not

fickle copper
#

What about the default implementation?

waxen sandal
#

According to the docs, references yes but structs won't

fickle copper
#

I am currently reading through the docs for GetHashCode() and so far, this can work as an altenative for GetInstanceID(). My only concern is how said method interacts with changes in the editor. The last thing i want is to created 100 lists of the same type.

waxen sandal
#

Sounds like a bad idea to me

fickle copper
#

Why?

waxen sandal
#

Because hashcode is a terrible way to identify a object

fickle copper
#

Hmm

waxen sandal
#

2 objects can have the same hashcode and not be equal

fickle copper
#

true

#

How on earth would i identify objects then?

#

I cant use Guid as most of these objects are basic variables and arrays of the default types

waxen sandal
#

Idk what you're doing sooo 🤷

fickle copper
#

Some context

#

The pictures show that arrays fail to draw themselves correctly

waxen sandal
#

I don't have time to read though several hours of conversation

fickle copper
#

I am currently trying to create a Reorderable List that gets identified per variable

fickle copper
#

My current problem is finding an identification variable to use as a Key for the dictionary that stores the lists.

#

I want the key to be the variable itself so that i can redraw the list when its called

#

My problem can boil down to: How do i identify a variable and store said identification as a key?

fickle copper
#

This will probably be my last question: How do i create a region of color in the same way as how GUILayout does it with their BeginHorizontal/BeginVertical("box") methods.

#

For raw GUI.

fickle copper
patent pebble
#

Does anybody know if there's a built in way of dealing with ObjectFields and Stages?
I'm doing my own PreviewStage and opening in the same fashion you'd open a prefab editing stage.
The thing is, I'd like to have access via ObjectFields to the GameObjects from the main Stage.

#

Right now all I can get on the object picker from the ObjectField is the GameObjects of the Stage i'm currently in

#

I'd like to have both show on the object picker, no matter what Stage I'm on.
But I'm not sure if Unity has a way of doing that 😓

waxen sandal
#

I doubt that's possible, the whole idea of a stage is that it's isolated

opaque venture
#

Does anybody know if there is a way to get a list of all "My Assets" assets via script and then Import them? I found a way to get the installed packages (that follow the new package manager NPM style) found here: https://docs.unity3d.com/Manual/upm-api.html But what i would like to do is to write a custom importer (for the .unitypackage packages found in the asset store) that lists all my downloaded assets and then i can check multiple of them and import them one after another.

waxen sandal
#

If Client.List doens't return them then I wouldn't know of any api

#

You could look at the PM source

opaque venture
#

tried even with SearchAll, but dont getting assets, only the com.x.y packages.

waxen sandal
#

Source it is then

opaque venture
#

@waxen sandal sry, what do you mean with PM source? i checked the PackageManager Documentation, or what did u mean?

waxen sandal
#

No the source code should be available somewhere

#

So you can see waht they're doing

opaque venture
#

ah ok, yes, good point. always forgetting about that unity has everything public now.

chilly bough
#

I just finished slapping these scripts together and thought i would share it. It lets you create A numbered Array/List by replacing the element Name with its ID number and the next Strings data
Handy if you want to label your list/arrays but also quickly asses their ID

using UnityEngine;
using UnityEditor;
using System.Linq;

[CustomPropertyDrawer(typeof(LabeledArrayAttribute))]
public class LabeledArrayDrawer : PropertyDrawer {
    public override float GetPropertyHeight(SerializedProperty property, GUIContent label) {
        return EditorGUI.GetPropertyHeight(property, label);
    }

    public override void OnGUI(Rect rect, SerializedProperty property, GUIContent label) {
        EditorGUI.BeginProperty(rect, label, property);
        try {
            int pos = int.Parse(property.propertyPath.Split('[').LastOrDefault().TrimEnd(']'));
            EditorGUI.PropertyField(rect, property, new GUIContent(ObjectNames.NicifyVariableName(pos.ToString()+" : " + label.text)), true);
        } catch {
            EditorGUI.PropertyField(rect, property, label, true);
        }
        EditorGUI.EndProperty();
    }
}
public class LabeledArrayAttribute : PropertyAttribute {
    public LabeledArrayAttribute() { }
}```
EXAMPLE USEs
```css
using System.Collections.Generic;
using UnityEngine;

public class LabeledArrayExample : MonoBehaviour {
    [LabeledArray]
    public List<DialogueBranch> dialogueTree;

    [LabeledArray]
    public DialogueBranch[] dtree;

    [LabeledArray]
    public List<DialogueBranch> dialogueTreeGFGF = new List<DialogueBranch>();
}

[System.Serializable]
public class DialogueBranchEEE {
    //These are Each Option Per Dialogue Branch

    public string elementName = "";
    public string whoInfo = "";
    public string whatInfo;
}```
patent idol
#

how to draw reorderable list in custom inspector window? By reorderable list i mean like list from new version 2020.2 or something.

patent pebble
#

@patent idol is that the [Reorderable] attribute they added? or what?

patent idol
patent pebble
#

@patent idol there's an undocumented API called UnityEditorInternal that has the ReorderableList class

#

I've never used it so I don't know if that's exactly what you're looking for

#

I don't know how complete or stable it is, maybe someone who has used it can chime in and give their opinion

patent idol
#

thanks! i made my editor windows differently so it doesn't use lists but i'm sure i will use it in some way in the future

half scroll
#

I'm having an issue getting arrays within scriptableobjects to save and load. All the other data is loaded as expected but for some reason the arrays are empty when I load unity back up. Does anyone know why this could be?
(the Walk assets in the grid)

Before reloading unity
https://cdn.discordapp.com/attachments/701524254658658379/798279509186052147/unknown.png

And here is the YAML file showing the data from the array is being stored correctly
https://pastebin.com/sV5547ng

But for some reason when i reboot unity while the rest of the data is persistent as expected the arrays are empty?
https://cdn.discordapp.com/attachments/701524254658658379/798283033912016927/unknown.png

patent pebble
#

@half scroll are they single-dimension arrays?

half scroll
#

yeah

#

i tried replacing it with lists too but no luck with that either

#

oh oops i put the wrong image

patent pebble
#

you didn't share code either

#

we can only guess without knowing what you're doing exactly

half scroll
#

which code would u want to see? the class that stores the arrays

patent pebble
#

that'd be a good place to start

half scroll
patent pebble
#

have you debugged your AnimationClip[] through all steps of your process? I don't see you doing anything with your previewClip which gets serialized correctly

#

I see you do a bunch of stuff to the array tho, I'd guess you are doing something that makes you lose the data

half scroll
#

i'll try to make sure i'm not doing anything to lose it although in the YAML file i can see that the array is being serialized correctly so i guess something must be changing when unity loads up? the previewClip was to just make sure it wasnt the AnimationClip class that was the problem but is never used

split bridge
#

@half scroll looks like you're creating instances of Scriptableobjects but not serializing/saving them as assets? e.g. AssetDatabase.CreateAsset()

half scroll
#

ah i do that inside the editor script which is probably the wrong place to do that so i should probably move that

half scroll
#

thanks for the help here it was simply because i forgot to mark the layers and sets as serializeable

grim vine
#

Hello, i made this lovely little thing here using tiles. As of now i'm looking at 10k objects and the Scene file is about 28mb. Performance is also rapidly degrading. So i wanna try to explore ways to make this perform better.

#

i tried some binary read/write shinanigans saving only transform and guid, which i could reduce the scene to a mere 500kb

#

problems arose when i tried to load it. I don't know what's going on honestly. It loads and looks normal, but performance is much worse than the old scene. In editor i'm looking at 10fps

#
GameObject prefab;
if (prefabCache.ContainsKey(guidStr)) {
    prefab = prefabCache[guidStr];
}
else {
    var path2 = AssetDatabase.GUIDToAssetPath(guidStr);
    prefab = AssetDatabase.LoadAssetAtPath<GameObject>(path2);
    prefabCache[guidStr] = prefab;
}
var instance = (GameObject)PrefabUtility.InstantiatePrefab(prefab, ((Component)target).transform);
instance.transform.position = pos;
instance.transform.localEulerAngles = rot;
instance.transform.localScale = scale;```
#

is there any way to improve performance? Perhaps i should venture into ecs?

patent pebble
#

@grim vine are you telling us that scene is made up of ten thousand objects, each one of them with a sprite in it?

#

😶

grim vine
#

it's one of those modular packages

#

so each block is 1x1x1 usually

#

i will bake the meshes together, but that removes my ability to work on it 😦

patent pebble
#

I mean... if you are doing it to test performance with big amounts of GameObjects, that's fine and all

#

but if you are actually trying to use that for something you plan on releasing...

#

you should seriously reconsider

grim vine
#

so you mean baking it into one giant mesh wont achieve anything?

patent pebble
#

I'm not saying that, but if your performance is so bad that you cant even work properly in the Editor you should probably try to reduce performance costs, maybe reducing modularity

#

I'd just profile the game entirely to see if the gameobject count is even the problem

#

Maybe you arent instancing materials and your draw calls are skyrocketing

grim vine
#

yes ok.

#

i tried spawning all the objects, but instead of the prefab, just a cube

#

and performance was better

patent pebble
#

That scene is relatively simple, and by what you've said it seems like that's not a fully functional game with characters and moving things and systems and Ai, etc

grim vine
#

i have these boxes that basically disables all objects within, that improves the fps a lot. But the scene file still grows rapidly

patent pebble
#

If performance is that bad at this scope, what's gonna happen when you try to make it into a fully fledged game? 😅

grim vine
#

good point

#

gonna need a lot of custom tools to make it run properly

patent pebble
#

I don't think the lack of custom tools is your main problem here. But I don't know the context of your project so I can't really tell

#

If I were you i'd just first go over basic optimization concepts and research that topic

grim vine
#

well i already know a bit of it. I just haven't delved into any implementation, would like to delve into the mesh merging. Making 1 big mesh seperated into submeshes as per their material is not too complicated

#

but i would probably like to have some kind of chunking so i can hide and show them on the fly

#

so, if i just made like a 20x20x20 chunks and then seriazled the blocks into a base64 stream in the scene i could cut the scenesize by 90%

#

and then had the ability to "unlock" a chunk

#

which turns it into gameobjects

#

so i can work on it

#
  • base64 so i can save it in the scene file itself as a string field
#

i tested already with file sizes.
Base64 = 750kb
Binary = 520kb

#

saving the scene took a less than a second, but loading the scene took half a minute.

#

and significantly worse fps

#
  • worse than Unity's native scene file
#

the bottleneck is prefab instantiation

patent pebble
#

well instantiating 10k prefabs seems like i'd take a while

grim vine
#

yeah, i wonder how the editor does it, perhaps they bypass instantiation.

#

i'll try to write a mesh merger 😂

waxen sandal
#

I doubt Unity Tilemap instantiates tiles as gameobjects'

#

(not that I have used it)

#

They probably have some high performance data format that they can query based on location

#

Then just render the nearby tiles without creating gameobjects

#

Or perhaps they do but do a lot of batching/pooling/combining sprites

grim vine
#

Unity's tilemap is for 2D though?

waxen sandal
#

lots of similar concepts apply

grim vine
#

i think for tilemaps you allocate a single block to contain the entire atlas and just blit with offset+size from that surface to the a buffer.

#

for 3d models i heard the words of something called GPU instancing, but it sounds low level and Unity may not even provide access to the API

split kraken
#

Hey, I have a problem with Unity, it seems after an hour of work on my EditorWindow, unity seems to use A LOT of CPU, and I can't seem to profile the issue...

#

How can I know which Update functions the Editor calls? Its not showing anything related to my code...

waxen sandal
#

Deep profile

split kraken
#

Used it now

#

my function is really low on CPU

#

Anyone know what is SceneTracker in the profiler?

#

And what could cause it to take a lot of CPU time?

#

I opened a new scene (empty scene) and now SceneTracker is WAY higher...

#

Again, empty scene, nothing but a camera and a light source, and, no EditorWindow I created are used

#

meaning everything is closed

#

This never happened to me before with Unity, its the first time after I started playing with the GUI system, but I closed the window using it and its still happening, and I just updated to 2019.4.17f, could be a bug maybe?

shell beacon
#

hmm.. guys why can't I hide AudioSource icon from my scene view? 🤔

split kraken
#

Ok, after some profiling, I found that changing the SceneView pivot property, will cause a really huge stall

#

SceneView.duringSceneGui += DuringSceneGUI;
If you use this, and try to set the pivot there, you will see the issue

#

I could probably set it up once every time I want to move the view, but that just a hacky way, why would changing the pivot cause stuff like that?

#

Okay.. so it seems setting .pivot is wrong, you should use LookAt (for some odd reason, LookAt change the position AND view)

#

I believe this is a bug, you should be able to change the position of the view camera...

split bridge
#

I'm going to guess that over time you're adding this listener multiple times

split kraken
#

@split bridge no..

#

OnEnable and deleted on OnDisable

#

I reported a bug

#

Changing the pivot causes unity to freak out

#

using LookAt works great but note it comes with animating the camera

trim heart
#

@severe python do you know how to create custom skins for the new UI toolkit?

severe python
#

Read the documentation and about css?

severe python
#

Not trying to be unhelpful, thats just a basic question best answered by the documentation available in Unitys manual. Additionally looking at UIBuilder and its documentation would also probably be helpful

split kraken
#

Anyone know how to use GUILayoutUtility.GetRect to create two vertical panels?

#

This is what I tried:

        Rect leftPanel = GUILayoutUtility.GetRect(
            GUIContent.none,
            "button",
            GUILayout.ExpandHeight(true),
            GUILayout.Width(250));

        Rect rightPanel = GUILayoutUtility.GetRect(
            GUIContent.none,
            "button",
            GUILayout.ExpandHeight(true),
            GUILayout.ExpandWidth(true));

        LeapGUIExtensions.DrawTexture(leftPanel, Color.red);
        LeapGUIExtensions.DrawTexture(rightPanel, Color.blue);
#

I want the blue rectangle to be side by side with the red rectangle

#

I could create it using Rect alone, and assign values I want, but I wanted to know if there is a way to do it with Unity's layout system

fickle copper
#
  • GUILayout.Expand(Height/Width) only expands in acordance to other UI Elements. Im pretty sure there is a GUILayout.(Min/Max) method for you to use. Play around with those and see what you get
fickle copper
fickle copper
#

Also i doubt LeapGUIExtensions.DrawTexture(rect, color) would work with that layout method.

#

since it requires a rect.

onyx harness
#

Clearly, but he wants to stay with layout and the stuff

fickle copper
#

true.

fickle copper
# onyx harness Begin/End horizontal layout

Also, he/she wanted a vertical layout so BeginVertical/EndVertical is the way to go if he/she wants to use the layout. (I clearly forgot how those work since i barely use em...)

onyx harness
patent pebble
#

i like using scopes instead of Begin/End methods. It's a lot more readable

patent pebble
#
using (new GUILayout.HorizontalScope())
{
      GUILayout.Button("I'm the first button");
      GUILayout.Button("I'm to the right");
}
patent pebble
#

that does the same as BeginHorizontal/EndHorizontal

onyx harness
#

Except the Change scope

#

Which I find giganticly ugly

patent pebble
#

there's a lot of different useful Scope classes for the GUI stuff: horizontal, vertical, scrollview, area, disabled, fadegroup, togglegroup, indentlevel, property, iconsize ...

#

I mostly just use the horizontal and vertical ones, but the others are useful too

onyx harness
#

I've never used the property one

patent pebble
#

I've used it sparsely to implement custom controls when I wanted them to support serializedproperties

#

I can't remember exactly the cases, but it was useful

#

or maybe it wasn't custom controls from scratch, but controls made of other already existing controls

#

can't remember exactly, it's been a while

#

it was something similar to that

#

for GUI controls that don't handle SerializedProperty you can wrap them inside BeginProperty and EndProperty as shown in the example below. You can use this for your own custom GUI controls too.

waxen sandal
#

I saw that last week or so and decided that the nested would be too much using that

#

Tbh I don't see why unity doesn't do begin /end property by default

patent pebble
#

A recurring theme I've seen with APIs they roll out for Editor extensions is they tend to leave some loose ends here and there, specially on things that won't be widely used

#

it feels like they do that a lot recently

#

release something that on the surface seems like a very useful and complete API but when you dig into it for more specific usage you start to need workarounds and custom tools to make it work

severe python
#

wait, are you telling me I can have actual scope for Begin/End Horizontal/Vertical insteaqd of having to make 2 method calls?

#

And now I'm realizing just how trivial that would have been to implement all along if i had just taken 2 seconds to think about it...

onyx harness
#

Avoiding 2 methods calls is an illusion, but yeah scope are more reliable & better & smoother & fluider

severe python
#

Yeah, its definitely an illusion, I should have put it differently, I was speaking in terms of code readability

#

Man mind blown, thanks ya'll for enlightening me

patent pebble
#

they improve readability dramatically when using nested horizontals/verticals

#

when I started learning GUI it was a nightmare to do with GUILayout

onyx harness
#

Even without scope, I did put brackets to indent to keep readability

patent pebble
#

yeah

onyx harness
#

The real gain using the scope is the reliability

#

You cant go wrong

patent pebble
#

yeah saves a lot of time not having to debug and go over stuff all the time to see what's messing up your GUI

#

specially when doing quick and dirty ui prototypes

severe python
#

will a using statement always dispose?

#

such as, if an unhandled exception occurs inside a using statement, can that prevent the dispose?

onyx harness
#

Yes

patent pebble
onyx harness
#

It will execute no matter what

severe python
#

superb

#

a color scope?!

onyx harness
#

Like such?

using System;
using System.Collections.Generic;
using UnityEngine;

namespace NGToolsEditor
{
    public sealed class ColorContentRestorer : IDisposable, IEqualityComparer<Color>
    {
        private static Dictionary<Color, ColorContentRestorer>    cached = new Dictionary<Color, ColorContentRestorer>(new ColorContentRestorer());

        private Color    last;

        public static ColorContentRestorer    Get(bool condition, Color color)
        {
            return condition ? ColorContentRestorer.Get(color) : null;
        }

        public static ColorContentRestorer    Get(Color color)
        {
            ColorContentRestorer    restorer;

            if (ColorContentRestorer.cached.TryGetValue(color, out restorer) == false)
            {
                restorer = new ColorContentRestorer();
                ColorContentRestorer.cached.Add(color, restorer);
            }

            restorer.Set(color);

            return restorer;
        }


        public IDisposable    Set(Color color)
        {
            this.last = GUI.contentColor;
            GUI.contentColor = color;

            return this;
        }

        public IDisposable    Set(float r, float g, float b, float a)
        {
            this.last = GUI.contentColor;
            GUI.contentColor = new Color(r, g, b, a);

            return this;
        }

        public void    Dispose()
        {
            GUI.contentColor = this.last;
        }

        bool IEqualityComparer<Color>.Equals(Color x, Color y)
        {
            return x.a == y.a && x.r == y.r && x.g == y.g && x.b == y.b;
        }

        int IEqualityComparer<Color>.GetHashCode(Color obj)
        {
            return obj.GetHashCode();
        }
    }
}
#

dont know if Unity has built-ins

#

I made one for indentLevel, until I discover they made one built-in

patent pebble
#

there's this on the source

        internal struct ColorScope : IDisposable
        {
            private bool m_Disposed;
            private Color m_PreviousColor;

            public ColorScope(Color newColor)
            {
                m_Disposed = false;
                m_PreviousColor = GUI.color;
                GUI.color = newColor;
            }

            public ColorScope(float r, float g, float b, float a = 1.0f) : this(new Color(r, g, b, a))
            {
            }

            public void Dispose()
            {
                if (m_Disposed)
                    return;
                m_Disposed = true;
                GUI.color = m_PreviousColor;
            }
        }
#

I don't think it's actually exposed or documented

#

they use it here

        private void DrawSplitLine(float y)
        {
            Rect position = new Rect(0, y - Styles.lineSeparatorOffset, m_Pos.width + 1, 1);
            using (new GUI.ColorScope(Styles.lineSeparatorColor * GUI.color))
                GUI.DrawTexture(position, EditorGUIUtility.whiteTexture);
        }
onyx harness
patent pebble
#

i think it's all internal

#

I wish Unity let us use all those cool things they use internally 😓

onyx harness
#

It's just slightly more annoying/cumbersome, but Reflection is our best ally

patent pebble
#

yeah reflection seems like it's the last hope for a lot of things like this

#

i'd rather just have it given to us rather than having to finagle our way into their features, but well... that's Unity 🙃

severe python
#

publically facing non focusing popups that can have custom content when

severe python
#

I've been setting up a bunch of code to nest ScriptableObjects into other ScriptableObjects, not a hierarchical setup only a single layer, for example, I have a ScriptableObject, Pipeline, which I can add PipelineJobs to, which are also ScriptableObjects.
Is there any reason why I should be wary about this?

waxen sandal
#

Except for your code being annoying, not erally

split bridge
#

speaking as the author of btagged... really really annoying 🤣

#

e.g.

  • very hard/impossible to support undo properly
  • got to play lots of tricks to refresh the project window properly with e.g. an asset rename or reparent
  • tricks change per Unity version
bold skiff
patent pebble
#

@bold skiff update as in repainting the window?

bold skiff
#

Update as in throw a new animation into one of those slots, click the update button, it updates the animatorcontroller

patent pebble
#

oh, no idea then

#

it's been a while since i've done animation stuff

bold skiff
#

Yah thats where I'm stuck to, haha

#

I was hoping it would be real easy as in reassigning the variable, but apparently its not.

patent pebble
#

@bold skiff I mean, animator controllers are assets, you probably have to do something with AssetDatabase?

#

just throwing random ideas

bold skiff
#

Well I already load up the controller when its put into the FX box. I can access that controller, but no idea how to reassign a specific one.

severe python
#

@split bridge I ran into some issues with updating, but I just really meant doing things in the right order and pushing updates/saves at the right times

#

The main issue I've been having, is that the sub-assets are also added to an Array on the parent object, and I had to change that array, and I put in a FormerlySerializedAs property, but it didn't work

#

so stuff just falls apart when there are significant api changes, but those should be avoided anyways

gloomy chasm
#

So, I got a odd problem. I have a list in a class, and a list of that class, which all works fine. However, when using ReorderableList in a PropertyDrawer for the class to draw the list that is in the class, it seems to use the property for the first element in the top list, the one that contains the classes. Any ideas why this would be?

#

(Well, assuming that makes sense)

#

Well, apparently only one property drawer is created for them.... Storing the ReorderableLists in a dictionary in the PropertyDrawer works. Bit odd, looking.
Good old Debug.Log() comes through again.

severe python
#

I've got a custom inspector editor which is rendering a composable type, and in that type I have an array which represents the composition elements. Each of those elements must derive from ScriptableObject, but may be of varying types.
To that end i want each of those objects to be rendered normally, and use a PropertyDrawer if one is available

#

What call do I use in order to allow a PropertyDrawer to be used to render the element?

#

I do feel like I'm overlooking an important aspect of this

#

like, a PropertyDrawer isn't used to render an entire type like an Inspector Editor

gloomy chasm
#

Can you just use EditorGUI.PropertyField()?
Or are you looking for Editor.CreateEditor()?

severe python
#

Maybe I am looking for create editor... but I also am not?

gloomy chasm
#

I am not quite clear on what you are wanting.

severe python
#

So CreateEditor would create the standard inspector unless a custom editor is available, which makes sense, however I specifically don't want to render the Script field

#

Maybe this would help

#

So, the bottom image is an old version of a system I used to compose data together for packaging/building/etc

#

I want to recreate the Manifest Dependencies area for the "Thunderstore Manifest" element in the top image

gloomy chasm
#

@severe python I use this sometimes

public static class InspectorExtentions
{
    /// <summary>
    /// Draws the base inspector without the "Script" field and the option to exclude other fields as well.
    /// </summary>
    /// <param name="excludeFields">The fields to exclude.</param>
    public static void OnInspectorGUIWithout(this Editor inspector, params string[] excludeFields)
    {
        SerializedProperty Iterator = inspector.serializedObject.GetIterator();

        Iterator.NextVisible(true);

        while (Iterator.NextVisible(false))
        {
            if (!excludeFields.Contains(Iterator.name))
                EditorGUILayout.PropertyField(Iterator, true);
        }
    }
}
severe python
#

oh maybe I'm just being dumb, perhaps I should be making a PropertyDrawer for an Attribute I can use on a List<String> field to get the desired effect

#

I'm alreading doing that really, though in much more convoluted code

#

though this is a good bit cleaner

visual stag
#

In an Editor you can call DrawPropertiesExcluding

gloomy chasm
visual stag
#

Forever

#

It's undocumented

#

or at least, it was

gloomy chasm
#

For shame! Well thank you for the heads up!

severe python
#

heh, so its useful, but its useless for me my use case I think lol

#

since I would need to create an editor, and then call that, but its a protected method so I can't call it externally

gloomy chasm
#

Nah, you just override OnInspectorGUI and call it in there.

severe python
#

That means I need to make an Editor for every type

#

eg, a new default editor

#

or an editor for every type I want to do that for

gloomy chasm
#

There is always reflection.

severe python
#

oh I guess I can just specify the editor to use...

#

hmmmmm

gloomy chasm
#

I just want to double check. There isn't any good way to get the value of a SerializedProperty that is a custom class that is not a UnityEngien.Object?

severe python
#

No, I can't just specify the editor to use, that means that more appropriate editors will not apply

visual stag
#

I have a trash helper method that I need to rewrite to do it

#

I thiiiiink there's some internal unity ones that may be more reliable that you can reflect to, but I don't have them at hand

gloomy chasm
#

Hey, I got a related question. Is there any reason that that using the setManagedReference property would create a new instance of the value being assigned when used with the [SerializeReference]?

visual stag
#

I have no answer for you because I spent a week writing a graph framework that suffered from that issue. I've reported many bugs with SerializeReference

severe python
#

How would I get the size of the result of DrawPropertiesExcluding

visual stag
#

I ended up using a GUID lookup for part of it instead of SR and it fixed my issues

severe python
#

I technically already, have it solved through a custom solution, but I imagine there must be a better way

#

                    ExecuteField(serializedObject.GetIterator().Copy(), sp =>
                    {
                        height += standardSize;
                        if (sp.isExpanded)
                            height += standardSize * (sp.arraySize + 1);
                    });
        private static void ExecuteField(SerializedProperty property, Action<SerializedProperty> action)
        {
            if (property != null && property.NextVisible(true))
            {
                do
                {
                    if ("m_script".Equals(property.name, System.StringComparison.OrdinalIgnoreCase)) continue;
                    action(property);
                }
                while (property.NextVisible(false));
            }
        }
gloomy chasm
visual stag
#

I think you have to do the property loop and GetPropertyHeight for each of them

severe python
#

I have this setup going on right now

visual stag
#

The bugs I reported were both crashes

gloomy chasm
#

I guess someone has got to. I will do it sometime this week I guess. I am going to have to include some ugly reflection stuff to get the value of a SerializedProperty like I am now, oh well.

severe python
#

I thought they fixed that issue with SerializedReference :/

visual stag
#

I also reported a Property Drawer bug and got

it's already fixed in Unity 2021.2.0a1 and above.

#

Thanks for opening that backport though 😄

gloomy chasm
#

Will they backport the fixes to 2019.4 you think? It is an LTS after all...

visual stag
#

I'm dev'ing any SerializeReference stuff on 2020/2021 tbh

#

There's just so many serialization changes that are great there that will not be backported

#

like the generic serialization change

#

But I am also not doing it to make a game for release, so I can see why you wouldn't do that regularly 😄

gloomy chasm
visual stag
#

:/ good luck with SerializeReference then! I'm not going hard into it outside of personal projects because it seems to be quite buggy sadly

#

It's probably really nice in simple use cases

severe python
#

which isn't where you ever need it

visual stag
#

but trying to do something complex in it has really just exhausted me

gloomy chasm
#

I used it for some contract work...

visual stag
#

Eh, it's nice to serialize a simple array of different subtypes

#

which is a common enough thing that I'd switch to doing as I feel it'd be safe

severe python
#

I ran into basically the exact same problem you did, I built a hierarchical object graph and I tried to use SerializeReference, i ran into endless different little issues, but primarily an issue with array growth causing new elements to reference an existing object which caused endless issues

visual stag
#

but nesting and cross referencing seems iffy

severe python
#

admittedly its not a simple project, I'm very much over simplifying what that is, the whole thing doesn't serialize well because properties access internal data structures for their data which may end up collecting data from other objects

visual stag
#

At least they do seem to be prioritising bugs with it above my experience with other things

gloomy chasm
#

If it wasn't such a massive undertaking it would be amazing if they rewrite their serialization system. But I know that will never happen.

visual stag
#

Unity 2 Electric Boogaloo is a real dream

severe python
#

they are taking an iterative approach to fixing weaknesses in it, thats honestly good enough for me

tropic rampart
#

So I feel like this is probably a really silly question/mistake

#

But

#
using UnityEngine;
using UnityEditor;

[CustomPropertyDrawer(typeof(HexCoordinates))]
public class HexCoordinatesDrawer : PropertyDrawer {
    public override void OnGUI (Rect position, SerializedProperty property,
                                GUIContent label) {
        HexCoordinates coordinates = new HexCoordinates(
            property.FindPropertyRelative("x").intValue,
            property.FindPropertyRelative("z").intValue);

        position = EditorGUI.PrefixLabel(position, label);
        GUI.Label(position, coordinates.ToString());
    }
}```
#

Anyone know why this Prefix Label isn't aligned?

waxen sandal
#

Because the position you pass is not indented

dusky plover
#

Anyone knows of any tricks to make editor fields invisible but still clickable?
I want to use a EditorGUILayout.ColorField() that will open the color picker when I press a certain location on the editor window, but I don't want the field to be shown.

waxen sandal
#

Look at the source on how it opens and then just invoke that instead

dusky plover
#

Well, yes, but that's the nuclear option 😅

#

If there's a way to just set the opacity of all controls in a scope, like a EditorGUILayout.BeginHorizontal() that would be much preferable.

waxen sandal
#

I'd argue that's the better option but you can use GUI.Color to change the opacity

#

And then change it back later

dusky plover
#

That one doesn't seem to affect the color part of the control.

waxen sandal
#

Shame, you probably can't then

dusky plover
#

Guess not.

#

Oh well. Thanks anyway.

solid thicket
#

It turns out when you use Event.mousePosition with GUI.BeginGroup, the mousePosition will have a new coordinate for the group (meaning, the mousePosition will show (0,0) if you click on the top left of the group rect, not the window rect)

fickle copper
#

Coming back with more spaghetti, i have a problem where the nested Editor's dont allow me to change ints or bools. Enums can be changed but further testing is required. I have no clue as to where to start in relation of finding a way to fix this.

onyx harness
hollow yacht
#

How do I make this code accept input from an array? (so I can add multiple audio clips)

creep.soundDestroyed= (AudioClip)EditorGUI.ObjectField(new Rect(startX+spaceX, startY, width, height), creep.soundDestroyed, typeof(AudioClip), true);```
dusky plover
# onyx harness Nope, that's the smart way.

The source code for the ColorField is a 200 line long uncommented method that uses a bunch of Unity's internal methods and is tightly integrated with the IMGUI system.
https://github.com/Unity-Technologies/UnityCsReference/blob/61f92bd79ae862c4465d35270f9d1d57befd1761/Editor/Mono/EditorGUI.cs#L4549
Yes, reverse engineering it and tweaking it to support your requirements is technically a smart thing to be able to do, so is designing a ballpoint pen that can work in space. The wise thing to do is to use a pencil, as the saying goes.

dusky plover
waxen sandal
#

ColorPicker.Show(GUIView.current, value, showAlpha, hdr); is probably waht you need

onyx harness
dusky plover
#

@waxen sandal It is (Though it's an internal class so it needs to be used with reflection). The problem is that this is just what opens the color picker dialog, the field goes beyond that in also returning a value. It's a piece of the puzzle for recreating the functionality, yes, but I just first wanted to check if there was a solution I was unaware of for just setting the opacity of controls which would solve the issue without much development time.

waxen sandal
#

It raises an event on the GUIView you give it with the color

#
                            case EventCommandNames.ColorPickerChanged:
                                GUI.changed = true;
                                HandleUtility.Repaint();
                                return ColorPicker.color;```
dusky plover
#

@onyx harness That wasn't my point. I can do it, it just doesn't necessarily mean that I should be doing it if there's already a simpler solution that is meant to solve this issue without rewriting source code.
Doesn't mean your method is wrong though 🤷🏼‍♂️

onyx harness
dusky plover
#

@waxen sandal True, thanks.

solid thicket
#

Does anyone know how to access this function?:

// UnityEngine.GUIClip
public static Vector2 Unclip(Vector2 pos)
#

Unity use it when there is BeginGroup or BeginArea, and the mouse is relative to it, it becomes relative to the main window

#

I can create one myself, but in the current state of the code I will have to pass rects all over the place, and Unity just didn't make this public

waxen sandal
#

If it's public then just access it? or is GUIClip not public

solid thicket
#

Its inside an internal class

#

GUIClip

dusky plover
#

Ah.

waxen sandal
#

Then use reflection to resolve the type and then resolve the method from that

solid thicket
#

internal sealed class GUIClip

dusky plover
#

Same thing as we mentioned above haha
You can use reflection to access it.

solid thicket
#

Oh, never actually tried it with C#

#

Thanks I'll try it!

solid thicket
waxen sandal
#

Type.GetType

solid thicket
#

But I don't have access to GUIClip is it still possible?

dusky plover
#

You can search for it by its name as a string.

waxen sandal
#

It's probably UnityEditor.GUIClip that you have to pass

#

If that doesn't work then there's some weird format you can use to specify the assembly and stuff

#

Check the docs for it

solid thicket
#

Theres nothing on the docs about GUIClip, but I saw on ILSpy this:

    public static Vector2 Unclip(Vector2 pos)
    {
        return Unclip_Vector2(pos);
    }

And:

    [FreeFunction("GetGUIState().m_CanvasGUIState.m_GUIClipState.Unclip")]
    private static Vector2 Unclip_Vector2(Vector2 pos)
    {
        Unclip_Vector2_Injected(ref pos, out var ret);
        return ret;
    }

And finally..:


[MethodImpl(MethodImplOptions.InternalCall)]
private static extern void Unclip_Vector2_Injected(ref Vector2 pos, out Vector2 ret);

#

Does this help somehow

#

?

#

Sorry im pretty new to reflections, never used them

waxen sandal
#

I mean check the docs for Type.GetType

solid thicket
#

Oh

#

Okay got you!

dusky plover
solid thicket
#
object[] param = {Event.current.mousePosition};
            Vector2 test = (Vector2)Type.GetType("UnityEngine.GUIClip").GetMethod("Unclip").Invoke(null, param);

Shouldn't this work?

#

I get null reference from Invoke

#

I mean, from GetMethod

onyx harness
#

GetMethod("Unclip", BindingFlags.Static | BindingFlags.Public)

#

The default will fetch "Instance | Public", but you want the Static one

solid thicket
#

Same result

#

I think it has multiple unclip methods with different arguments

#

I'll check msdn if you can specify that

onyx harness
#

If you have an ambiguity exception just add the parameters in the argument

dusky plover
#

I don't remember if there's a way to request a method based on a certain signature, but you can also use GetMethods() instead of GetMethod() and then find the right signature from the list of MethodInfos

solid thicket
#
            object[] param = {Event.current.mousePosition};
            Vector2 test = (Vector2)Type.GetType("UnityEngine.GUIClip").
                GetMethod("Unclip",
                BindingFlags.Static | BindingFlags.Public,
                null,
                CallingConventions.Any,
                new Type[] { typeof(Vector2) },
                null
                ).Invoke(null, param);
#

still no luck

#

This one should've got the right function, I think, I'll recheck the params

#

But GetMethods sounds like a good start

dusky plover
#

Are you sure that the null reference is from the GetMethod() and not from the GetType() then?
Since the MSDN for GetType does mention that you need a fully qualified name to find a type, and if my memory serves, that should include the assembly information.

solid thicket
#

You are right

#

its from Type.GetType("UnityEngine.GUIClip")

#

Isn't UnityEngine the assembly?

dusky plover
#

I don't remember off the top of my head, but it formatted something like "UnityEngine.GUIClip,UnityEngine.dll" or something similar, note the ,
You can find the full string by doing something like typeof(GameObject).AssemblyQualifiedName and printing it to console to check, should work on any Unity built-in type.

dusky plover
#

The UnityEngine part in UnityEngine.GUIClip refers to the namespace. But an assembly can contain multiple namespaces.

solid thicket
#

var GUIClip = Type.GetType("UnityEngine.GUIClip, UnityEngine"); Okay this one worked!

dusky plover
#

@onyx harness Yea, he just sent a code example of it straight after I sent that haha

solid thicket
#

lol yeah thanks!

#

Now the unclip again is the problem

#

the GetMethod

#

Nevermind!

#

Working now!

#
var GUIClip = Type.GetType("UnityEngine.GUIClip, UnityEngine");
            var Unclip = GUIClip.GetMethod("Unclip",
                BindingFlags.Static | BindingFlags.Public,
                null,
                CallingConventions.Any,
                new Type[] { typeof(Vector2) },
                null
                );
            object[] param = {Event.current.mousePosition};
            Vector2 test = (Vector2)Unclip.Invoke(null, param);
dusky plover
#

👍🏼

solid thicket
#

Full snippet if anyone intersted

#

Thanks everyone!

#

Well, unfortunately I was wrong and the function probably does nothing without using GUIClip fully, so the function just returns the same coordinates given.. I'll probably need to do the fix on my own then

patent pebble
#

Is there a way to repaint the entire Unity editor?

#

I want to force everything to repaint, including the top bars with the "File, Edit, Assets, etc" buttons and the one with the Play and Pause buttons

onyx harness
patent pebble
#

@onyx harness aaaah right! I had some website with the documentation for that API somewhere in my bookmarks but didn't think of looking in there

#

Thanks a lot! 😊

severe python
#

Okay, I don't understand, can someone sanity check me on this.
If I render a field using EditorGUI.PropertyField(property, true), that should allow a CustomPropertyDrawer to execute shouldn't it?

onyx harness
#

Yes & no. 🙂

severe python
#

oh thats the worst

severe python
#

To be more specific, I'm making a CustomPropertyDrawer for an Attribute

onyx harness
#

Yes, it will draw a CPD.
But what happens if your CPD draws using a PropertyField again on a similar or same Object ?

#

If I'm not mistaken, PropertyField has mechanisms to prevent cycling

severe python
#

So it should only not work if it encounters a cycle condition?

onyx harness
#

Do you fall on the 2nd case?

#

This is the only one I know where it fallbacks on default GUI

severe python
#

its definitely not a cycle, the attribute is on a List<string>

#

Does it matter if I'm calling EditorGUI.PropertyField in a different assembly than where the PropertyDrawer and PropertyAttribute are defined?

onyx harness
#

Should not

#

These kind of things are suppose to be common since AsmDef

severe python
#

so this is basically what I have

#

These are all in the same assembly, via an AsmDef, but the Editor which renders them isn't depicted here, which just calls EditorGUI.PropertyField

#

it all seems right to me

#

I'd show the editor aqs well, but its pretty big

wispy delta
#

Is it possible to access the class a property drawer is currently drawing? (not the SerializedProperty representation of the class, but the class itself)

for context, the property drawer I'm making is for a class that references a scriptable object. whenever that reference changes, I want the class to register itself with the newly assigned SO. However I'm struggling to do this in the property drawer because I don't see a way to access the current property that is being drawn.

// abbreviated pseudo-code

class Palette : ScriptableObject
{
  void Register(PaletteRef r);
  void Unregister(PaletteRef r);
}

class PaletteRef // can be encapsulated on any monobehaviour
{
  Palette palette;
}

[CustomPropertyDrawer(PaletteRef)]
class PaletteRefDrawer : PropertyDrawer
{
  void OnGUI(SerializedProperty sp)
  {
    SerializedProperty paletteProperty = sp.Find("palette");
    Palette previousPalette = paletteProperty.objRef as Palette;
    DrawProperty(paletteProperty)
    if (changed)
    {
      Palette newPalette = paletteProperty.objRef as Palette;
      previousPalette.Unregister(currentObject);
      newPalette.Register(currentObject);
      // ^^ currentObject is the PaletteRef being drawn. does this reference exist anywhere in the API?
    }
  }
}
severe python
#

Okay, so the problem was I was trying to use a propertyDrawer for a List<String> or string[] which is nonsense

#

However, if I subclass List<string> I can do it

#

or atleast, I think that is the case definitely the case

patent pebble
#

@wispy delta can't you get the class from the SerializedObject of the SerializedProperty?

#

or maybe something with SerializedProperty.propertyPath ?

#

it's been a while since I delved into this topic, I don't fully understand what you are trying to do

visual stag
#

I have a bullshit helper method I need to rewrite that does it

#

But, unless I'm misunderstanding what you're talking about, seeing as you're using a ScriptableObject that's just property.objectReferenceValue?

hardy apex
#

What is the best way to align the rect component of a togglebox when making a custom inspector?

#

I feel like it's a very simple problem but I can't figure a solution out.
EDIT: Figured it out, was accidentally using GUILayout instead of EditorGUILayout.

rough raven
#

hello, I'm having some issues with a ScriptedImporter

#

my importer basically works like the texture importer of Unity, it generates a lot of assets from a single file and appends it to the imported file using AddObjectToAsset

#

I see all the imported objects in Unity without a problem, but I've noticed they are not being added to the .meta file at all, so on every reimport (or when a colleague imports the project the first time) all links to those generated assets are broken, because they get new ids as they don't really "exist" anywhere

#

I've investigated textures and the TextureImporter seems to use a mixture of a field called internalIDToNameTable and a list of the generated sprites as part of its meta

#

however, I can't find any way of doing this myself and I was actually hoping the ScriptedImporter context would do that for me, otherwise I don't see the point of using the AddObjectToAsset if it just disappears after a reimport (unless I'm doing something wrong, of course)

grim vine
#

@rough raven can you modify the .meta files yourself?

rough raven
#

hmm, not sure how?

ebon helm
#

can someone please explain to me how to use MultiColumnHeader and add rows to a columns

solid thicket
patent pebble
#

the examples they give in that manual page are very vague, you are gonna need to dig through the example project they give

#

and even then, I think all the multi column examples on their example project are also using a custom tree data model, which can make things confusing if all you want to know is how to make a simple multi column tree

fickle copper
#

Ok, good news! I fixed the problem where i couldnt edit the inner-editors that i made previously. Now i am coming to a problem where i cant add objects from the scene to the list inside the scriptable object (for obvious reasons). Is there a way to "cheat" around this limitation?

fickle copper
#

Can someone explain to me why the first element in a reorderable list is 20 units longer in height than the other elements?

#

Here is the code for that specific element:

 private void DrawReorderableList(ref Rect rect, SerializedProperty property)
        {
            if (!_reorderableLists.ContainsKey(property.propertyPath))
            {
                ReorderableList list = new ReorderableList(property.serializedObject, property, true, true, true, true);
                list.drawElementCallback = (rect1, index, active, focused) =>
                    DrawElementCallback(rect1, property, index, active, focused);
                list.drawHeaderCallback = DrawHeaderCallback;
                list.elementHeightCallback = (index) => ElementHeightCallback(index, property);
                _reorderableLists.Add(property.propertyPath, list);
            }

            SerializedProperty it = GetFirstSerializedProperty(property);
            it.Next(true);
            rect.height = EditorGUI.GetPropertyHeight(property, property.isExpanded) +
                          EditorGUIUtility.singleLineHeight * Mathf.Min(3,
                              property.Copy().CountRemaining() + 1f);
            //_reorderableLists[property.propertyPath].DoList(rect);
            GUI.Box(rect, "");
            rect.y += rect.height + _spacing;
        }
#

I have experienced this sort of behavior before and i usually do some very wonky workarounds to this. Id like to figure out the bottom of this inconsistency so i know what to do in future scenarios when this problem occurs.

waxen sandal
#

Because your height calculation is probably messed up

fickle copper
#

Im literally using a EditorGUI.GetPropertyHeight() method

waxen sandal
#

There's a callback on reorderablelist to determine an elements height

#

You need to register on that and return the correct height

fickle copper
#

you mean this one?

private float ElementHeightCallback(int index, SerializedProperty property)
        {
            SerializedProperty element = _reorderableLists[property.propertyPath].serializedProperty
                .GetArrayElementAtIndex(index);
            return EditorGUI.GetPropertyHeight(element, element.isExpanded);
        }
#

which is, yet again, using EditorGUI.GetPropertyHeight.

#

No matter what height i input into this callback and/or method that i posted previously, there is always a 20 unit height difference.

waxen sandal
#

rect.y += rect.height + _spacing; I also doubt this is what you're supposed to do

fickle copper
#

You can clearly see it in the 2 pictures i sent above

#

The rectangles are spaced correctly

#

its just the middle square's height is fucked

#

here is the whole GUI method:

 public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
        {
            SerializedProperty eventToListenTo, conditions, responseToEvent;
            Rect r = position;

            eventToListenTo = property.FindPropertyRelative("eventToListenTo");
            conditions = property.FindPropertyRelative("conditions");
            responseToEvent = property.FindPropertyRelative("responseToEvent");

            EditorGUI.BeginChangeCheck();

            GUI.Box(new Rect(position.x, position.y, position.width, totalHeight), GUIContent.none);
            EditorGUI.indentLevel++;
            DrawPropertyField(ref r, eventToListenTo);
            if (eventToListenTo.objectReferenceValue != null &&
                eventToListenTo.objectReferenceValue is CustomEvent customEvent && !customEvent.isEventGlobal)
            {
                DrawReorderableList(ref r, conditions);
            }

            DrawPropertyField(ref r, responseToEvent);

            if (EditorGUI.EndChangeCheck())
            {
                property.serializedObject.ApplyModifiedProperties();
            }

            EditorGUI.indentLevel--;
        }`
#

Each DrawPropertyField and DrawReorderableList methods edit the rect for the next element.

waxen sandal
#

So you're saying that if you return a constant value in ElementHeightCallback it breaks?

fickle copper
#

No, im saying that the value inside the ElementHeightCallback is different on the first element of the ReorderableList vs the other elements.

fickle copper
#

I have explored every option i know thus far and so far, this only seems to be a bug on Unity's side of things

#

I guess ill go back to my wonky solution

gloomy chasm
#

@visual stag So uh, you know how we were talking about SerializeReference, well fun fact, it doesn't support more than a 2 deep tree on prefab variants. I think am going to have to rewrite my system to just not use it... It is still too unstable...

severe python
#

That is unfortunate, depth issues could make it useless for me :/

chilly bough
#

i wrote an extension that opens and displays the inspector in a new window, but the data is not saving after closing the window. The template for the code is from here. on youtube : "Easy Editor Windows in Unity with Serialized Properties"

severe python
gloomy chasm
severe python
#

Don't assets also have depth limits?

gloomy chasm
severe python
#

I want to add a different set of objects, using that whole menu system they have there, with the folders and the scrolling and what not

gloomy chasm
severe python
#

superbbbb

#

that should make this feel much nicer

gloomy chasm
#

I made a UIToolkit version of it that you can use if you want to. It has more customization options and works almost identically (Though has not been put through that many tests yet). 🙂

severe python
#

unfortunately I'm trying to support a wide range of versions, and in an inspector, so I'm limited to imgui

gloomy chasm
severe python
#

oh no, its not in my version!

gloomy chasm
severe python
#

2018.4

gloomy chasm
#

Yes it is...

#

I think...

severe python
#

well the documentation says that there is no page for it in 2018.4 and older

#

maybe its internal, and I can reflect it, and i'm totally not above that

gloomy chasm
#

I could have sworn that it was there... My bad. Did you try it in code just to be sure it is not there and just not documented?

severe python
#

yeah, thats what caused me to check

#

but maybe I can just "polyfil" it

#

I suppose I can't really do that and redistrubute eh

gloomy chasm
#

If you can't get it with reflection, I suppose you could just roll a custom solution. It shouldn't take that long too make tbh.

severe python
#

Yeah, doesn't look like thats legit

#

I have a custom solution right now, I have a search-suggest control I built, which works well enough but has limits on discoverability

#

but I think the answer is really that I need to keep expanding on that control to fill in that gap

royal scroll
#

So, I know zero about editor extensions, so I was wondering if someone could point me in the right direction either to a resource or where to get started on a better way to access animations from the Animation tab.
I'm nearing 100 animations per character, and having to scroll down the dropdown list is getting silly. I'm not picky on the solution, either opening a file explorer prompt or just adding some kind of search bar I could use to type the name of the animation I'm trying to get to.

livid beacon
#

I've heard some tutorials claim editor scripts must be in a folder called "Editor".
However, I seem to be able to get away with making them outside of that folder.

Are they giving me outdated information or something? Or is there some edge-case that what I'm doing could result in?

#

Oh. . .
Brackeys said "That's because any script put inside the Editor folder won't be included in builds"

#

I suppose that's the only reason

waxen sandal
#

Also editor code will break your build if you don't have it in either a editor only asmdef or a editor folder

waxen sandal
#

What were the rules for having a custom string show up as the array element header? Was it the first string or the name of a SO?

civic river
#

@livid beacon Assembly definitions are the more "modern" approach for this now

#

For the UITK crowd, is anyone aware of a way to do layers like in photoshop? Where you can disable the top layer raycast and let it trickle down to lower elements?

#

I can't seem to find any possible way to do this

grim vine
#

@livid beacon
in build the namespace UnityEditor is unavailable.
In Editor it'll run fine, but in build you'll get an error like namespace not found.

You can certainly mix editor and build code together, you merely have to put your editor specific code in a block like this

#if UNITY_EDITOR
all your editor stuff
#endif

you can wrap your entire script into a block like that.

livid beacon
#

oh i see
nice

ty

grim vine
#

here's a trick i use a lot. When you need just a little bit extra but don't want an entire script for it.

public class Magic : MonoBehavior {
  public bool Vector3 Size;
#if UNITY_EDITOR
  [CustomInspector(typeof(Magic))]
  private class MyEditor : UnityEditor.Editor {
    private override void OnInspectorGui(){
      base.OnInspectorGui();
      if(GUILayout.Button("Reset size"))
        ((Magic)target).Size = Vector3.one;
    }
  }
#endif
}

It'll show the Vector3 field like normal, with a button under it.

real meadow
#

So I'm trying to make an editor tool which attaches itself to any GameObject with a MeshRenderer component attached. Then I want the button to trigger Unity making a thumbnail in a folder from that model.

Problem is, while the code does find the correct model in the correct folder, it seems that no matter what I feed GetCachedIcon() it keeps saying that the path is invalid. The error is:

Use path relative to the project folder.
Below is my code. I just want to actually make the first part work before I get the code to write a file to disk.

[CustomEditor(typeof(MeshRenderer))]
public class ThumbnailGenerator : Editor
{
    public override void OnInspectorGUI()
    {
        DrawDefaultInspector();
        if (GUILayout.Button("Generate Thumbnail"))
        {
            MeshRenderer render = serializedObject.targetObject as MeshRenderer;
            Texture thumbnail = AssetDatabase.GetCachedIcon($"{Application.dataPath}/Meshes/{target.name}.fbx");
            //byte[] _bytes = thumbnail
            //string _fullPath = $"{Application.dataPath}/Textures/Icons/{target.name}.png";
            //File.WriteAllBytes(_fullPath, _bytes);
            //Debug.Log(_bytes.Length / 1024 + "Kb was saved as: " + _fullPath);
        }
    }
}
#

I tried with GetMiniThumbnail() and GetAssetPreview() too. I can't any of them to work. They always return a null Texture2D

#

It's supposedly because they are called asynchronously but I am not sure what to do to deal

waxen sandal
#

Should probably be relative to Assets

#

E.g. Assets/Meshes/target.fbx

real meadow
#

Huh. I could have sworn I already tried that. That at least gives me a Texture. Thanks @waxen sandal

waxen sandal
#

👍

real meadow
#

New problem tho

#
public override void OnInspectorGUI()
{
    DrawDefaultInspector();
    if (GUILayout.Button("Generate Thumbnail"))
    {
        MeshRenderer render = serializedObject.targetObject as MeshRenderer;
        Texture texture = AssetDatabase.GetCachedIcon($"Assets/Meshes/{target.name}.fbx");
        Texture2D thumbnail = (Texture2D)texture;
        byte[] _bytes = thumbnail.EncodeToPNG(); // <-- Stops here
        string _fullPath = $"{Application.dataPath}/Textures/Icons/{target.name}.png";
        File.WriteAllBytes(_fullPath, _bytes);
        Debug.Log(_bytes.Length / 1024 + "Kb was saved as: " + _fullPath);
    }
}

On the line byte[] _bytes = thumbnail.EncodeToPNG(); it stops saying the following:

ArgumentException: Texture 'd_PrefabModel Icon' is not readable, the texture memory can not be accessed from scripts. You can make the texture readable in the Texture Import Settings.

#

But the Read/Write flag is set to true in the mesh settings

cerulean maple
waxen sandal
#

@real meadow mesh settings?

#

Should be on the texture importer

real meadow
#

Well

#

I gave up on my solution and instead found an external solution

#

It's fine though seeing as it doesn't have to be during runtime

#

It's an old python script that uses Blender 2.7x to prop up an OBJ file in a blender scene then generate a picture and save it

#

It's pretty neat

obsidian quest
#

Morning Guys, I lack some knowledge so i thought i directly ask here instead of google since i have no idea what to ask google.

Situation: i have a Class with 3 variables: 1x Enum, 1x SkinnedMeshRenderer (SMR) and 1x GameObject.

Question: Is it possible to hide the SMR or the GameObject Variable in the Inspector depending on what i choosed in the Enum?

Reason: the Enum contains the Itemslot (head Chest, Mainhand etc) and the weapons simply don't use a SMR while the Armor doesn't need a GameObject reference since it is already part of the SMR

spark lotus
#

It's not as active here but pretty much override OnGui and modify the contents of the inspector relative to that enum value.

obsidian quest
#

uuuuhm.

spark lotus
spark lotus
obsidian quest
#

ah i was already wondering why override and ongui don't wanted to work ^^

#

@spark lotus do you know if such editor changes the performance / size of the built game in any way?

#

performance probably not but isn't it still code and "unnecessary" functions i implement into the code?

#

or are we only talking about a few bytes that nobody cares about it

#

always wondered

spark lotus
spark lotus
#

Inappropriate handling will cause your Unity to crash though.. 😛

obsidian quest
#

Inappropriate handling will cause your Unity to crash
thats often the case but thanks for the reminder ^^

obsidian quest
#

Whelp. it took not even 30 minutes and i have headaches and still no idea what to do >.<

#

i can't even figure out how to check what enum is currently selected in the editor figured out how to check what enum is active

grim vine
#

may i ask what excactly you're building?

#

i have about 30 minutes and is bored

#

if you are going to have many kinds of slots you might roll outwith a different design, but i can't really tell

obsidian quest
#

give me a sec ^^

grim vine
#

i saw a video about the "Tyranny of MonoBehavior" that showed how you could use ScriptableObjects as enums

obsidian quest
#

i haven't seen the vid yet but what i do is that i use scriptable objects to define the properties of items. my default inspector looks like this:

#

the "problem" that i have right now is, that Equip Slot has values for head, body, legs, main hand, off hand etc.
to instantiate the armor parts i need a skinned mesh render, but for the weapons i need a gameobject instead

#

so i have "Game Object" and "Mesh" both showing up in the inspector. while only one is needed

#

i wanna get rid depending on what value i select in the enum

grim vine
#

ok, well first of all, there is no way to selectively hide properties, you have to roll out a new editor

#

tho there is a hybrid solution that may save your day

obsidian quest
#

mom^^

grim vine
#

hide the properties you want to switcharoo, and make a new inspector for those

#

inheritance might be your answer actually

obsidian quest
#

i already managed to show the Gameobject field by figuring out this code, but i am not sure if it is possible to override the original inspector or if i have to write it completely from scratch and get rid of DrawDefaultInspector... also dunno why it is grayed out

grim vine
#

you can mix them

#

just call base.OnInspectorGUI(); and it'll paint the default inspector

obsidian quest
#

instead of drawdefaultinspector?

grim vine
#

never heard of that function

#

oh

#

same thing

#

the properties you want to selectively hide, put the attributes

// private fields are not serialized by default
[SerializeField] // private fields can be serialized but this attrib also makes them show
[HideInInspector] // so force hide it
private GameObject _gameObject;
#

it will hide them from the default inspector

#

then just write the ui code to add them back

obsidian quest
#

oh gosh

#

i am such a dumdum

#

of course >.<'

#

if i hide them in the original class via hideininspector they are also hidden in my editor version... wow i feel so dumb now xD

grim vine
#

right you don't actually need SerializeField if you make the prop public

obsidian quest
#

only thing i still don't know. is how i get a "usable" gameobject field

grim vine
#

right

#
_gameObject = (GameObject)EditorGUILayout.ObjectField("Prefab", _gameObject, typeof(GameObject));
#

btw i presume the process to apply skin and weapons are very different

#

so i raise you: Polymørphism

public abstract class Equipment : ScriptableObject {
    public string Name;
    public abstract Apply(CharacterController whatever);
}

public class Armor : Equipment {
    public SkinnecMeshRenderer _skinnecMeshRenderer;
    
    public override Apply(CharacterController whatever){
        // apply skin
    }
}

public class Weapon : Equipment {
    public GameObject _gameObject;
    
    public override Apply(CharacterController whatever){
        // apply GO
    }
}
obsidian quest
#

yeah i already use that (not for weapon/armor) but Equipment is already deriving as Equipment : Item and Item : ScriptableObject

grim vine
#

also another editor

public class Equipment : ScriptableObject {
    
    private enum ItemSlot
        Head,
        Chest,
        Weapon
    }
    
    private Enum _slotType;
    private SkinnecMeshRenderer _skinnecMeshRenderer;
    private GameObject _gameObject;
  
    #if UNITY_EDITOR
    private void OnInspectorGUI(UnityEditor.Editor editor){        
        editor.OnInspectorGUI();
        _slotType = EditorGUILayout.EnumPopup("Slot Type", _slotType);
        
        switch(_slotType){
            case Slot.Head:
                _skinnecMeshRenderer = (SkinnecMeshRenderer)EditorGUILayout.ObjectField("Skin", _skinnecMeshRenderer, typeof(SkinnecMeshRenderer));
                break;
            case Slot.Chest:
                _skinnecMeshRenderer = (SkinnecMeshRenderer)EditorGUILayout.ObjectField("Skin", _skinnecMeshRenderer, typeof(SkinnecMeshRenderer));
                break;
            case Slot.Weapon;
                _gameObject = (GameObject)EditorGUILayout.ObjectField("Prefab", _gameObject, typeof(GameObject));
                break;
            default: throw new Exception();
        }
    }
    [CustomInspector(typeof(Equiptment))]
    private class MyEditor : UnityEditor.Editor {
        public override void OnInspectorGui(){
            ((Equipment)target).OnInspectorGUI(this);
        }
    }
    #endif
}
#

also pay attention to the fact that even if the property is not drawn, it may still hold data if you had it used it a different type previously, so be sure to null unused fields as they still consume space

#

i'll be off

obsidian quest
#

ok thank you 🙂

#

will try to understand your last one ^^'

ebon helm
#

Im still confused about multi column headers. Do I need to use a treeview with them or can someone point me to a example on how to use them on their own.

patent pebble
#

@ebon helm iirc Multi Column Headers can be used for other things, but I think the only API from Unity that uses it is the TreeView API

#

so it should be possible to use with your own implementations

ebon helm
#

yeah I found that too. But I was hoping I would not have to calc my own content. The tree view example has a searchbar that I need too so I will just go with the tree. Even tough my data is not a tree at all haha

#

seemed like overkill but..

patent pebble
#

the Searchbar they do in the TreeView examples is not exclusive to that API

#

you can use this and do your own searching logic

#

there's also the AdvancedDropdown class, has similar functionality to a treeview, and has searching by default

ebon helm
#

I know about that too. I was hoping to get this done in a "quick and easy" way. A man can only dream.

patent pebble
#

"quick and easy" that doesn't exist when doing Unity Editor extensions 🙃

ebon helm
#

hah yep. Life is pain and doing editor extensions is a punishment for my past sins

patent pebble
#

the more stuff you do yourself the more you learn about extending Unity's default functionality

#

and that's great

severe python
#

Can I specifically order SubAssets?
I have 2 classes, ComposableObject : ScriptableObject, and ComposableElement : ScriptableObject
I am adding ComposableElements to ComposableObjects as SubAssets, and then also populating a ComposableElement[] in the ComposableObject
This leads to some problems, and I'm wondering if I can omit the ComposableElement[]
In order to eliminate it I would need to be able to do 2 things.

  1. specifically order the SubAssest
  2. iterate over the SubAssets
#

I can work around the ordering by adding an Index value to the ComposableElement, though I don't feel that is ideal since it would require that I order them every time I iterate

#

I also don't know if its possible to iterate over sub-assets, I've looked but I haven't found anything

waxen sandal
#

I doubt it

#

They might be sorted by name?

severe python
#

well, that'd be unfortunate but I can work around it I suppose, now I just need to figure out how or if I can iterate over sub-assets

split bridge
#

if you mean using AssetDatabase you can use LoadAllAssetRepresentations? (roughly that name)

tulip plank
#

I see references to UXML elements named "Template" and "TemplateContainer". I only seem to be able to successfully reference "TemplateContainer". Is one of these an older version of the other? (This is for the purpose of reusing controls in UXML).

patent pebble
#

I don't understand why screenPoint is returning the same value as guiPoint

patent pebble
#

Oh nevermind, this just flips the Y value of the point in the current camera. In my case the SceneView camera

#

the method is just incredibly poorly named/documented

#

this one gives the actual global screen position GUIUtility.GUIToScreenPoint()

real ivy
#

How do i make conditional displaying in uxml?
Or i have to do this in cs ?

stuck olive
#

That is something OnGUI is quite good at

split bridge
stuck olive
#

Nice

real ivy
#

Yep, just did that. Had to name everything uniquely
But looking back (just 10 minutes ago), i could just use a class to tag them all for something similar, and query them all in 1 go
It's for hiding a bunch of properties when the "isPassive" toggle is checked

#

In fact im gonna do that now. The sudden wall of text in the code just for hiding is kinda unsightly..

split bridge
#

I usually create some helper methods too in case it helps. E.g. in a static utils class:

        static StyleEnum<DisplayStyle> DisplayStyleFlex = new StyleEnum<DisplayStyle>(DisplayStyle.Flex);
        static StyleEnum<DisplayStyle> DisplayStyleNone = new StyleEnum<DisplayStyle>(DisplayStyle.None);
        static public bool IsVisible(VisualElement el)
        {
            return el.style.display.value == DisplayStyle.Flex;
        }
        static public void SetVisible(VisualElement el, bool show = true)
        {
            el.style.display = show ? DisplayStyleFlex : DisplayStyleNone;
        }
        static public void Show(VisualElement el)
        {
            el.style.display = DisplayStyleFlex;
        }
        static public void Hide(VisualElement el)
        {
            el.style.display = DisplayStyleNone;
        }
        static public void SetHasClass(VisualElement el, string className, bool shouldHave = true)
        {
            if (!shouldHave) el.RemoveFromClassList(className);
            else el.AddToClassList(className);
        }
real ivy
#

Do u guys use .visible or display.value = DisplayStyle.Flex?

split bridge
#

usually display as I almost always want the layout to change - visible is opacity and the layout is maintained

zinc schooner
#

Hi all, I am looking for an example for adding a repeater style field into my editor inspector. I need to be able to add many items into a list, each item having an if/ifnot drop down, field for a value and then just another field for a string. I can do that bit but not the add / remove from the list part

#

If anyone may know it would be a great help thanks

#

Basically a list that contains those fields on an item I can add/remove from

whole steppe
#
t.go = (GameObject)EditorGUILayout.ObjectField(new GUIContent("Go", "Event GameObject"), t.go, typeof(GameObject), true);

when i restart Unity the field is empty and i have to assign it again, is there a way to save the gameobject? I am allowing sceneobjects as you can see and assigning a gameobject form the scene into this field

#

my target "t" is a Scriptable object i made this custom editor for.

#

would appreciate it alot if somenoe has a soloution to this problem.

waxen sandal
#

Undo.RecordObjet

whole steppe
#

i think i even tried that. Let me try it again. so into my custom editor script in the OnInspectorGui method right

whole steppe
#

unfortunately not working. field is null after unity restart

waxen sandal
#

Then you're doing something wrong

#

Need more context

#

You coudl also just use serializedobjects instead

whole steppe
#

instead of t ?

waxen sandal
#

Yeah

whole steppe
#

i don´t exactly understand where to use serializedObject.

patent pebble
#

@whole steppe well your field is not serializable

whole steppe
#

shall i use SerializeField on it?

#

oh i already do it.

#

i think it is simply not possible to have Scene GameObject on the assets 😦

#

whatever i try the field is empty after unity restart

zinc schooner
#

Hi im trying to use a ReorderableList and it works and shows up for my custom inspector however how can I access the 'list' of this in code? thanks basically want to iterate that list now

whole steppe
#

new Unity verions have reorderable list by default.

zinc schooner
#

oh do they now, interesting thanks I will check

#

I did look but I could only find a link to a tutorial where someone made it themselves

#

is it in the docs?

whole steppe
#

just install the recent 2020.2 version and use it.

zinc schooner
#

unless I include UnityEditorInternal it wont be recognised, can i just check where it should be

whole steppe
#

the default Unity lists are reorderable lists now

zinc schooner
#

ah right that explains it

#

spot on that thanks

patent pebble
whole steppe
#

tried so much tho, no clue what to do now. i mean i have a soloution but it is not so user friendly (pusblishing an asset)

patent pebble
#

a quick search gave me this

#

looks interesting, I've never used it or heard about it

whole steppe
#

looks like something really promissing. I will look into that .Thank you very much.

patent pebble
#

maybe someone with more knowledge of keeping references to scene objects can chime in, I'm not very experienced in this topic 😅

waxen sandal
#

That's the only way unlses you make your own system of course

patent pebble
#

@waxen sandal what would be a "good" way to implement your own system, just have some rudimentary id value added to each of the GameObjects in a script or something like that?

waxen sandal
#

I'd probably make a component with a GUID that register itself to a database

#

Then record that GUID in your SO

#

Probably with some extra data like scene name and go name for debugging

patent pebble
#

hmmm, seems simple enough

waxen sandal
#

Whether it's a good idea is something else

#

Since you'd have to validate that your SO actually works in that scene somehow

patent pebble
#

yeah the concept of storing scene references in a ScriptableObject seems counterproductive

#

i haven't had that need ever

waxen sandal
#

It has some uses but most of the time you can solve them in differnet better ways

west fog
patent pebble
onyx harness
zinc schooner
#

hello all, so I have a custom editor script and I would to hide certain fields from a list based on whatever values. I tried using DrawPropertiesExcluding and I can hide values outside of a list but how could I target values inside of it please?

patent pebble
#

@onyx harness I wonder if the GuidComponent just uses the default GUIDs or if it creates new ones

#

also, under what conditions does the GUID of an object change? only when you move it across scenes or does it change under other conditions?

#

like modifying the asset, adding new component to the gameObject, etc

bold skiff
#

Hello, I've been at this for a while and I don't know how to do this, hopefully someone here does.

So, I'm working on an animation panel where I want to be able to drag'n'drop animations into the panel and I want it to update the states in the controller.

I'm running into the issue where I don't know how to access the animations. I'm capable of pulling the animclips by their position in an array, however I can't feed back and change them.

Code: https://gist.github.com/YelbyNoshn/3834ca9051beb0d04e9e438d92db2176

Gist

GitHub Gist: instantly share code, notes, and snippets.

waxen sandal
#

(I also checked the source before)

inner folio
#

I want to draw properties attributed with [Auto] in a special, simple way.
With OnGUI it's easy, but with VisualElement, I somehow can't?

    [CustomPropertyDrawer(typeof(Auto))]
    public class AutoDrawer : PropertyDrawer
    { //this works
        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
        {
            var text = "Ⓐ" + label.text;
            GUI.Label(position, text);
        }

        public override VisualElement CreatePropertyGUI(SerializedProperty property)
        { //this doesn't
            var container = new VisualElement();
            var label = new Label("Ⓐ" + property.name);
            container.Add(label);
            return container;
        }
    }    
#

(I would uncomment one of these two, just here next to each other for reference)

#

This is what I want, and I can't get it with UIElements and I don't know why.

split bridge
#

That’s be because the editor isn’t uitk. It’s annoying and not going to be the default for a long while.

#

You can create a custom editor that applies to eg all monobehaviours if you like - there’s one on the forums

split bridge
#

I ended up using imgui for some property drawers instead, given you can sort of use them within uitk stuff still

inner folio
#

Hmm.

#

I'll stick with immediate mode for this one.

#

Thank you for the thread, it will be useful. 🙂

#

You will currently need to also implement a custom editor for WorldStateBehaviourMono as the default editor is still using IMGUI.

minor sun
#

I want to create an editor extension that automatically adds components when placing objects in a scene. Are there any events that are called when an object is created in the scene?

gloomy chasm
minor sun
severe python
#

Can a folder in Assets be marked so that Unity will not load Assemblies in that directory?

onyx harness
severe python
#

Sadly, not AsmDefs

onyx harness
#

Well, you can prefix the folder with a dot

severe python
#

these would be compiled DLLs, I'm trying to setup some stuff to manage staging and packaging of mods, but I'm do

#

hmm

onyx harness
#

You can alter DLL to specify if you want them to load or not

severe python
#

Yeah, that doesn't meet the requirements I didn't state up front, I do want these things to be assets, I just don't want any assemblies loaded

#

Technically, all the assemblies would already be loaded in unity, this is probably just me trying to do something I shouldn't be doing

severe python
#

You mean altering the DLL?

#

Do you mean altering the Meta file?

onyx harness
patent pebble
grave dirge
#

hey all, so I couldn't find a way (because there isn't) to use the cs [RequireComponent()] attribute to require for than one of the same component, so I wrote my own extension method, which is currently being called in Monobehaviour.Reset (called when you first add a component)```cs
private void Reset()
{
gameObject.RequireComponents<ObstacleCheck>(2);
}

This works, but it's not very pretty, and I have 0 experience making custom attributes, and of course, have done some research and not found anything I deem useful to my situation, which is the fact that I want to create an attribute that looks like this ```cs
[RequireComponents(typeof(djklsfajdkals), 3)]
``` thanks in advance, I would love to hear your input, sorry if I have little knowledge on how attributes work 🙃
patent pebble
#

@grave dirge why don't you just use AddComponent in the Reset method?

grave dirge
#

just created a generic method so any gameobject can do it

#

was just curious if there was a way for me to create a custom attribute like that

#
public static void RequireComponents<T>(this GameObject _gameObject, int _components) where T : Component
{
  int _currentComponents = _gameObject.GetComponents<T>().Length;
  for (int i = 0; i < _components - _currentComponents; i++)
    gameObject.AddComponent<T>();
}
patent pebble
#

@grave dirge iirc you can make custom attributes for classes

grave dirge
#

like how would I do that?

#

I can find lots of information on property attributes

#

not much else

patent pebble
#

I've only made Property Attributes so I don't know how to make attributes for classes like the RequireComponent one

#

maybe someone more experienced can point you into the right direction

waxen sandal
#

Afaik, there's no real way to create your own RequireComponent implementation, you can do things like your reset trick but they all are not that great

lethal helm
#

hi everyone

#

i'm trying to write a property drawer for an array-type piece of data

#

it would be fantastic if i could call Add() and Remove() in the instance using a property drawer with a button

#

is this possible

waxen sandal
#

If you have the serializedproeprty of the array then you can increment or decrement the arraySize

#

Or use InsertArrayElementAtIndex

#

There's a similar one for remove iirc

#

IIRC PropertyDrawers are applied to each element and not to the whole array so that'll give you some trouble

lethal helm
#

yeah, i noticed you can change the size but i didnt see functionality to add an object to that index

lethal helm
#

that inserts an empty element

waxen sandal
#

Yeah so?

#

Then just change that element

lethal helm
#

Okay, where do I do that ?

waxen sandal
#

GetArrayElementAtIndex then just set the value

waxen sandal
#

Anyone knows a way to get the information provided by TextureImporter.DoesSourceTextureHaveAlpha through some other api?

#

Apparently TextureImporter.DoesSourceTextureHaveAlpha is not supported outside of assetpostprocessors, while it did work just fine in 2018

gusty topaz
shadow violet
#

What might be a good way to store references in a list of object fields? I have a editor where you can add/remove as many prefabs from a list as youd like, and it would be useful to keep that list when the window is closed/re-opened - my first thought is to store the GUID of all the items in EditorPrefs but I feel thatd be storing too many prefs having SetString/GetString MyEditorItem1, MyEditorItem2, etc - my other thought was to use 1 EditorPref as just MyEditorItems and have GUID1,GUID2,GUID3 etc and split by comma, but then I feel there will be string limitation issues or is there no actual character limit to a string?

shadow violet
# gusty topaz silly question , but what does this icon mean ?

If your referring to the blue/grey box in the left of that pic, it lets you set an icon for an object, so that object in the scene view will always show through all geometry in the shape, color and/or image set for it, so its easier to find in busy scenes - i think Unity explains it (https://docs.unity3d.com/Manual/AssigningIcons.html) - and you CAN also set it by code (https://answers.unity.com/questions/213140/programmatically-assign-an-editor-icon-to-a-game-o.html), the idea is to store a Texture2D, then use EditorGUIUtility to actually get/set the icon of that object, to your Texture2D

gusty topaz
#

Thank you for the answer @shadow violet , but I meant the Box icon , which is similar to Prefab but its not.

shadow violet
gusty topaz
#

that one

shadow violet
#

Oh, yeah thats what those 2 links refer to

gusty topaz
#

Okay , Thanks !

shadow violet
#

Np, gl - if it doesnt work out you can always come back and post your code

grave dirge
#

I was under the impression that they were a unity thing

#

thanks for the help

lime rock
#

Hey, I'm not sure if that belongs here but anyone ever experienced that intellisense and go to definition, basically everything where a language server takes care about stopped working in vscode? I think it stopped after I moved my project to github and switched branches a lot. I'm on Windows and use wsl for git which might also have an impact 🤔 I really have no idea what it is so every idea or experience is very appreciated 😢

gloomy chasm
#

I'm getting an error when trying to set a managedReferenceValue.
Attempting to set the managed reference value on a SerializedProperty that is set to a 'Node' The thing is, that the value is of type Node. It should work...

Node newNode = new Node();

_allNodesProperty.arraySize++;
_allNodesProperty.GetArrayElementAtIndex(_allNodesProperty.arraySize - 1).managedReferenceValue = newNode; // Error here.
[Serializable]
public class NodeTree
{
    [SerializeField] private List<Node> _allNodes = new List<Node>();
}
steady crest
#

How do I change the displayed name of a SO in an objectfield? (I want to remove the type of the SO from the name, and leave only the name, but overriding the ToString doesnt seem to do it, this is without a custom inspector, but I expected overriding the ToString would cover that)

grim vine
#

screenshot

steady crest
waxen sandal
#

I don't think you can

grim vine
#

you can render it as something else

#

like a label

#

or a textfield

steady crest
#

hmm I could, but I need it to be an object selector 🤔

waxen sandal
grim vine
#

i don't think it's a bad thing that the type is visible tho?

steady crest
#

it was more out of curiosity than necessity tbh

grim vine
#

maybe you could use an intermediate type

#

yeah ok

steady crest
#

ah well, it probably uses what @waxen sandal suggests, which is code I probably dont wanna try touching. If I can't I can't, no big deal

grim vine
raw viper
#

hey

#

how i can do it this one thing have a name

#

MissionTask_1

waxen sandal
#

Set the name on the ScriptableObejct

raw viper
#

im not sure

#

there is the title

#

but not showing up

waxen sandal
#

Show code

gloomy chasm
#

Sorry, I'm going to ask my question again because I am at my wits end.
Any ideas why this code:
_property.FindPropertyRelative("_rootNode").managedReferenceValue = new BranchNode();
Would give this error:
InvalidOperationException: Attempting to set the managed reference value on a SerializedProperty that is set to a 'BranchNode'

This is the code for the property.

[Serializable]
public class NodeTree
{
    [SerializeField] private BranchNode _rootNode;
}
sleek berry
#

I'm pretty sure managedReferenceValue is read only

patent pebble
#

i think it's write only

#

i could be wrong

sleek berry
#

Sorry you're right

#

Might it require it to be attributed as a SerializeReference?

patent pebble
#

maybe. I don't think he should be using managed references for that. I myself don't fully understand them, I remember it being a relatively new feature

#

but I don't really know

#

@gloomy chasm any particular reason for you using ManagedReference?

gloomy chasm
patent pebble
#

have you debugged what SerializedPropertyType your SerializedProperty is?

sleek berry
#

Whats the definition of BranchNode ?

gloomy chasm
gloomy chasm
# sleek berry Whats the definition of `BranchNode` ?

Nothing special. (Removed public access properties to make it shorter)

 [Serializable]
    public class BranchNode
    {
        [SerializeField] private string _id;
        [SerializeField] private string _parentId;
        [SerializeField] private List<string> _childrenIds = new List<string>();

        [NonSerialized] private List<BranchNode> _children = new List<BranchNode>();

        public BranchNode()
        {
            _id = Guid.NewGuid().ToString();
        }
    } 
sleek berry
#

You probably need [SerializeReference] instead then

#

Thats what managedReferenceValue is for as far as I know

waxen sandal
#

^

sleek berry
#

Note, the Unity serialization system is pure madness. So you're going to run into pain if you want to work with it

patent pebble
#

I've seen some people also reporting bugs or incomplete features with [SerializeReference] in the past, maybe it's all fixed now

gloomy chasm
patent pebble
#

It does support more than 2 serialization depths though

#

iirc the issue is that if you have a nested serialized field of the same type the serialization system runs into a cycle and stops at somewhere around depth 7 to avoid the infinite cycle

#

it has to do with how [SerializeField] vs [SerializeReference] treat the values, since one creates the value and the other references it

#

it's been a while since I've gone through the serialization tribulations in Unity, but it was something like that roughly

gloomy chasm
patent pebble
#

Since I can't remember exactly how it all works, I'm not gonna give you an answer because it would probably be incorrect information, but it shouldn't be too hard to find info on how the serialization system works in Unity

gloomy chasm
#

Specifically prefab variant. It works normally, and with prefabs, just not prefab variants.

patent pebble
#

@gloomy chasm does it serialize when using [SerializeReference] ?

patent pebble
#

in the example you just said, having a Node field in a component

#

you can't have a child in a child in a child of that field

gloomy chasm
patent pebble
#

that's why I asked if it worked with [SerializeReference], because it should, due to fields serialized by reference not having the composition cycle problem

gloomy chasm
#

The dang new instance thing is still thing though :/
All that really means is that I will have to get rid of the parent field. But it isn't really needed for any of the functions, would just be nice to have.

patent pebble
#

I haven't tested how the new prefab system works with Unity's serialization so I don't know what would be the issue with prefabs and prefab variants

#

as the other person said Note, the Unity serialization system is pure madness. So you're going to run into pain if you want to work with it