#↕️┃editor-extensions
1 messages · Page 78 of 1
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
Even if you use a Property Drawer?
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
For future editors, yes
https://forum.unity.com/threads/when-to-choose-a-custom-editor-vs-property-drawer.333306/ this forum post helped me when I was learning all of this
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
Though that threat didnt solve my problem, i found it very helpful. Thank you for the share.
Have you tried using BeginArea?
Uhmm... no?...
Dont even know what BeginArea is

Ima google, give me a sec
It allows to draw GUILayout stuff in a given Rect
Type : public class UnityEngine.GUILayout
Unity Doc
Versions : 3.4.0f5 ⟩ 2021.1.0b1
Method : public static BeginArea()
Unity Doc
Versions : 3.4.0f5 ⟩ 2021.1.0b1
GitHub Source
Dont cry now, you might cry after if it does not work
BeginArea is not something I would call easy to use
It can kinda easily misbehave
Good news, it doesnt work
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
Have you overload GetPropertyHeight?
Yep, albeit i dont have any relevant property information to get the child count to extend the height.
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
Inside the BeginArea?
yep
You have 2 ways of drawing an Editor, either by using its OnInspector() (GUILayout), or by using its SerializedProperty (GUI or GUILayout)
I dont think it works
Show me the code
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;
}
I guess its time to choose the 2nd way then
But OnInspectorUI() has this behavior:
I explain myself here on how i want it to draw on the inspector: https://discordapp.com/channels/489222168727519232/533353544846147585/797513974496362506
What behaviour?
Draw its fields?
Pretty much ye
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
Thats what i think as well
If the Object targeted is being itself, you have infinite recursion
The object targeted is the objectReferenceValue of the field itself
And targeting itself should be impossible in that field.
Even if you prevent this recusion with a if, I just need to point to a copy B, which will point to origin, kaboom
Now i am wondering. Since i dont know anything about the object's properties. How do i fetch said properties?.
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
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
😅
🙂
@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
Seems like it
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.
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
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?
I think not
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
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.
I'm not really a fan of GUILayout.BeginArea
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
I dont use Layout at all for production 🙂
yeah haha i was gonna say
main reason? performance?
Perf and precision
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
They are customize to your need and only you (or team) will use it, totally undestandable
I publish them, I don't have much room for garbage ⛑️
@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
oh and it renders both the class and its inheritor:
Collections are drawn differently
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
Ofc, but what if that element is not itself?
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
They should
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);
}
More over, it kept complaining about the type is not supported pptr value on the IsCorrectType(element.objectReferenceValue.GetType(), typeof(ScriptableObject)) method:
https://paste.myst.rs/d9pp57ye
a powerful website for storing and sharing text and code snippets. completely free and open source.
I would bet the problem is earlier than this method
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
It is not because an error appears at this location that the error is the instruction at this line
Hmm
This property element.objectReferenceValue is throwing the error
Yes
Because you are calling it, while apparently the SerializedProperty (SP) is not suppose to be an Object
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?
What about the default implementation?
According to the docs, references yes but structs won't
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.
Sounds like a bad idea to me
Why?
Because hashcode is a terrible way to identify a object
Hmm
2 objects can have the same hashcode and not be equal
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
Idk what you're doing sooo 🤷
I don't have time to read though several hours of conversation
I am currently trying to create a Reorderable List that gets identified per variable
You dont need to, and im pretty sure it takes 3 seconds to look at two pictures
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?
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.
Found out GUI.Box was a thing. Ill be on my way now.
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
This is what I get when using the ObjectField while my PreviewStage is open
This is what I get when I'm on the Main Stage
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 😓
I doubt that's possible, the whole idea of a stage is that it's isolated
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.
If Client.List doens't return them then I wouldn't know of any api
You could look at the PM source
tried even with SearchAll, but dont getting assets, only the com.x.y packages.
Source it is then
@waxen sandal sry, what do you mean with PM source? i checked the PackageManager Documentation, or what did u mean?
ah ok, yes, good point. always forgetting about that unity has everything public now.
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;
}```

That is indeed cool

how to draw reorderable list in custom inspector window? By reorderable list i mean like list from new version 2020.2 or something.
@patent idol is that the [Reorderable] attribute they added? or what?
[Reorderable] attribute is by default added to lists and arrays, i think, but i'm talking about making this visual/effect in custom EditorWindow. I don't know if there is like function that i can call or something because there isn't a lot of info/
@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
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
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
Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.
@half scroll are they single-dimension arrays?
yeah
i tried replacing it with lists too but no luck with that either
oh oops i put the wrong image
you didn't share code either
we can only guess without knowing what you're doing exactly
which code would u want to see? the class that stores the arrays
that'd be a good place to start
Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.
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
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
@half scroll looks like you're creating instances of Scriptableobjects but not serializing/saving them as assets? e.g. AssetDatabase.CreateAsset()
ah i do that inside the editor script which is probably the wrong place to do that so i should probably move that
thanks for the help here it was simply because i forgot to mark the layers and sets as serializeable
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?
@grim vine are you telling us that scene is made up of ten thousand objects, each one of them with a sprite in it?
😶
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 😦
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
so you mean baking it into one giant mesh wont achieve anything?
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
yes ok.
i tried spawning all the objects, but instead of the prefab, just a cube
and performance was better
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
i have these boxes that basically disables all objects within, that improves the fps a lot. But the scene file still grows rapidly
If performance is that bad at this scope, what's gonna happen when you try to make it into a fully fledged game? 😅
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
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
well instantiating 10k prefabs seems like i'd take a while
yeah, i wonder how the editor does it, perhaps they bypass instantiation.
i'll try to write a mesh merger 😂
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
Unity's tilemap is for 2D though?
lots of similar concepts apply
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
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...
Deep profile
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?
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...
I'm going to guess that over time you're adding this listener multiple times
@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
@severe python do you know how to create custom skins for the new UI toolkit?
Read the documentation and about css?
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
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
Aint the best in GUI Rect stuff but id say that you should assign the width of the rightPanel in condjuction to your left panel.
GUILayout.Expand(Height/Width)only expands in acordance to other UI Elements. Im pretty sure there is aGUILayout.(Min/Max)method for you to use. Play around with those and see what you get
Lastly, i suggest you dont mix GUI and GUILayout stuff as it is quite hard to be precise when it comes to drawing elements. Not to mention the performance cost.
Begin/End horizontal layout
That does it too. but rip precision.
Also i doubt LeapGUIExtensions.DrawTexture(rect, color) would work with that layout method.
since it requires a rect.
Clearly, but he wants to stay with layout and the stuff
true.
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...)
2 verticals side by side no?
i like using scopes instead of Begin/End methods. It's a lot more readable
Scopes?

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

that does the same as BeginHorizontal/EndHorizontal
Yep
Except the Change scope
Which I find giganticly ugly
ah yeah I never use that
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
I've never used the property one
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
https://docs.unity3d.com/ScriptReference/EditorGUI.PropertyScope.html ah yeah they have an example on the docs
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.
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
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
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...
Avoiding 2 methods calls is an illusion, but yeah scope are more reliable & better & smoother & fluider
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
they improve readability dramatically when using nested horizontals/verticals
when I started learning GUI it was a nightmare to do with GUILayout
Even without scope, I did put brackets to indent to keep readability
yeah
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
will a using statement always dispose?
such as, if an unhandled exception occurs inside a using statement, can that prevent the dispose?
Yes
Act the same as finally
It will execute no matter what
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
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);
}
Well it's internal, so not exposed 🙂
yeah I meant there's nothing exposed that uses it either
i think it's all internal
I wish Unity let us use all those cool things they use internally 😓
It's just slightly more annoying/cumbersome, but Reflection is our best ally
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 🙃
publically facing non focusing popups that can have custom content when
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?
Except for your code being annoying, not erally
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
So, I'm having some issues here. I'm try to take an animator controller that already exists. Then I want to edit the state motions (animations) that are inside of it. I found how to fill out my panel, but no idea how to make it update.
https://gist.github.com/YelbyNoshn/3834ca9051beb0d04e9e438d92db2176
Update as in throw a new animation into one of those slots, click the update button, it updates the animatorcontroller
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.
@bold skiff I mean, animator controllers are assets, you probably have to do something with AssetDatabase?
just throwing random ideas
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.
@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
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.
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
Can you just use EditorGUI.PropertyField()?
Or are you looking for Editor.CreateEditor()?
Maybe I am looking for create editor... but I also am not?
I am not quite clear on what you are wanting.
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
@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);
}
}
}
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
In an Editor you can call DrawPropertiesExcluding
The heck! How long has that been a thing for!?
For shame! Well thank you for the heads up!
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
Nah, you just override OnInspectorGUI and call it in there.
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
There is always reflection.
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?
No, I can't just specify the editor to use, that means that more appropriate editors will not apply
There is not. You can only do it via mad reflection
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
Yeah, that is what I though. I have an extension method that does it, but wanted to ask.
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]?
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
How would I get the size of the result of DrawPropertiesExcluding
I ended up using a GUID lookup for part of it instead of SR and it fixed my issues
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));
}
}
Well shoot, so it is a bug? And you have reported it?
I think you have to do the property loop and GetPropertyHeight for each of them
I have this setup going on right now
I didn't report that as a bug because my code was convoluted enough that I wouldn't have been able to explain the issue. If yours is simple enough making a report sounds good to me, you can ask for more info if it isn't a bug and hopefully we'll learn something 😄
The bugs I reported were both crashes
LOL! No I haven't reported it for that exact same reason xD
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.
I thought they fixed that issue with SerializedReference :/
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 😄
Will they backport the fixes to 2019.4 you think? It is an LTS after all...
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 😄
I want that so bad! But I am making a game meant for release, so that doesn't seem wise to do... 😦
:/ 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
which isn't where you ever need it
but trying to do something complex in it has really just exhausted me
I used it for some contract work...
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
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
but nesting and cross referencing seems iffy
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
At least they do seem to be prioritising bugs with it above my experience with other things
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.
Unity 2 Electric Boogaloo is a real dream
they are taking an iterative approach to fixing weaknesses in it, thats honestly good enough for me
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?
Because the position you pass is not indented
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.
Look at the source on how it opens and then just invoke that instead
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.
I'd argue that's the better option but you can use GUI.Color to change the opacity
And then change it back later
That one doesn't seem to affect the color part of the control.
Shame, you probably can't then
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)
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.
Context; #↕️┃editor-extensions message
Skip the Repaint event.
Nope, that's the smart way.
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);```
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.
This, however, might just be the pencil I was looking for.
Thanks~
ColorPicker.Show(GUIView.current, value, showAlpha, hdr); is probably waht you need
Your are self-blocking your mind to go beyond the mortal ways, because you are afraid of 200 unknown lines.
It will take time, but the more you do reverse, the more the code will become easy to grasp.
And ColorField is not particularly complex, but I do understand it involves some basics to dig it easily
@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.
It raises an event on the GUIView you give it with the color
case EventCommandNames.ColorPickerChanged:
GUI.changed = true;
HandleUtility.Repaint();
return ColorPicker.color;```
@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 🤷🏼♂️
I see, unfortunately, the picker is internal, and we (Navi & I) don't know any public API to do such thing
@waxen sandal True, thanks.
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
If it's public then just access it? or is GUIClip not public
Ah.
Then use reflection to resolve the type and then resolve the method from that
internal sealed class GUIClip
Same thing as we mentioned above haha
You can use reflection to access it.
What do you mean resolve the type?
Type.GetType
But I don't have access to GUIClip is it still possible?
You can search for it by its name as a string.
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
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
I mean check the docs for Type.GetType
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
GetMethod("Unclip", BindingFlags.Static | BindingFlags.Public)
The default will fetch "Instance | Public", but you want the Static one
Same result
I think it has multiple unclip methods with different arguments
I'll check msdn if you can specify that
If you have an ambiguity exception just add the parameters in the argument
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
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
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.
You are right
its from Type.GetType("UnityEngine.GUIClip")
Isn't UnityEngine the assembly?
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.
There is
The UnityEngine part in UnityEngine.GUIClip refers to the namespace. But an assembly can contain multiple namespaces.
var GUIClip = Type.GetType("UnityEngine.GUIClip, UnityEngine"); Okay this one worked!
@onyx harness Yea, he just sent a code example of it straight after I sent that haha
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);
👍🏼
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
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
Type : public class UnityEditorInternal.InternalEditorUtility
Unity Doc
Versions : 3.4.0f5 ⟩ 2021.1.0b1
Method : public static RepaintAllViews()
Unity Doc
Versions : 3.5.0f5 ⟩ 2021.1.0b1
GitHub Source
@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! 😊
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?
Yes & no. 🙂
oh thats the worst
Care to extrapolate?
To be more specific, I'm making a CustomPropertyDrawer for an Attribute
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
So it should only not work if it encounters a cycle condition?
Do you fall on the 2nd case?
This is the only one I know where it fallbacks on default GUI
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?
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
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?
}
}
}
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
@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
PropertyDrawer has a reference to the fieldInfo and you can use that to get the value. I think you still need to hunt it down from the root serializedObject.target though.
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?
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.
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)
@rough raven can you modify the .meta files yourself?
hmm, not sure how?
can someone please explain to me how to use MultiColumnHeader and add rows to a columns
@ebon helm Here you go:
https://docs.unity3d.com/Manual/TreeViewAPI.html
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
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?
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.
Because your height calculation is probably messed up
Im literally using a EditorGUI.GetPropertyHeight() method
There's a callback on reorderablelist to determine an elements height
You need to register on that and return the correct height
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.
rect.y += rect.height + _spacing; I also doubt this is what you're supposed to do
It is, since the next element to be drawn will have the correct spacing to be drawn into
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.
So you're saying that if you return a constant value in ElementHeightCallback it breaks?
No, im saying that the value inside the ElementHeightCallback is different on the first element of the ReorderableList vs the other elements.
between the first and the other elements. I assumed that the context would be understood as i was writing the message (since you replied the 2 pictures and my questions).
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
@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...
That is unfortunate, depth issues could make it useless for me :/
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"
Anyone know if this is a control I can re-use?
Yeah, it seems to work great for polymorphic serialization. But it seems to not work great with trees still. I am going to test it on 2020.2 or something and see if it is still there. If it is then I will report it along with the managedReference problem. If I have to report both, it will take several hours I suspect :/
Which part? If you just mean the dropdown then yes. It is in UnityEditor.IMGUI.Controls.AdvancedDropdown
If you mean adding components part, then no, not without reflection.
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
Yep! That is what you want then!
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). 🙂
unfortunately I'm trying to support a wide range of versions, and in an inspector, so I'm limited to imgui
I think they do, but if you are talking about my problem with SerializeReference, then that isn't it. It works fine for prefabs, but breaks when making prefab variants.
oh no, its not in my version!
What version are you on!?
2018.4
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
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?
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
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.
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
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.
This is an AdvancedDropdown https://docs.unity3d.com/ScriptReference/IMGUI.Controls.AdvancedDropdown.html
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?
Example of one of my scripts that is not in any sort of "Editor" folder:
PlayerUpdate.cs:
https://hatebin.com/flvbitfpjy
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
Also editor code will break your build if you don't have it in either a editor only asmdef or a editor folder
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?
@livid beacon Assembly definitions are the more "modern" approach for this now
Name sounds intimidating but they're really straightforward https://docs.unity3d.com/Manual/ScriptCompilationAssemblyDefinitionFiles.html
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
@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.
oh i see
nice
ty
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.
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
Huh. I could have sworn I already tried that. That at least gives me a Texture. Thanks @waxen sandal
👍
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
If your editor script relies on various editor only namespaces and classes such as UnityEditor, and that script is outside of a Editor folder, then your build will fail.
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
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
It's not as active here but pretty much override OnGui and modify the contents of the inspector relative to that enum value.
uuuuhm.
Should be able to Google OnGui, the editor version: https://docs.unity3d.com/ScriptReference/EditorWindow.OnGUI.html
Opps, wrong one. Your want the inspector on gui (why are there so many...): https://docs.unity3d.com/ScriptReference/Editor.OnInspectorGUI.html
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
Gui layout should have a variety of tools to select in customization and https://docs.unity3d.com/2020.2/Documentation/Manual/editor-CustomEditors.html had some examples; property field is illustrated in one of the examples.
Gui layout should have a variety of tools to select in customization and https://docs.unity3d.com/2020.2/Documentation/Manual/editor-CustomEditors.html had some examples; property field is illustrated in one of the examples.
Yes, depending on how often and how computational it is. But this is simply for the editor and will not be added to the build/release file.
Inappropriate handling will cause your Unity to crash though.. 😛
Inappropriate handling will cause your Unity to crash
thats often the case but thanks for the reminder ^^
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
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
give me a sec ^^
i saw a video about the "Tyranny of MonoBehavior" that showed how you could use ScriptableObjects as enums
https://www.youtube.com/watch?v=6vmRwLYWNRo
for later studying
Get the assets here: https://bitbucket.org/richardfine/scriptableobjectdemo/
This session goes over ScriptableObject class in detail, compares it to the MonoBehaviour class and works through many examples of how it might be applied in a project.
Richard Fine - Unity Technologies
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
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
mom^^
hide the properties you want to switcharoo, and make a new inspector for those
inheritance might be your answer actually
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
you can mix them
just call base.OnInspectorGUI(); and it'll paint the default inspector
instead of drawdefaultinspector?
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
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
right you don't actually need SerializeField if you make the prop public
only thing i still don't know. is how i get a "usable" gameobject field
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
}
}
yeah i already use that (not for weapon/armor) but Equipment is already deriving as Equipment : Item and Item : ScriptableObject
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
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.
@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
doing a quick search, there's someone on the forums trying to make a multi column view https://forum.unity.com/threads/how-to-make-a-multi-column-view-in-editor-windows.647371/
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..
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
I know about that too. I was hoping to get this done in a "quick and easy" way. A man can only dream.
"quick and easy" that doesn't exist when doing Unity Editor extensions 🙃
hah yep. Life is pain and doing editor extensions is a punishment for my past sins
the more stuff you do yourself the more you learn about extending Unity's default functionality
and that's great
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.
- specifically order the SubAssest
- 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
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
if you mean using AssetDatabase you can use LoadAllAssetRepresentations? (roughly that name)
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).
does anybody know why I'm getting the same GUI point and Screen pixel coordinate when using this?
https://docs.unity3d.com/ScriptReference/HandleUtility.GUIPointToScreenPixelCoordinate.html
Vector2 guiPoint = Event.current.mousePosition;
Vector2 screenPoint = HandleUtility.GUIPointToScreenPixelCoordinate(guiPoint);
I don't understand why screenPoint is returning the same value as guiPoint
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()
How do i make conditional displaying in uxml?
Or i have to do this in cs ?
That is something OnGUI is quite good at
I believe the expected workflow (and one I use all the time) - is to construct your tree with everything you want in it, then set the display style to none on everything you don't want active via c#.
Nice
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..
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);
}
Do u guys use .visible or display.value = DisplayStyle.Flex?
usually display as I almost always want the layout to change - visible is opacity and the layout is maintained
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
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.
Undo.RecordObjet
i think i even tried that. Let me try it again. so into my custom editor script in the OnInspectorGui method right
unfortunately not working. field is null after unity restart
Then you're doing something wrong
Need more context
You coudl also just use serializedobjects instead
instead of t ?
Yeah
@whole steppe well your field is not serializable
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
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
new Unity verions have reorderable list by default.
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?
just install the recent 2020.2 version and use it.
unless I include UnityEditorInternal it wont be recognised, can i just check where it should be
the default Unity lists are reorderable lists now
ah right I don't think that's possible unless you use your own system for storing references or some sort of identifiers
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)
a quick search gave me this
looks interesting, I've never used it or heard about it
looks like something really promissing. I will look into that .Thank you very much.
maybe someone with more knowledge of keeping references to scene objects can chime in, I'm not very experienced in this topic 😅
That's the only way unlses you make your own system of course
@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?
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
hmmm, seems simple enough
Whether it's a good idea is something else
Since you'd have to validate that your SO actually works in that scene somehow
yeah the concept of storing scene references in a ScriptableObject seems counterproductive
i haven't had that need ever
It has some uses but most of the time you can solve them in differnet better ways
This seems relevant https://github.com/Unity-Technologies/guid-based-reference
looks interesting, thanks for sharing! 👌
I think, this might be more relevant
https://docs.unity3d.com/ScriptReference/GlobalObjectId.html
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?
@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
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
It uses a new one, it can't use the existing one since it doesn't exist at runtime
(I also checked the source before)
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)
The visual element looks like this for a field called rnd
This is what I want, and I can't get it with UIElements and I don't know why.
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
I ended up using imgui for some property drawers instead, given you can sort of use them within uitk stuff still
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.
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?
I think EditorApplication.hierarchyWindowChanged would be your best bet.
Thank you very much. You've been very helpful.
Can a folder in Assets be marked so that Unity will not load Assemblies in that directory?
It is not at the folder level, but AsmDef level
Sadly, not AsmDefs
Well, you can prefix the folder with a dot
these would be compiled DLLs, I'm trying to setup some stuff to manage staging and packaging of mods, but I'm do
hmm
You can alter DLL to specify if you want them to load or not
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
Read my answer again
Yes
ah! very nice, thanks a lot for the info 😊
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 🙃
@grave dirge why don't you just use AddComponent in the Reset method?
tis exactly what I'm doing
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>();
}
@grave dirge iirc you can make custom attributes for classes
that is what I'm curious about 🙂
like how would I do that?
I can find lots of information on property attributes
not much else
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
alr thank you
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
That said, making an attribute is pretty simple, see https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/attributes/creating-custom-attributes
You can then check whether your class has an attribute using reflection https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/attributes/accessing-attributes-by-using-reflection
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
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
yeah, i noticed you can change the size but i didnt see functionality to add an object to that index
that inserts an empty element
Okay, where do I do that ?
GetArrayElementAtIndex then just set the value
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
silly question , but what does this icon mean ?
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?
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
Thank you for the answer @shadow violet , but I meant the Box icon , which is similar to Prefab but its not.
Box icon, the checkmark on the right of your picture?
Oh, yeah thats what those 2 links refer to
Okay , Thanks !
Np, gl - if it doesnt work out you can always come back and post your code
💀
I guess my issue was that I did not know that attributes were a c# thing
I was under the impression that they were a unity thing
thanks for the help
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 😢
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>();
}
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)
screenshot
I don't think you can
hmm I could, but I need it to be an object selector 🤔
Think it uses this https://github.com/Unity-Technologies/UnityCsReference/blob/61f92bd79ae862c4465d35270f9d1d57befd1761/Editor/Mono/EditorGUIUtility.bindings.cs#L157
i don't think it's a bad thing that the type is visible tho?
it was more out of curiosity than necessity tbh
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
So got around the issue with having too many gameobjects
Set the name on the ScriptableObejct
Show code
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;
}
I'm pretty sure managedReferenceValue is read only
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?
Yes, because that is the only way to set the value of a field that is of normal c# class that does not inherit from Object
have you debugged what SerializedPropertyType your SerializedProperty is?
Whats the definition of BranchNode ?
Yep, SerialiedPropertyType is Generic as you would expect.
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();
}
}
You probably need [SerializeReference] instead then
Thats what managedReferenceValue is for as far as I know
^
Note, the Unity serialization system is pure madness. So you're going to run into pain if you want to work with it
I've seen some people also reporting bugs or incomplete features with [SerializeReference] in the past, maybe it's all fixed now
Oh it is 1000% not fixed now. That is why I am having to do this now because it is still broken. It does not support more than 2 deep serialization on prefab variants and when setting the value through MangedReferenceValue it creates a new instance making the whole thing pointless.
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
Oh, really? How are you meant to set the value for fields that are normal c# classes?
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
No, what I am saying is if you do
[Serializable]
public class Node
{
[SerializeReference] public List<Node> children = new List<Node>();
}
And then have a Node field in a component, you can't have a child in a child in a child of that field. It will not serialize it on a prefab variant.
Specifically prefab variant. It works normally, and with prefabs, just not prefab variants.
@gloomy chasm does it serialize when using [SerializeReference] ?
Using where?
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
Well fuuuuu....
It worked..... thank you...
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
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.
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

