#↕️┃editor-extensions
1 messages · Page 19 of 1
but its a float
damn it im lost
show me UI and say what you want to achieve, maybe it will be easier that way
i want the height of these fields to be the same
element.style gives you what is set for that instance, resolvedStyle gives you actual final calculated value at given frame for that element, thats all it is to it
one more .value
mb it sets it to 17
but not 18 as it should
you need to query for that specific element inside and set its style if I understand correctly
or use uss like normal human being XD
PopupField > .unity-base-field__input {} or maybe even deeper
Uh i had created a custom control with BaseField and it was shown in UI Toolkit. But now even i create new one, i cant see in UI Toolkit
Am an idiot nvm.
Has anyone tried to do foldout with an object in UI Toolkit?
https://forum.unity.com/attachments/foldout-gif.288720/
Hello,
Is it possible to delete sub assets inside an .fbx? I have some fbx where I want to say delete the mesh but keep the animclip.
I've tried to access the sub assets with AssetDatabase.LoadAllAssetRepresentationsAtPath(path);
And ran through them and called DestroyImmediate(asset, true);
But the asset file doesn't seem to get the changes. Tried all sort of set dirty/import after wards etc.
is there any way i can add to my class another class?
public static string AlignedFieldClass => BaseField<bool>.alignedFieldUssClassName;
No, it is not possible to combine the classes, there is no inheritance in USS or anything to that effect
oki, thanks 😄
Do you know why contentContainer is not the parent of added elements to UIElement, my issue is that Radio Button Group gets styled and not it's child container
I guess csharp toolbar.ElementAt(0).ElementAt(0) works, but for how long???
This is an amazing idea.
Is it a good idea to create fields from Init() of UxmlTraits?
I did this:
private void CreateFoldableField(string label, string propertyPath)
{
m_Foldout?.RemoveFromHierarchy();
m_Input?.RemoveFromHierarchy();
m_Foldout = new Foldout
{
text = label
};
m_Input = new PropertyField
{
bindingPath = propertyPath
};
this.Add(m_Foldout);
this.Add(m_Input);
}
And called from Init() of UxmlTraits
This is full code: https://gist.github.com/YunusYld/3c42cdf318945a7112a855ee1aadbeed
OH! I SHOULD USE PROPERTIES INSTEAD!
Nah, you should use the constructor, it's what all of the builtin elements do
public string label {
get
{
return m_label;
}
set
{
if(m_Foldout != null)
{
m_Foldout.text = value;
}
m_label = value;
}
}```
Is this ok?
No, definitely don't do that. You don't know when or if ever you will access the properties. So some will be created and some will not
What will i do 
Use the constructor 🙂
But the label returns null because Init() starts after the constructor
I'm saying don't use Init() to create elements. use the constructor to create the elements
Okey let me post the full code
I'm sorry, yeah this is fine. I didn't read it properly. You can and should set the foldout text like that! Sorry 😬
Thank you 😭
I feel like i am doing wrong. FoldableField should be inherited from PropertyField but i dont know how can i customize PropertyField since even i add the constructor, they are going invisible. I will do research as usual 
You can inherit from Toggle 🙂
Or from any other class
Ouch i never thought of that
Whaaat its cool
Or from Foldout even
But what about BindProperty() and Binding Extensions such as Bind() UnBind() it would be cool if my little pony be able to do that?
That is automatically taken care of if you implement INotifyPropertyChange
Wow i will try
Might have some good info for ya https://docs.unity3d.com/Manual/UIE-create-custom-controls.html
I was exactly looking at it but their documentation uh for me atleast, it was just like a "TAKE THIS CODE AND UNDERSTAND BY YOURSELF" i mean it is not beginner friendly
thank you tho
What this thing does actually? INotifyPropertyChanged
I want to put a PropertyField next to Foldout Label so is this thing gonna tell me "ey yo man propertyfield changed" I will test it.
Oh i need to tell that manually?
Oooookey lovely humans, this is what i've done so far!
Sooo the foldout works but wait... Did you see that!?
The unity-foldout__toggle causes this thing. But why? i dont know. I shouldnt remove it tho it changes the style of button on the left hand. Maybe i need to change the locations of toggle? Well i will fix that but time consuming!!!
You can just add a bit of margin to the field style 🙂
is there any way i can do this in uss? _button.style.backgroundSize = new StyleBackgroundSize(new BackgroundSize(15, 15));
How can i add a visual element after a visual element? Something like this:
Element
Child - I know this one from code
New Child - I want to add new child after the known Child
Child - Unknown
I read something about PlaceBehind and PlaceInFront but i dont think this is the solution...
I think Insert() is the only way.
I think it would be "slice" at the background foldout in UI Builder. I mean since it is only one that overrides the size behaviour
Okey guys i ended it up finally! Anyone would like to test the FoldableField, here is the code u can use. I didnt tested it man i am sleepy sorry. While i am sleeping you could do that. Here is the file.
How it works? You add information to the folded area. The field is shown even the fold is folded.
An example would be: Imagine an type "AMD Graphics Card" Object field and you want to display the informations.
I would like to know my mistakes in the code.
https://gist.github.com/YunusYld/3c42cdf318945a7112a855ee1aadbeed
How am i supposed to select what folder Unity installs in? The Hub doesnt bother asking me to select an installation path, and it defaults to a predetermined path on a specific drive. I have 3 drives and I want it installed in a specific drive folder. It doesnt give me such option. How can such a basic feature not exist in this software?
I use Unity Hub 3.5.1
It's preferenes > installs
Also not the right channel, this channel is for discussing the development of extensions to the editor, not for usage of Unity or IDEs
agreed but where would i ask for Hub issues?
How do I FindPropertyRelative() a property with a custom get; set;?
Apparently you can do FindPropertyRelative("<SpawnTime>k__BackingField") where SpawnTime is my property, but it doesn't seem to work
have you serialized the backing field?
yes
Can you show that
[SerializeField]
private float spawnTime = 0f;
public float SpawnTime {
get { return spawnTime; }
set {
if (value < 0) value = 0;
spawnTime = value;
}
}
That's not the backing field, that's just a field
In the end I just want a non zero spawnTime
Just use [Min(0)] on your field
public float SpawnTime { get; set; } will create a private backing field.
Your property has no backing field, it just uses private field called spawnTime
If you want to be technical about it, any private field that stores data for a public property can be called a backing field:
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/fields#:~:text=A private field that stores,otherwise changing an object's data.
So it's more of a question of whether it's a compiler generated backing field or not.
If you want to be technical about it
I don'tI didn't find it relevant, and thought it would be more confusing to have to then elaborate about terminology
We could just pretend I was saying "anonymous backing field" or "compiler-generated backing field" the whole time. Either way, a property cannot be accessed via a SerializedProperty so it doesn't matter whatever form the backing field has
Now Franzyd knows this, because I don't think they did before.
Hi all. I'm assuming get_guiDepth and set_displayIndex are editor serialization related stuff?
Begin MonoManager ReloadAssembly
The file 'MemoryStream' is corrupted! Remove it and launch unity again!
[Position out of bounds!]
UnityException: set_displayIndex is not allowed to be called during serialization, call it from Awake or Start instead. Called from MonoBehaviour 'PlayerMountControl' on game object 'Npc'.
See "Script Serialization" page in the Unity Manual for further details.
at (wrapper managed-to-native) UnityEngine.Event.set_displayIndex(UnityEngine.Event,int)
at UnityEngine.Event.Internal_MakeMasterEventCurrent (System.Int32 displayIndex) [0x00018] in <e95189d6f30b400684230df4b35c0389>:0
UnityException: get_guiDepth is not allowed to be called during serialization, call it from Awake or Start instead. Called from MonoBehaviour 'PlayerMountControl' on game object 'Npc'.
See "Script Serialization" page in the Unity Manual for further details.
at (wrapper managed-to-native) UnityEngine.GUIUtility.get_guiDepth()
at UnityEngine.Event.get_current () [0x00001] in <e95189d6f30b400684230df4b35c0389>:0
at UnityEditor.WindowLayout.MaximizeGestureHandler () [0x00001] in <434908727417408abd02bbd1a0835ef8>:0
at UnityEditor.EditorApplication.Internal_CallGlobalEventHandler () [0x00012] in <434908727417408abd02bbd1a0835ef8>:0
I'm getting editor crash after every recompile. Had to reopen Unity, enjoy the changed script, but when making another change it'll have to crash again first
Have you tried launching with a deleted Library folder yet?
Also, is there any preprocessor arguments in PlayerMountControl? Perhaps you've done something weird that has upset the serializer
(it may also be that PlayerMountControl is completely irrelevant, and just the next thing encountered by the serializer)
This is an old project which at some point i deleted the Library folder, so just today it did rebuild the Library so i didn't bother deleting again but... i'm gonna try again in case
I'm suspecting this yes. I dont have any fancy editor anything on this script. Also i'm using Odin
But the Odin doesn't do anything here and... hmm
How do i know what's after/before this?
[PlayerMountControl] Found NetworkBehaviour PlayerMountControl
[PlayerMountControl] Process Start
[PlayerMountControl] Sync Var _activeMount Mirror.NetworkIdentity
[PlayerMountControl] GenerateSerialization
[PlayerMountControl] GenerateDeSerialization
[PlayerMountControl] Process Done```
There's weaver here (using Mirror)
But yeah, this never gave a problem before
And the weaved part looks valid n no problem with the base class etc too
I don't know if you do, I've not had an error like this for ages, but I think if it persists you may have to do a git bisect or something awful to find it
popupStyle = new GUIStyle(GUI.skin.GetStyle("PaneOptions"));
I saw this code from an open source project. GUI.skin.GetStyle() searches the string inside a dictionary named m_Styles which is does not have a "PaneOptions" style. But it does have in EditorStyles which is not reachable since it is an internal style. It seems it does not adds any style from EditorStyles to m_Styles...
How does this works?
the editor style also does a research with GetStyle() using GUIStyle.skin too ._.
in ui toolkit can i unregister the ChangeValue<string> from a textfield as i get it each time the textfield is modified?
In textfield, there is a delayed option. I recommend that.
But dont know if change event getting affected by that
If not, maybe try to not registering callback via ChangeValue. Instead, i think every field has it is own method like "RegisterValueChangeCallback"
Maybe that is getting affected by "is delayed"?
An alternative option would be implement a Blur event callback which is a Focus-Unfocus thing but no idea how will u get the changed property. I think i've ran this issue before but not found any solution in my case.
I have almost no experience extending unity's engine's behaviour itself - before I go down that rabit hole, is this even physically possible to add to unity?
The ability to click+drag from hierarchy to Animator to fix lost animation clip name references?
right now I have to extremely tediously rename everything in the animation one by one
which just isnt an acceptable workflow, not efficient
not asking how to do this, asking if its even possible to do this at all
before I waste a bunch of time trying to figure out how to do this
If I have an assembly definition, let's say in folder "MyLibrary", as well as an assembly definition "MyLibrary.Editor", is there a way to tell unity that any code under "MyLibrary" in an "Editor" folder should instead go to "MyLibrary.Editor"?
The alternative is to put an assembly definition reference in each of these folders, but I'd like to get a middleground between assembly definition and the special folder name "Editor"
Unfortunately, no :(
https://forum.unity.com/threads/assembly-definition-woes.509541/#post-3402749
Looks like to avoid 8 billion asmrefs I'll just make the editor files entirely separate which isn't ideal
Does anyone know how to access the width of that expand arrow used for complex types within the inspector?
I would like to manually indent a label to make room for that arrow
I ended up just increasing the indent level by 1 while drawing the label
with using (new EditorGUI.IndentLevelScope())
15 iirc
Yeah I just don't like magic numbers so I wanted to access a getter somewhere
I think it is just the same as the indent amount. Its been a while though so could be wrong. The width is a internal static field/property on EditorGUI
But can also just do EditorGUI.IndetnRect or as you were doing, use the indent scope
hi guys, how to write my own animation preview editor window like the default clip preview? any starting point?
to be specific, I want an editor window to preview each frame of an animation clip and edit some 2D hitbox data associated to that frame
Obscure question - is there a way to customize the text that appears alongside a variable referencing a GO component (in this case an Audio Source) to show the AudioClip file name it's referencing?
preferably without GUI code for every script referencing an audio source component <_> I'd rather even extend the AudioSource code object than to customize each script GUI... but I don't think that'd let me sneak in the file name to the editor text
basically looking for a way to add the audioclip filename to that display
what the fuck, why is scriptablesingleton available but undocument in 2019 but filepathattribute is internal so can't use it
scrollView.ScrollTo(scrollToElement); This is giving me different results. Either goes to the element or if already with the element in view goes to 0,0
EDIT:
Fixed with
public static async void ScrollToAsync(this ScrollView scrollView, VisualElement scrollToElement)
{
await Awaitable.EndOfFrameAsync();
scrollView.ScrollTo(scrollToElement);
}```
- Unity is not known for updating its documentation
- Make your own FilePathAttribute. Fairly easy to do.
you're using 2019? if so proly it's time to update?
[FilePath("Assets/Something/Editor/somefile.someExt", FilePathAttribute.Location.ProjectFolder)]
public class Foo: ScriptableSingleton<Foo>
{}
They uhh forgot
Maybe he's "MAKING MY DREAM GAME"
for 4 years
this would've worked in 2019 if FilePath wasn't defined as assembly internal
ScriptableSingleton is exposed as public but not FilePathAttribute

also updating is not super trivial + there are potential tos issues so I would prefer to stay on 19
I worked on moving to 2022 and some other upgrades during downtime but now that we're probably jumping off unity I'm not even sure if doing that is worth it
getting so mad with unity right now. I simply want an editor function to get the mouse position for an editor script ... but "Event.current.mousePosition;" always throws errors
@dense agate it works fine on my machine
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
Debug.Log(Event.current.mousePosition);
}
Hi, I am really not sure if this is the right place to ask this but it seems the most appropriate, correct me if I am wrong and I'll move the question to another channel.
Here's the code before I start explaining what I am trying to achieve:
[System.Serializable]
public struct PlaceableItem
{
public ItemSO ItemSO;
public int MaxItems;
[Tooltip("Amount the item should move for when switching planets")]
public float HideOffset;
[HideInInspector] public HashSet<GameObject> PlacedItems;
}
public List<PlaceableItem> PlaceablePlants;
public List<PlaceableItem> PlaceableBuildings;
I would like to display only PlantSOs or BuildingSOs depending on the list I am adding items to.
They both inherit from the ItemSO and that is kind of a problem because when I wanna attach the scriptable object in the inspector it displays all the ItemSOs.
My first thought was have a base struct PlaceableItem and then use inheritance for 2 additional structs that would only contain either type(PlantSO, BuildingSO) and then set the list type to PlaceablePlant/PlaceableBuilding instead.
However, I've discovered that structs can't use inheritance so that plan failed.
Another approach I thought of is having an enum in the struct:
public enum Type { Plant, Building };
public Type ItemType;
and then use a custom inspector to display either PlantSO or BuildingSO with the ItemSO using a getter to return the appropriate so.
The issue is that drawing struct inspectors seems overly complicated and maybe not the best approach.
Last thing that came to my mind probably sounds really stupid. I thought maybe somehow you could display the appropriate SOs per list and gpt recommended something called PropertyDrawers.
I am really out of ideas and your recommendations/help would mean a lot.
Thanks in advance!
I am not sure if that's the case but it sounds related to the EventSystem component.
Maybe they are missing one in the scene?
yeah I edited out that reply just now. Input.mousePosition doesn't work but Event.current.mousePosition sure works.
if it throws an error, it could be that it's being used in the wrong phase
what does that mean
phase meaning like timespan, but as in codespan, the context of which a method executes and ends; Unity makes it's native getters/setters ready to use for only specific phases. add a simple 10 milliseconds delay to your code and you might get out of the phase
public override async void OnInspectorGUI()
{
base.OnInspectorGUI();
await Task.Delay(10);
Debug.Log(Event.current.mousePosition);
}
that code throws a NullReferenceException
oh wow, didn't even know that was a thing.
Is there a particular reason that is done?
I don't know for sure
Immediete mode GUIs work in different stages, not all data is available in different stages
Purely because it's not calculated/impossible to calculate
yeah, that's beyond me, I'd have to learn a lot more to understand that.
thanks either way!
can't easily say impossible. it's certainly a design flaw on Unity's Editor part
I guess theoretically not impossible, but unnecessary and potentially performance heavy
Unity's Editor event system is really flawed. it's static, yet it functions as if it were local. it adapts itself right before drawing your inspector, and then changes itself afterwards. not something you'd expect a static field to do. so when you wait a 10 milliseconds or simply a yield(), the event will not be the same event you'd expect in your context
You should learn about immediete mode GUIs
it has nothing to do with immediate mode... it's a flaw that's been rooted in very old unity editor systems and haven't changed yet.
to learn about good immediate mode GUIs take a look at dearIMGUI and feel the blessing of good quality code 🙂
My head still spinning that even in 2023, imgui is still the most ask questions in this channel 🤪
Oh you mean Event.current specifically, sure it's bad but it's just global state.
I thought I'd have to learn UITK at some point but looks like I don't have to 😛
seems they're slowly migrating to it. editor docs are slowly using UITK now. I think it's what Unity prefers and wants to standardize (that's a valid word) now. might take some time before it becomes necessary, but eventually we'll have to learn it, it appears
still need help w this
if I understand correctly, you want PlaceableItem to accept either PlantSO or BuildingSO for the field ItemSO.
if so, you can take advantage of generic types. add a <T> to your PlaceableItem struct and add a constraint to T to only accept types derived from ItemSO, which would then be used as the type for the field ItemSO .
[System.Serializable]
public struct PlaceableItem<T> where T : ItemSO
{
public T ItemSO;
public int MaxItems;
[Tooltip("Amount the item should move for when switching planets")]
public float HideOffset;
[HideInInspector] public HashSet<GameObject> PlacedItems;
}```
oh my, that was actually insanely smart never would've thought of it.
question, I've used generics only once before this and am not sure if there's a way to set the default type to the ItemSO?
well generics are great!
you can't make a default T, but you can make a class to look like the default option. you can add a class with the same name but without the T, and just have it inherit from the generic class, providing a type as T that you want be default
public class PlaceableItem : PlaceableItem<ItemSO> {}
note that because you'd be forced to use classes if you want to do this. since structs don't do inheritance
thanks for the reply, I'll stick with the struct because it's easy to serialize unlike a class
good to know that a class can have a default one
that's not a default. C# doesn't have a proper way to offer a default T. it's even considered bad practice to do so. but that's the closes solution to what you're looking for
Is it possible to get a callback before Unity begins importing?
2nd question : is there a way to cancel asset import?
is there any limit on editorprefs strings?
events for general asset related actions (delete, save etc): https://docs.unity3d.com/ScriptReference/AssetModificationProcessor.html
events for more complicated and specific actions (processing a imported 3D model etc): https://docs.unity3d.com/ScriptReference/AssetPostprocessor.html
also what'd be the best way to apply tint to an icon in editor?
I have a simple icon that I want to use and add tint depending on the parameter
gui.color?
I think GUI.DrawTexture might work, now I just need to figure out how to put icon where it'd be normally with GUIContent by drawing it directly
How do ya display one of these progress bars? All I can find is the one that takes a progress indicator :/
There's this:
https://docs.unity3d.com/ScriptReference/Progress.html
But I don't know if it integrates with the busy progress bar.
Yeah, as far as I know that is only for background tasks. But I will take a look to make sure
just saying, it has clear results in web search.
https://www.bing.com/search?pglt=513&q=unity+editor+progressbar
which points out to the EditorUtility.DisplayProgressBar and related functions
I know, I said that was the only one I could find. But tit takes a progress from 0 - 1 which I don't want.
Yeah, Progress on the other hand does.
https://docs.unity3d.com/ScriptReference/Progress.Options.Indefinite.html
Ahh!
I don't think Progress can force showing a progress dialog, but the built-in "busy" progress bar might use information from it to show the name of the progress.
Dang, looks like it doesn't :/
Oh wait
sorry I misunderstood
for the orbiting thing you gotta set the progress as -1
a magic value I found by trial and error
Oh really? Cool, good to know!
alright anything less than zero does it
Still want to see if I can get Progress to work since it seems like the new and now intended way to do it.
Nah, looks like it really is only for background non-blocking tasks. Thats too bad.
Uhh... I tried this, but when I clear it, it still stays up just isn't blocking any more... :/
I had tested with clearing and worked fine. the cancellable progress bar to be exact. are you certain the problem is because of the negative number?
I was wrong, it does affect all textures despite what documentation says
anyone knows how i can fix this UI issue on my IMGUI codde?
just curious cuz i have no idea whats causing it, lol
Hastebin is a free web-based pastebin service for storing and sharing text and code snippets with anyone. Get started now.
here's said code btw
if i make a custom editor for a type and that type is actually a field in another class but i want the editor to show up in that class how do you bind it correctly?
eg: if i have a class A which has a reference of B and i made an editor for B so i want B's editor inspector to show in A
i also need it to bind to B aswell
so the fields in B link to the ui elements by the binding path that i had set in the element settings
Uhh, like a PropertyDrawer for B? Or am I not understanding?
so B is a monobehaviour same as A but. A has a serialized field of B and i want B's custom editor i made to show in inspector on A and i also need the ui document to bind to the values of B which is of course a field now not the target
I would use InspectorElement https://docs.unity3d.com/ScriptReference/UIElements.InspectorElement.FillDefaultInspector.html
would i have to turn B into a serialized object from A then pass that in ?
Yes
okay i think i understand now
Also do note you can right-click on an object field and click Properties, and it will pop out a nice temporary editor
At least... I thought you could, it's disappeared again in the Unity version I'm looking at, I have reported a bug when it wasn't there before... do I have to report it again 💤
ok so is there a way to do it if the reference to the object isn't a monobehaviour but a regular class?
since that one requires a unity object
regular classes don't have editors
they have property drawers
so, just use a PropertyField
(which is what's used by default anyway, so I don't reaaaly understand the question)
but cant i clone the asset tree of my ui and then bind it some how to myMonobehaviour.B
I don't know what "asset tree" means, or what you're talking about. If you're trying to draw an Editor, use InspectorElement. If you're trying to draw a PropertyDrawer (or default) for a serialized type, use a PropertyField, which is what's done by default if you don't do anything.
something like this:
var m = _tankLayoutUI.CloneTree();
var m2 = _builderUI.CloneTree();
m.Add(m2);
m2.BindTo((target as TankLayout).Builder);
where Builder is not a monobehavour but just a regular class
Create an Editor with nested PropertyDrawers, and the binding will work if you properly set it up
don't try to manually construct the whole UI and bind the individual pieces
Yes, and you can use them in property drawers or editors
You should be leaning on property drawers as much as you can to avoid having to manually make editor UIs. Even when you do manually make an editor, if you're drawing a serialized object, that should just be a property field.
I can't fully make out what you're doing or why you might not be able to do that. If the objects are being pulled from all sorts of areas, and they don't have editors, it's fine to construct those manually
If you have a regular class, it should be serialized somewhere if you want to display it, and you use a PropertyField
well i made a custom ui so i can see internal data so i can stop using debug log
yeh it is serialised, but i wanted to use a more custom visual to the editor for it
this is how it looks with the two ui documents together
since builder isnt a monobehaviour i just wanted to display the info for its data
but where is it serialized? Find that property and draw it with a PropertyField
in the editor script itself
so create a SerializedObject out of the editor, and draw the property using a PropertyField
ah okay ill try it
do you mean something like this:
public override VisualElement CreateInspectorGUI()
{
var m = _tankLayoutUI.CloneTree();
return m;
}
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
SerializedObject so = new(this);
var prop = so.FindProperty("_builder");
EditorGUILayout.PropertyField(prop);
}
not sure how i tie that to my custom ui for it though
oh
But yes, practically that, except your property fields are in your UITK hierarchy and you can either use binding or just pass them the SerializedProperty
ah i wait i figured it out
so this seemed to work:
var m = _tankLayoutUI.CloneTree();
var m2 = _splineBuilderUI.CloneTree();
m.Add(m2);
SerializedObject so = new(this);
var prop = so.FindProperty("_builder");
_runningLabel = m.Q<Label>("running-label");
_runningLabel.BindProperty(prop.FindPropertyRelative("_state"));
i didnt realise i could get another property inside a serialised property
this correctly displays this._builder._state
that is very powerful editor stuff compared to the old ways
Yeah that will certainly work.
Personally I avoid manually authoring complex hierarchies and binding them, and use property drawers to create the portions of UI. It generally leads to more reusability as if that class or struct was reused the drawer just works out of the box
do you have a good reading material on property drawers ?
some how ive not even seen much about them involving ui toolkit
The concept is the same as in IMGUI, you author them, use the attribute to associate it with a class or attribute, and draw them using a PropertyField if you need to manually add them to an editor
just wasted 30 minutes wondering why my label wouldn't bind only to find they dont work for float3 only vector3
wonder if thats by design or they forgot to support their mathematics api
does anybody know how to make a custom drawn element line up with everything else?
idk how exactly to explain this but like
see how all the fields are the same width
how do I get that width
Does this particle system UI have anything to do with your problem? Or is it unrelated
oh i wanted to do something like this where i could select like
normal value or min/max
but i realized afterwards id have to make it custom anyway
probably
since i dont want the curves bit
If you're talking about the field alignment for UI Toolkit then you have to apply the alignedFieldUssClassName to the control https://unity.huh.how/programming/editor-extensions/property-drawers/ui-toolkit-aligned-field
if you're doing it in IMGUI, then you use PrefixLabel
prefixlabel?
ty
ill check it out
ok yeah thats exactly what i need wow how was that so hard to find
cant help but notice completing domain is so slow when ui builder is open
Hey, I am trying to write a function that will create a scriptableObject, holding an image. But when loading a new level, the scriptable object asset loses its data. Can you help me out please? https://gdl.space/rinibabuxo.cs
Anyone have a customized inspector that lets me organize/group scripts?
Hi all
Is there a way to call "Ctrl+D" in the project folder, in code?
And would it support nested SO assets?
I have a SerializedProperty x of a list and I'm accessing one element's properties with y = x.FindPropertyRelative
Then I edit y's floats value and after that I want to sort the x list
For some reason the changes to y aren't showing up in x
Is this intentional or am I missing something?
How are you sorting
I implemented ICompareable on the type of the list
it sorts by y which is a float
You got to apply your SO otherwise it won't set the values to the actual objects
Yes
I see
Im realizing that someone's plugin is causing constant compiling, including when I press Stop and even doing something as simple as removing a component from any game object. I did some debugging and I realize that dynamically they are "building" something. And somehow able to change a value dyanmically that increases every "update" (Play/ Stop)
return new VersionInfo() {
Major = 1,
Minor = 4,
Patch = 4,
**Build = 3936**
};
The Build variable there is the one that increases on a Reload Script Assembly prior to the Play Starting OR the Play Mode stop. It's a constant that is being updated by something, but I can't tell what.
I'm attempting to track down what is causing this as it's likely the reason for the constantly reloads of script assemblies. Anyone have any idea how they are doing this? Debugging through the editor has not given me any clues.
[CustomEditor(typeof(Dropper))] // Replace "xxx" with the name of targetscript
public class AddLoot : Editor
{
Object source;
public override void OnInspectorGUI()
{
DrawDefaultInspector();
source = EditorGUILayout.ObjectField(source, typeof(ItemSO), false);
if(source)
{
var dropp = (ItemSO)source;
if(dropp)
{
var targ = (Dropper)target;
var newdrop = new DropThing();
newdrop.ToDrop = dropp;
targ.Drops.Add(newdrop);
source = null;
}
}
}
}```Can I freely turn this on and off at will so i can have access to multiobject modification?
You should generally not use target, and use the SerializedObject / SerializedProperty workflow if you want to support multi-object editing. The code you have doesn't support multiple objects (you can use targets, but eh). Then you add a [CanEditMultipleObjects] attribute.
[CanEditMultipleObjects]
[CustomEditor(typeof(Dropper))] // Replace "xxx" with the name of targetscript
public class AddLoots : Editor
{
Object source;
public override void OnInspectorGUI()
{
DrawDefaultInspector();
source = EditorGUILayout.ObjectField(source, typeof(ItemSO), false);
if(source)
{
var dropp = (ItemSO)source;
if(dropp)
{
foreach(var item in targets)
{
var targ = (Dropper)item;
var newdrop = new DropThing();
newdrop.ToDrop = dropp;
targ.Drops.Add(newdrop);
source = null;
}
}
}
}
}```this? 
it kinda works, so ig it's a job well done, thanks!
it doesnt update as quick however?
the list size got modified, but the new item dont pop unless i reselect the Dropper
size 3, but only two elements
minibug 
You never dirty any of these objects, so the changes are not persistent
what do people generally use when you need to load some icons in some editor script? for editor windows I can set icons in default values of serializable fields (although they never update until window is reopened), but what about other components (for example visualelement)
making it would be easy but it will not work with scriptablesingleton because it looks up specific type which is in its own UnityEditor.dll assembly, I'll have to reimplement entire scriptablesingleton, granted that's easy to do but the built-in type will not work simply because the crucial part of its API is private and there is no way to bypass it (since you can't add private attribute to a type no matter what as far as I know)
are the IMGUI styles hardcoded or something?
I'm trying to copy one of the built in styles but remove icon from it but no matter what I do it stays there
I tried to modify guistylestates since that's what seems to affect background with no luck
How did people make tools that rely on polymorphism with unique property drawers before serialize reference?
Im sincerely asking cause i feel like my brain lags when trying to wrap my mind around it.
Cause if we have 10 "children" classes that derive a lot of the same logic, i would only assume we make 10 different lists if we dont serialize the reference to keep track of this data
Atm i have made my solution using [SerializeReference] for versions of 2019 and above, but i want to know out of curiosity and a want to understand
Everything was scriptable objects and inheritance, or some people did their own serialisation.
Unity engine objects support polymorphic serialization just fine, with the pain point of having to create all these assets
So wait you can serialize in a content container (i mean scriptable objects in this context)?
or am i misinteprenting what you meant?
The alternative would be to create a new asset for every single instance you need, which isnt what i had in mind @_@, and if anyone did that that sounds unfortunate
If BaseEnemy inherited from ScriptableObject then if you serialised a field of that type you can assign any subtype of BaseEnemy into it
Yea thats a smaller example than what i had in mind, per example for data handling (where you may have like 30 entries in each subchild with different parameters) wouldnt you need to create 30 instances of each scriptable object?
i understand what you mean though so i guess for more fixed solutions - examples like enemies - weapons - items and such this would work
Is there a default editor UITK class for "hidden"?
ayy lmao, writing to GUIcontent.none is fun
instead of using nulls like normal people for missing values they managed to make global writable singleton which is supposed to represent missing value, except you can just write random garbage into it and everything that's supposed to render empty space will render than content instead
How can I get the serialized property from a UITK.PropertyField?
What are the things to look out for when trying to fix a bug which causes a field to change during an Undo/Redo when it shouldn't?
Usual suspects would be usages of the Undo class if there are any. After that, I would check usages of SerializedObject.ApplyModifiedChanges().
Hello, I am attempting to use a custom GUI to update my Sound Manager Volume like so
public class SoundManagerEditor : Editor
{
SoundManager soundManager;
float desiredMusicVolume;
float desiredSoundVolume;
private void OnEnable()
{
soundManager = (SoundManager)target;
}
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
if (soundManager != null)
{
desiredMusicVolume = EditorGUILayout.Slider("Music Volume:", desiredMusicVolume, 0f, 1f);
soundManager.MusicVolume = desiredMusicVolume;
desiredSoundVolume = EditorGUILayout.Slider("Sound Volume:", desiredSoundVolume, 0f, 1f);
soundManager.SoundVolume = desiredSoundVolume;
}
}
}
The issue I am having is that I'm not sure how to save the data that I am changing in the inspector. Ideally I'd like to have persistent data between play mode and edit mode and be able to have the data saved after deselecting the object. I really do not know where to start. I looked around a fair bit on the forums and tried SetDirty() to no avail and I am struggling to figure out many other promising methods. Can someone point me towards some useful docs on the subject?
dont modify the SoundManager directly, instead modify it through the serializedObject
you do so by doing it like this:
EditorGUILayout.Slider(serializedObject.FindProperty("desiredMusicVolume"), 0f, 1f, new GUIContent("Music Volume"));
also in the start of OnInspectorGUI you need serializedObject.Update() and at the very end you need serializedObject.ApplyModifiedProperties()
I want to make an editor which shows a list of elements inside foldouts. When a foldout is clicked the corresponding data gets loaded. Only one foldout can be open at once, which I've done.
I do have some problems with data carrying over when switching between the foldouts and Undoing it. Would it be a good idea to segment the editor into two classes: one which draws the foldouts and the second one which draws the elements in and when the foldout is open?
Anyone know if it's possible to programmatically modify services settings? We have multiple games which are built from the same code base using our own build setup, but only 1 version wants to have the IAP service on.
Thank you for your response! serializeObject.FindProperty() seems to return null at this point in time. Did I miss something obvious or is there some docs on the subject I should read?
I assume this is because I define these variables inside the SoundManagerEditor class and not inside the actual SoundManager
Sorry slight misreading from my part. You need to put the exact variable name you use in SoundManager, for the variable you want to display
That's the correct variable name
Is the variable serialized in SoundManager? I.E [SerializeField] or public?
ah in that case you dont want the property, you gotta get the field "musicVolume"
Would that then not correctly update the sound through the property?
I suppose I could update it manually
Unfortunately not, that's a limitation of custom editors. There are workarounds but they are typically kinda wonky.
Personally I found that using OnValidate() to ensure the value is properly set works well for most simple cases
Since it would be triggered after you alter the field from the custom editor
Unity is developing a new serialization library called Unity.Properties which would support using properties like that in custom editor. I am not that familiar with it however and it's pretty new. So I can't say exactly how it works
can I change GUILayout.Button color directly somewhere instead of using GUI.backgroundColor ?
how do i know when the user has not chosen anything yet? EditorSceneManager.SaveModifiedScenesIfUserWantsTo();
currently i have some code that looks something like this
if(!EditorSceneManager.SaveModifiedScenesIfUserWantsTo())
return;
MultiSceneManagement.LoadCollection(TargetCollection);
but i cant really wait for the bool to become true or false as far as i know. unless its nullable which would be dumb right?
this is code that should just be called once when the user attempts to load the collection
I'm writing a custom property drawer for something that's getting rendered in an IMGUI property drawer
I'm having a surprising amount of trouble putting two property fields side by side...
(since you can't use EditorGUILayout in a property drawer)
should I just make two Rects out of the posiiton rect?
subtracting half of the width does not appear to be correct
I actually don't quite get why this is correct.
Rect left = new Rect(position);
// left.center -= new Vector2(position.width / 2, 0);
left.size *= new Vector2(0.5f, 1);
Rect right = new Rect(position);
right.center += new Vector2(position.width / 2, 0);
right.size *= new Vector2(0.5f, 1);
I feel like I should have to move both the left and right rects
I think it is your use of .center which is confusing. Idk if this maybe makes it a bit clearer what is happening
(small error right.xMin should be right.x)
Ahh, yeah. You can also simplify your code
Rect left = new Rect(position);
left.xMax -= position.width /2; // could also just do left.width /=2;
Rect right = new Rect(position);
right.xMin += position.width / 2;
I am trying to create a material that will use an image I have in my assets folder, but when I try to drag and drop into the Sprite Texture thingy its grayed out and I can't neither clicking or drag and drop works, any idea why?
3d or 2d
2d
Sprites/Default won't let you set the texture
I have created that material, is the one that is shown on the inspector
Oh
I wanna set the texture of this materiaal to this image
No idea whats that, I guess just 2d
Thank you, I managed to solve the issue

But too many options can be confusing fr 💀
It's just the way sprite rendering is handled in Unity
[Serializable]
internal struct UICallback
{
public string MethodName;
public int IntValue;
public float FloatValue;
public string StringValue;
public bool BoolValue;
public Enum EnumValue;
}
I wanna serialize some data ill need later on to create delegates from. All methods I consider for this puropse take 1 parameter and it can be either an int, float, string, bool or (and here is my problem) Enum. Enum class isnt serializable so I will need to store it either as an int or string. Have anyone had this experience and can tell me which will be better?
Important note: Ill also need to display that enum in editor, which wont be a huge pain in the *** I guess, but if someone also already knows how to do it will propably safe me some time too
how can I display TMP_SpriteCharacter in the editor ?
I have no clue but if there is no native way to do it I can suggest checking if it is possible to cast it to a Sprite or Texture2D for display purpose, it has Sprite in name so maybe its doable 🤷
ListView does not record Undo on item move/add/remove or am I doing something wrong?
If you're using binding property it should, but if you're registering callbacks manually then you're on your own
well... I register callbacks for make and bind item, but moving, adding and removing list handles on its own
a simple hack is to just Rebuild the whole list when undo is called.
Note, you should do your own filtering so Rebuilding only when needed
there are events on itemsAdded and Removed, but to manualy register an Undo i would need something like beforeItemsAdded or something... and there is also no event or callback for item move
hmmm yeah thats a workaround I guess
w8 no... it is not a workaround at all XD
this doesnt change anything cause nothing is even recorded onto undo stack
yeah, thats the manual way...
There's a new-ish examples to bind ListView via binding property so you don't need to register callbacks, this way, Undo/redo will work ootb
it is a workaround, I said that with assumption that you know how to do recordUndo, which is quite simple
I need to bind it on my own unfortunately, native binding wont do it
I did this myself in my own project awhile back
hmmm will TrackPropertyChange work when tracking property pointing to a collection?
maybe that would work
but I guess again i will be notified AFTER item is moved/added/removed so i cant call Undo.Record
or im missing something idk
yeah, you don't want the manual way, use a binding property, there's an example for it that was released for 2022.x iirc
which is the prefered way
the example was part of uuitoolkit manual, so you wont finding it in the docs
so you dont mean this example?
https://docs.unity3d.com/Manual/UIE-bind-to-list.html
although this one is still pretty useless for me XD
that should do it yeah
why?
because there is a reason for my custom bindItem callback to be around 100 lines long
simple as that
60 lines to be exact, my bad
you can do the bindding with inlinestyle... just the binding part
it's a 1 liner basically
im not sure if im following...
oh ok im starting to understand what you mean
but still there is one catch. At some point I need to bind EnumField to an int property, which doesnt work so I need to manually add propertyTracking callback to that field
and that wont do it with inlinestyle
@halcyon pine
private static GUIStyle s_lockButton;
[SerializeField] private bool _isLocked;
private void ShowButton(Rect r)
{
s_lockButton ??= "IN LockButton";
using var cCS = new EditorGUI.ChangeCheckScope();
_isLocked = GUI.Toggle(r, _isLocked, GUIContent.none, s_lockButton);
if (cCS.changed)
{
Debug.Log($"{nameof(_isLocked)} Changed");
}
}
That is much simpler than I had! Thanks.
It magically gets called, an undocumented Message function
And getting it to actually lock the window to a specific item?
that is completely up to your own code to implement
cache the selection and don't change it for the window when _isLocked is true
That's actually the part that I was less sure about. I got the... well, a lock button implemented though this solution is a lot simpler
I will try to figure it out in the morning... er, afternoon, whenever my brain reboots
I got an editor script that will automatically select the fbx associated with a prefab, how do I get the Inspector to automatically switch to the Animation tab of the import settings?
Get Type.GetType("UnityEditor.ModelImporterEditor,UnityEditor") using Resources.FindObjectsOfTypeAll and use reflection to set m_ActiveEditorIndex to 2
omg thanks 🙏 I was just looking at the UnityCsReference at the ModelImporterEditor
looks like they use EditorPrefs to set the last active tab. This works:
EditorPrefs.SetInt("ModelImporterEditorActiveEditorIndex", 2);
Yes, that's an option but it won't do anything if the window is already open
But you can refresh that if you want to avoid the reflection
works fine for me, I set the importer to be seen in the inspector by simply Selection.activeObject = something; and that works, looks like that EditorPrefs is read again somewhere along the way when the selection is changed
Is it possible to make a specific visual element in custom editor be drag&drop'able in a way that when dropped on UnityEvent property field it will add some associated UnityAction to that event?
I read drag&drop examples in docs, but it shows either drag&drop visual element in a boudry of one window, or funcionality of dropping assets to a specific visual element
but I would need to somehow store information about some UnityAction when dragging my visual element and if it finds another visual element (on a different inspector) which binding path points to UnityEvent property when dropping it would add this UnityAction to that UnityEvent property
If it is a different window you will want to use DragAndDrop.SetGenericData(..) to set data based on a string key. And then get it via its Get counterpart
that is a very good anchor point that google didnt provide me with. Thanks, ill go check it
I came up with much simpler (and obvious) solution :V Ill leave drag&drop maybe for future development
Is there a way to customize the icon in an asset selection window? RenderStaticPreview only affects the Project window icons
I'm trying to create a context menu function that I will run on an object in prefab mode, which gets the path of the prefab this object is part of. I've been trying the PrefabUtility classes, but they all return null for me... PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot seems like it should be it, but if I run that with gameObject.transform.root.gameObject as a parameter it returns null. Any ideas?
how can i make sure a serialized property is updated/saved after edited in a property drawer? i cant seem to access serializedObject.Update(); im guessing thats because the struct im making the propertydrawer for is not the same thing
Have you applied modified properties to the serializedObject? https://docs.unity3d.com/ScriptReference/SerializedObject.ApplyModifiedProperties.html
I didn't try yet, i tried just starting with having update in the beginning as thats what you would do before anything else. But ill check it out when i get back
The thing that draws the property drawer is what applies changes to the SO
unless you're operating on a different SO because your drawer is drawing a different object, changes should be applied properly
TIL selecting an UXML and have it be previewed in the inspector will init the custom elements it contains, so it will mess up if you set static variables.
ok so as long as i handle the property correctly outside of the drawer it should be good?
Yes
ok thank you 
another quick question. is it possible to add lables between the dropdown and the list GUI? i want to make some lables like this above the list elements Checkbox 1 | is in build | Scene
if not i'll just add some GUIcontent's
i think i figured out a solution. having different guicontent for when its expanded / closed
is there a way i can make menu items dynamic? like say having menu items that are shortcuts to something in a list somewhere
got a weird problem but not sure why its happening, my editor script generates meshes and assigns them to child gameobjects to the parent gameobject, yet when i save the prefab (i have auto save on) nothing is saved - it generated fine however. I also tried generating in scene and updating the prefab by applying all overrides from the prefab options, but that also doesn't save anything
im confused why this is happening
this is probably because its not registering a change has happened. you might need to set the prefab dirty
im thinking its not serialising the created meshes so they aren't saved
whait, so the mesh itself is not saved anywhere is what you mean?
i think so? i created gameobjects as children to a gameobject in the scene, if i then drag the parent and save it as a prefab - those child gameobjects have null meshes
its like they all just vanished into thin air
if you want a generated mesh to be persistant you probably want to save the meshdata somewhere. either in a file or asset
not unless the meshdata is stored somewhere in it. like in a serialized class
damn okay kinda wish dragging them to prefabs would store the mesh data for you
there are plenty of ways you could store it though
what if i generate meshes and have them as references in a scriptable object
will that auto save them or will i still need to save to asset database
same issue i believe
you could put all the meshdata in a scriptable object if you wanted to do that though
dont know if thats the best way of doing it though
probably just to make it an asset itself
anyone knows where i can find documentation on styling the hierarchy? i just want to make scene groups. im going to sleep so if anyone has an answer please ping me
So my editor code is simple enough it looks like this:
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
if (GUILayout.Button("Generate"))
{
((LayoutAsset)target).Test();
}
}
And my script has this:
[SerializedField] GameObject _prefab;
public void Test() => Load();
void Load()
{
//TODO change to unique path
//check if prefab exists
if (!AssetDatabase.AssetPathExists(_assetPath + GetInstanceID() + ".prefab"))
CreatePrefab();
_prefab = PrefabUtility.LoadPrefabContents(_assetPath + GetInstanceID() + ".prefab");
}
void CreatePrefab()
{
//TODO change to unique path
GameObject go = new(_name);
_prefab = PrefabUtility.SaveAsPrefabAsset(go, _assetPath + GetInstanceID() + ".prefab");
DestroyImmediate(go); //delete from scene
}
The idea here is, either the prefab exists and should be linked to the field in the scriptable object as _prefab or if it doesn't yet exist - create one and assign to the field.
It seems very weird to use LoadPrefabContents and attempt to serialize that relationship
LoadPrefabContents loads an instance into an isolated scene
oh
it's not the asset, it's an instance of the asset
what method should i use then ?
AssetDatabase.LoadAssetAtPath
ah okay so prefab utility to save, asset database to load
ok that worked!
thanks!
the api for all this seems a bit all over the place lol
The PrefabUtility API is for doing unique operations with prefabs, mostly with instances (creating, loading, editing).
The AssetDatabase API is for working with assets. Once the prefab instance is an asset, the PrefabUtility API mostly stops caring about it, because the AssetDatabase API has it covered
i see
@visual stag by the way regarding GenerateUniqueAssetPath the issue i had with this is the input string would need to be unique, so say i used private string _name if i then renamed it the string path would no longer be correct
its why i thought instance id would be always the same
InstanceIDs are unique for objects loaded in memory
they do not persist between loads
so should i use AssetDatabase.GetAssetPath(this); where this is the ScriptableObject?
use guid instead to get the assets path
I have no idea what you're trying to do with these names. Just reference the asset directly by serializing a reference
You can name it whatever you want, if you want random names, use a GUID or something. GenerateUniqueAssetPath just checks whether an asset exists at that path, and will append a number to the end if it does
well for example if i proc gen some mesh in editor say this:
Mesh mesh = new Mesh();
AssetDatabase.AddObjectToAsset(this, mesh);
so this is now saved to the scriptable object, now some time later i need to load that mesh to add to the prefab reference, how do you specifically get that specific mesh object
since it was proc gen i wont know the name of the mesh
Well, it would be best if you serialized a reference to mesh when you added it, so you don't just pass it off to the asset database and forget about it
But if you did want to find the objects you've added to the asset you can use https://docs.unity3d.com/ScriptReference/AssetDatabase.LoadAllAssetRepresentationsAtPath.html
i see, so i'll have to figure out some procedural naming convention then
their example is so weird:
Object[] data = AssetDatabase.LoadAllAssetsAtPath("Assets/MySpriteTexture.png");
the fact there is multiple assets for a path linking directly to a png file
just so strange to my brain
The file is in the file system, it's just used to generate assets and as the key to find them, the asset database creates a sprite sheet that has the Texture at the root and the Sprite assets as children
ah i see
im getting a weird error deleting assets for this bit of code:
void DeleteAllAssets()
{
var objs = AssetDatabase.LoadAllAssetRepresentationsAtPath(AssetPath);
Debug.Log(objs.Length);
for (int i = 0; i < objs.Length; i++)
{
Debug.Log(objs[i]);
AssetDatabase.RemoveObjectFromAsset(objs[i]);
}
}
seems to return a null object but there is clearly a mesh asset in there
shouldn't that give me a mesh object since its a sub asset to the SO
Does anyone know if this is an error or intentional (that would be weird)? Unity's ScrollView code
ok so ive been looking into EditorApplication.hierarchyWindowItemOnGUI to add some features, but how can i check when the scene is being drawn in the hierarchy? everything else is objects and scenes are not objects 
I am having some difficulty. I'm updating my setup automation package and I want to set some player settings via code. Does anybody know if it is possible to set the Override Default Bundle Identifier to true as well as setting the Active Input Handling to New Input System in code?
is it possible to make ur own gui button class and write behaviour in that class then append that in editor script
Are you being sure to save/refresh/etc.
Of course it is possible to set it, if you can set it from the GUI. No idea what API it is though (might require reflection for all I know), this is a case where I would look at the source code for the GUI to see what APIs those controls are showing are
I think thats because the file is a sprite and it can have sub assets
any one know how to keep an object field in sync with the field of the class? I have this bit of code:
var objField = new ObjectField("Tank Asset File");
objField.objectType = typeof(TankAsset);
objField.value = (target as Tank).Asset;
objField.RegisterValueChangedCallback(evt =>
{
_tank.Set(evt.newValue as TankAsset);
objField.MarkDirtyRepaint();
Refresh();
});
root.Add(objField);
it keeps losing the reference
TankAsset is a scriptable object if that matters
once i lose focus on the inspector the field is empty again
i thought mark dirty would keep it's state
and the field in target is a serialised field
Bind a serialized property to the field instead is what I normally do.
I've so many questions for gui events like why are the values for left clicking with a mouse and not clicking the mouse at all result in the same 0 return value. Also, why are input events mixed together with other arbitrary events? Figuring out if the scene is repainting this frame shouldn't be tied together with if my mouse is being dragged.
why are the values for left clicking with a mouse and not clicking the mouse at all result in the same 0 return value
What do you mean?
Figuring out if the scene is repainting this frame shouldn't be tied together with if my mouse is being dragged.
I mean it isn't really, that is what the Drag event is for. Or do you mean that they shouldn't be in the same event system?
If that is what you mean, the event system is just a generic GUI event system, any and all GUI related events are send through it.
https://docs.unity3d.com/ScriptReference/Event-button.html
0 is also the default value when there's no input, but I can see here that I should also be checking if the input is the mouse even though Event.Button is primarily for mouse input? And what I mean by the event repaint getting tied together with mouse dragging is by the event type. I'm having a hard time trying to make my logic consistent, but trying to keep track of input event types seems difficult since it changes every frame.
Ah yeah, the general workflow is to either use a if chain or a switch on the Event.current.type to get the type and then do whatever logic you need inside of that if/case statement
For some reason list view doesnt update when adding or removing elements, but it applies changes, so to actually see them I need to reopen inspector. Any idea what may be causing it and how to fix it? Is is possible that it just cant handle too long binding path or something? Cause it looks like this: States.Array.data[0].TransitionsTo.Array.data[1].conditions.Array.data[1].conditions.Array.data[1].Strings (it is nested pretty deep)
its created simply with PropertyField
foreach (var property in prop.GetChildren())
{
var p = new PropertyField(property);
foldout.Add(p);
p.BindProperty(property);
}
uitk's ListView hates nested classes
that disables the element so you cant select a file for it
wat?
binding to properties for ui element disables their use to change the value yourself
What do you mean... you can set them just fine...?
hmm weird for me it becomes greyed out
show us the code, maybe we will notice something
maybe it is the case, when I add property field there which is bound to a collection less deep (shallower? idk if thats even a word) in serialized object it works just fine, but I cant change structure of data to workaround this issue in that way, it needs to be deep :/ I need a solution
if there was only an option to create serializedObject or inherit from Unity.Object for pure c# classes... (i know it is impossible, but i like to dream)
easy to workaround it. In your template you do something like this
Action<VisualElement, int> bindItem = (e, i) =>
{
if(itemSource.Count -1 < i)
{
itemSource.Add(new MyClass());
}
...
};
or alternativey if we had serializable dictionaries technically everything could be level 1 deep in path :V
nah. just do the above and you'll be good, no matter how deep is your nested class
but also I dont know source collection, dont know the type, I know hardly anything about what im displaying. It is user defined class that I need to display in my inspector, thus I simply iterate through all properties and display them with PropertyField
user defined class? then how'd you bind each fields if they can be any types OR any fields etc
I have a list of conditions. Condition is my custom class and it is abstract, so when binding list item it either displayes 1 of 3 predefined classes derived from Condition, or user defined class that inherits from Condition. If it is the latter one I just iterate through properteis and add a property field
public class NewCondition : FSMC_Condition
{
public string Text;
[Range(0, 5)]public float Number;
public bool Test;
public List<string> Strings;
}
user difened condition (it need to implement one additional method)
if (affixState == AffixState.Active
|| (currentEvent.isMouse
&& currentEvent.type == EventType.MouseDown
|| currentEvent.type == EventType.MouseDrag
&& currentEvent.button == 0))```
What a pain trying to get drag logic to work.
You parsing triggers? I was thinking about that but just went with a lot of pre-defined methods and delegates and SOs
trigger in my state machine actually shares the same class with a bool parameter, only has a flag to switch back to false when it is consumed, cant get easier than that XD
Are you applying any styling to that object field?
silly question, does unity have a special property drawer for char
if so, how can i get it? i cant seem to find a EditorGUILayout.CharField method
So this code works in an editor window but not in a runtime UI Document script:
IManipulator manipulator = new ContextualMenuManipulator((evt) =>
{
evt.menu.AppendAction(name, (x) => { action.TryInvoke(); }, status);
});
source.AddManipulator(manipulator);
is there a reason for that; was it not intended to work for runtime or is the reason it's not working on a Visual Element in the game view for me more of a styling issue?
It doesn't (afaik), you could use a TextField and always trim it's content to not be longer then a single char, I did something similar for a Crossword Editor once
noted
right now i'm in a bigger headache since i'm trying to find a way to get the Quaternion property drawer
which, afaik, it's not a regular Vector3 drawer using the euler angles
because i tried that and i started getting a bunch of impressicion from changing values
i was thinking on using the internal "ScriptAttributeUtility" class to use the "GetDrawerTypeForType" method
which apparently returns a Drawer for a Type
despite doing the reflection, the method is returning null, so i must be missing something.
What are the imprecisions you get with using a Vector3 for Euler Angles?
I used a Vector3 field for them as well, but it was for a Spline Tool, so I had Rotation Gizmos in the Scene as well
its for a serializer system i'm working on
in this case i cant just do a Property field, because the property itself just stores either a unityengine.Object or a string
Oooh I see, that's probably because you're converting from Quaternion to EulerAngles everytime
which later gets deserializeed at runtime
typeDrawers.Add(typeof(Quaternion), (labelTooltip, value) =>
{
Quaternion quat = (Quaternion)value;
Vector3 euler = quat.eulerAngles;
euler = EditorGUILayout.Vector3Field(labelTooltip, euler);
return Quaternion.Euler(euler);
});```
prolly
Couldn't you store a Vector3 representation only, and provide the quaternion only at runtime when the data is already set?
That's not the most beautiful solution, but the one with the least headache
Eventually, create a Wrapper struct that's internally working with Vectors, but has another Property that constructs the Quaternion for the actual "User"
hmm
actually
yeah i can do that now that i see
ugh
no i cant really do that, if i want tto do that i'd have to implement a special case for quaternions. because the Serialization handler expects a Quaternion and not a VEctor3. which in turn means i need to convert the quaternion to euler and i get the impresicion regardless
and i dont really want to add another edge case, i already had to do that for Enums to be serialized properly
tbh since this is returning null
it mmight as well be what youre saying
so... i guess i'll make another edge case 
VS is telling me my second return is unreachable code? I'm trying to make this editor related function safe to reference in non editor scripts
public static IEnumerable<ValueDropdownItem> GetScriptableObjects(Type type)
{
#if (UNITY_EDITOR)
List<ValueDropdownItem> newScriptableObjects = new List<ValueDropdownItem>();
IEnumerable<ValueDropdownItem> scriptableObjects;
scriptableObjects = UnityEditor.AssetDatabase.FindAssets("t:ScriptableObject")
.Select(x => UnityEditor.AssetDatabase.GUIDToAssetPath(x))
.Select(x => new ValueDropdownItem(x, UnityEditor.AssetDatabase.LoadAssetAtPath<ScriptableObject>(x)));
foreach (ValueDropdownItem item in scriptableObjects)
{
if (item.Value.GetType() == type)
newScriptableObjects.Add(item);
else if (item.Value.GetType().BaseType != null && item.Value.GetType().BaseType == type)
newScriptableObjects.Add(item);
}
return (newScriptableObjects);
#endif
return (null);
}
Theres other ways I can do this but curious what I'm missing here
You want to use a #elseif and have the return null there. Otherwise in the editor, the code compiles to look like:
return (newScriptableObjects);
return (null);
ah ty
I'm working on an AssetModificationProcessor, and finding that new folders are not returning their GUID when any other asset would.
public class AssetProcessor : AssetModificationProcessor {
[InitializeOnLoadMethod]
public static void Init()
{
EditorApplication.update += OnUpdate;
}
/// <summary>
/// Some callbacks must be delayed on next frame
/// </summary>
private static void OnUpdate()
{
if (Actions.Count > 0) {
while (Actions.Count > 0) {
Actions.Dequeue()?.Invoke();
}
ProjectCurator.SaveDatabase();
}
}
static void OnWillCreateAsset(string assetPath)
{
UnityEngine.Debug.Log("Asset path: " + assetPath);
if (ProjectCuratorData.IsUpToDate) {
Actions.Enqueue(() => {
UnityEngine.Debug.Log($"Guid string is: " + AssetDatabase.AssetPathToGUID(assetPath));
var guid = AssetDatabase.GUIDFromAssetPath(assetPath);
if (!guid.Empty()) {
ProjectCurator.AddAssetToDatabase(guid);
} else {
UnityEngine.Debug.LogWarning($"GUID for asset at path {assetPath} is empty");
}
});
}
}
For most assets the correct GUID will be available in the deferred callback, but for empty folders I get this:
Asset path: Assets/_Game/New Folder.meta
UnityEngine.Debug:Log (object)
Ogxd.ProjectCurator.AssetProcessor:OnWillCreateAsset (string) (at C:/Users/rhysv/Projects/project-curator/Editor/AssetProcessor.cs:49)
UnityEngine.GUIUtility:ProcessEvent (int,intptr,bool&)
Guid string is:
UnityEngine.Debug:Log (object)
Ogxd.ProjectCurator.AssetProcessor/<>c__DisplayClass4_0:<OnWillCreateAsset>b__0 () (at C:/Users/rhysv/Projects/project-curator/Editor/AssetProcessor.cs:52)
Ogxd.ProjectCurator.AssetProcessor:OnUpdate () (at C:/Users/rhysv/Projects/project-curator/Editor/AssetProcessor.cs:25)
UnityEditor.EditorApplication:Internal_CallUpdateFunctions ()
GUID for asset at path Assets/_Game/New Folder.meta is empty
UnityEngine.Debug:LogWarning (object)
Ogxd.ProjectCurator.AssetProcessor/<>c__DisplayClass4_0:<OnWillCreateAsset>b__0 () (at C:/Users/rhysv/Projects/project-curator/Editor/AssetProcessor.cs:57)
Ogxd.ProjectCurator.AssetProcessor:OnUpdate () (at C:/Users/rhysv/Projects/project-curator/Editor/AssetProcessor.cs:25)
UnityEditor.EditorApplication:Internal_CallUpdateFunctions ()
Does anyone know why this might be?
Ahhh, silly me, it's the .meta file, not the folder itself.
weird
we need a rubber duck emote here XD
Ive spend some time to change data structure a bit and I managed to shorten binding path to AllTransitions.Array.data[5].conditions.Array.data[0].conditions.Array.data[1].Strings which is MUCH shorter than before, but problem persists...
ok this is freakin wierd but I made it work, although im very not proud of the solution. I added callbacks to add items and remove items that are updating serialzied object and then scheduling rebuilding list (without schedule it doesnt work). To make it more interesting rebuilding on itself doesnt work unless I manually unbind and bind again that list before calling Rebuild()
Try calling rebuild then refreshitems idk why, but that works different (or refresh and then rebuild, I don't remember which order)
I will guess that I will get error while binding to missing item, but lets see
well... I was wrong. Literally nothing happens and im back to the old problem. Lists representation stays the same, although array size display updates itself
While testing literally everything that came up to my mind, I would say with a process of throwing sh*t on the wall until it sticks the only solution that works even looks like a random combination of code
if (property.isArray && property.propertyType != SerializedPropertyType.String)
{
var p1 = property.Copy();
var l = new ListView() {showAddRemoveFooter = true, showBorder = true, showBoundCollectionSize = true, showFoldoutHeader = true, headerTitle = property.displayName};
foldout.Add(l);
l.BindProperty(property);
l.itemsAdded += i => { l.Unbind(); l.BindProperty(p1); l.Rebuild(); };
l.itemsRemoved += i => { serializedObject.Update(); l.schedule.Execute(() => { l.Unbind(); l.BindProperty(p1); l.Rebuild();}); };
continue;
}
is it possible to change how the hierarchy is drawn so i can add a row above the first scene here?
only thing ive found is EditorApplication.hierarchyWindowItemOnGUI which only allows me to add on whats already there
[CustomEditor(typeof(TileMap3D))]
public class TileMap3DEditor : Editor
{
private int brushSize;
private SerializedProperty brushSizeProperty;
private TileMap3D tileMap3D;
void OnEnable()
{
tileMap3D = target as TileMap3D; // Initialize tileMap3D
brushSizeProperty = serializedObject.FindProperty("brushSize");
}
public override void OnInspectorGUI()
{
EditorGUILayout.PropertyField(brushSizeProperty); //NullReferenceException
}
}```
Any reason I get an error here? Can I not set up SerializedProperties which target variables directly on the editor script, or am I missing a step here?
I can make it work if I set the value on the TileMap3D class for which this Editor script targets, but it makes more sense to be here.
where have you serialized brushSize
oh, I had it serialized here
Because 1. private fields are not serialized, and 2. serializedObject is your target as a serializedObject
If you want to get the serializedObject for this editor, new it
[CustomEditor(typeof(TileMap3D))]
public class TileMap3DEditor : Editor
{
private SerializedObject editorObject;
private SerializedProperty brushSizeProperty;
[SerializeField] private int brushSize = 0;
private TileMap3D tileMap3D;
void OnEnable()
{
editorObject = new SerializedObject(this); //Not sure if this is correct
tileMap3D = target as TileMap3D;
brushSizeProperty = editorObject.FindProperty("brushSize");
}
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
serializedObject.Update();
editorObject.Update();
EditorGUILayout.PropertyField(brushSizeProperty);
serializedObject.ApplyModifiedProperties();
editorObject.ApplyModifiedProperties();
}
}```
So this is where I am at with the code and I am sure stuff is still incorrect, but I got the value exposed on the GUI now, yet it's greyed out such as it's readonly. Really, I'm not sure at all what the composition of this should looks like since it seems like everyone just uses the editor's serialize object and the script that it targets.
My assumption is that I need two serializeobjects? Perhaps I now need to figure a way to tell the editor to target it too, or am I misunderstanding that too?
You never call editorObject.ApplyModifiedProperties(); after setting the brush size
Ah, I left some stuff out here. Either way, it should still be editable in the GUI even if it doesnt update* right
This is how it's looking, and my assumption is because of the targeting isn't correct.
huh... yeah weird...
I mean, does it make sense what I am doing here? Or should I just keep the brush size on the TileMap3D script, even though it's more related to the editing of the TileMap if you understand what I mean
Nah it should work fine...
hummm
is doing editorObject = new SerializedObject(this); ok then? thats not how ive been doing it before
editorObject = new SerializedObject(serializeObject); is a compiler error
I'm not exactly sure what vertx means by "serializedObject is your target as a serializedObject"
but my understanding is that the Editor class has an instance of SerializeObject
but usually you're using that with the class you're targeting
in this case however, I am targeting a script while also trying to have serializeproperty and data on the editor script itself. So, I assume I need 2 serializeObjects
cant you just the property which is available from the Editor class that you are extending from Editor.serializedObject?
Like this? Throws a reference error
oh isee
I'm kinda stumped, but the value does show in the inspector, I just can't click modify it (it's like in a readonly state)
its on the class and you just want to edit? thats it? nothing special?
Yeah, it's on the editor class, but I want to use it as a serialize property, meaning that the undo is handled by unity
I've got it working if the data itself is on the targeted non-editor class, but apparently this way is creating some extra work.
it really should just be brushSizeProperty = serializedObject.FindProperty("brushSize"); if its throwing errors there might be serialization issues in the original script
like if its a struct that isnt set as serializable could be one cause. idk what kind of type brushSize is. if its just an int it shouldnt be any issue as long as its serialized
it's just an int
but yeah, I've tried that again but
EditorGUILayout.PropertyField(brushSizeProperty);```
Throws an object reference exception
assuming that I use the editor's serializeObject
the int itself is on the editor script
and when you do that brushSizeProperty is the expected object it should be?
if its not there is some kind of issue when finding it
private SerializedProperty brushSizeProperty;
[SerializeField] private int brushSize = 0;
brushSizeProperty = serializedObject.FindProperty("brushSize");```
yeah but have you debugged it?
What should I be looking for in the stack trace?
And put the breakpoint on brushSizeProperty = serializedObject.FindProperty("brushSize")?
if you brake it, then you can check the object brushSizeProperty directly if its set to null or not. you would probably need to go to next step for it to be set though from there
so yeah it's not finding it on the editor script
as brushSizeProperty = serializedObject.FindProperty("brushSize");
I hate string stuff
hideFlags &= ~HideFlags.NotEditable;
_serializedObject = new SerializedObject(this);
That's the dumb workaround for making the editor's SO editable
oh huh
wait when would you need this?
When drawing a SerializedProperty of an Editor
it's fine for EditorWindows, just Editors need this apparently
for any SO?
aight ty guys this is why I try to avoid editor stuff haha
in the editor for my config_SO for my package im doing things like brushSizeProperty = serializedObject.FindProperty("brushSize"); just fine without issues
what could the difference be?
same thing for other editors for other scriptable objects
I'm not too sure of all of this as I've written a lot of it a few months ago, but I assume that the editor's serializeobject isn't looking for properties on the script itself, but the script that it's a custom editor to.
I'll have to play around with it later with a fresh new setup as there could be perhaps something I am overlooking.
as an example what im doing and it works just how it should and looks like this
[CustomEditor(typeof(MultiSceneToolsConfig))]
public class MultiSceneToolsConfig_Editor : Editor
{
MultiSceneToolsConfig script;
SerializedProperty packageVersion, useBoot, wizardStartUp;
SerializedProperty bootPath, targetBootScene, collectionPath;
private void OnEnable()
{
script = target as MultiSceneToolsConfig;
packageVersion = serializedObject.FindProperty("versionNumber");
wizardStartUp = serializedObject.FindProperty("startWizardOnUpdate");
useBoot = serializedObject.FindProperty("UseBootScene");
bootPath = serializedObject.FindProperty("_BootScenePath");
targetBootScene = serializedObject.FindProperty("_TargetBootScene");
collectionPath = serializedObject.FindProperty("_SceneCollectionPath");
}
// ..... the rest of the editor script
}
from what i can tell its exactly what you were trying to do
Yeah, but missing one thing. Make a serialize int now on that exact script and expose it as a serializedproperty
oh isee
Not on your MultiSceneToolsConfig though
i missed that part, the int is local to the editor script
Yeah, so that's the complexity lol
I think it makes sense for my tool since my Tile3DMap I am making doesn't need to have a brush size variable. Only the editor script should care about it.
Yeah I could lol. I just assume you would do it this way, but apparently it doesn't seem the solution
Like, my TileMap only have matrix data that it should know about.
eh, unsure
From my understanding, serialize properties are pretty good for these type of tools and should use them when you can
you might be able to but doing manual undo's arent exactly reccomended
exactly
isee, well then i also learnt something. i will make sure to remember this
yeah definitely cause I've searched all over haha
Anyone know how I can properly await an async task inside of a scripted importer without getting the editor to infinitely hang?
/// <inheritdoc />
public override void OnImportAsset(AssetImportContext ctx)
{
using ThemeLoader loader = ThemeLoader.FromFile(ctx.assetPath);
Texture2D? previewImage = loader.ExtractPreviewImage().GetAwaiter().GetResult();
var resourceStorage = new UnityAssetsResourceStorage(ctx, previewImage);
OperatingSystemTheme theme = loader.LoadTheme(resourceStorage).GetAwaiter().GetResult();
ctx.SetMainObject(theme);
}
This is what I have right now. It hangs when loading the theme preview texture from the theme file
I've also tried
/// <inheritdoc />
public override async void OnImportAsset(AssetImportContext ctx)
{
using ThemeLoader loader = ThemeLoader.FromFile(ctx.assetPath);
Texture2D? previewImage = await loader.ExtractPreviewImage();
var resourceStorage = new UnityAssetsResourceStorage(ctx, previewImage);
OperatingSystemTheme theme = await loader.LoadTheme(resourceStorage);
ctx.SetMainObject(theme);
}
This doesn't hang but the asset doesn't properly import. Almost like Unity isn't waiting for the method to complete (why would it)
But I need the theme loader code to be async because it's a lot of IO, and themes can be loaded at runtime. I don't want the game hanging while a theme loads
can someone explain to what's wrong with this code?
foreach (var item in m_itemList)
{
using (new GUILayout.VerticalScope(s.listItem))
{
var key = item.key;
var selected = m_selected.Contains(key);
if (item.OnGUI(selected))
{
if (!selected)
m_selected.Add(key);
}
else if (selected)
m_selected.Remove(key);
}
}
this works fine when docked on right side but when docked on left side or not docked I get error message in log saying that I have to call beinglayoutgroup before calling endlayoutgroup, this happens after I click a specific button on list items, all that button does is open video or audio file in default external app - inside list items layout is only used to create rect for list item itself, the rest is done without any layout calls
I checked code of endlayoutgroup and this is what I see inside, I checked that Event.current isn't null before dispose and I also checked all references to this method and there is not a single place in project where it should be called outside of dispose from using statement
this is code of the button that causes issue
if (button.Button(controlRect, m_style))
{
var assetFile = new FileInfo(Path.Combine(basePath, path));
if (assetFile.Exists)
EditorUtility.OpenWithDefaultApp(assetFile.FullName);
else
Debug.LogWarning($"Asset '{asset.name}' does not exist at path '{assetFile.FullPath}'");
}
public bool Button(Rect buttonRect, GUIStyle style) =>
GUI.Button(buttonRect, m_content, style);
also it only happens on 2nd click and after, first click on the button works without error in log
and also if I move it to right dock and then move back to left it also resets this so that only 2nd click after that causes issue
So I am using a custom editor for a file I have and an error occurs when I try to load the scene with that editor.
I think that the problem is that the "target" variable in OnEnable is probably referencing the component in the editor, rather than the one being created when the scene loads dynamically.
If anyone knows how to fix this problem, or thinks that I might have other problem, I'll be happy to know! :D
Without an actual error, and without seeing the code, no one is going to be able to help much since there isn't enough info to go on.
the problem was somehow caused by EditorUtility.OpenWithDefaultApp(assetFile.FullName); which has nothing to do with IMGUI layouts at all
I queued it to execute on next editor update instead and it works without errors
how spaghetti does unity internal code have to be for EditorUtility.OpenWithDefaultApp breaking layout groups is beyond me
IIRC there's a good reason for it but I forgot why
Anyways you can also call exitgui after your OpenWithDefaultApp
don't think there should be a good readon why calling random unrelated function should break GUI code but it's unity; they managed to make ColorUtility.TryParseHtmlString (which a pure function at least in what it should do) non-thread safe, can expect anything from special folks like that
How to retain data inside elements of a Serialized List when Undoing and Redoing? I've tried [SerializedField] and [SerializeReference] but they don't work, with the latter only making my value null
the list has the [SerializeReference] attribute and I'm using Undo.RecordObject(this, "...") right before modifying it
And are you using SerializedObject and SerializedProperty to make the modification and/or to apply it?
Not after the Undo.RecordObject but I do inside the list object
I forgot to add that my problem is with undoing object insertion into the list and then redoing that
You shouldn't need to use Undo if you make the modification through SerializedProperty, such as:
SerializedProperty.InsertArrayElementAtIndex
I use Undo before modifying the list inside class A, then modify data inside the list's element of class B
Undo.RecordObject(this, "...") where this is class A
I currently am trying to make an editor window which loads all scriptableobjects(i already did this) and then upon clicking one loads their properties(also done) and creates fields to edit those properties accordingly. This last point I am struggling with since I don't know the exact types of the properties nor the amount of properties, so I thought hey I can just make a List<T> which stores all those values but obviously thats not how that works.
I know there are probably multiple assets out the that already do this, I just have a thing for wanting to do things myself.
this is a rough example of what it should look like, select scriptableobject on the left, and then be able to edit its properties on the right.
I am using the following to help me align my edge colliders, however the moment I look away from my prefab and look back, the changes that script made are gone. How do I get it to save?
EDIT: Solved. I used Undo.RecordObjects and recorded the colliders list with it
[ExecuteInEditMode]
public class CollisionBuilderHelper : MonoBehaviour
{
}
[CustomEditor(typeof(CollisionBuilderHelper))]
public class CollisionBuilderHelperInspector : Editor
{
public override void OnInspectorGUI()
{
DrawDefaultInspector();
if (GUILayout.Button("Setup"))
{
CollisionBuilderHelper helper = (CollisionBuilderHelper)target;
var colliders = helper.transform.GetComponents<EdgeCollider2D>();
foreach (var collider in colliders)
{
collider.edgeRadius = 0.01f;
List<Vector2> points = new List<Vector2>();
var numOfPoints = collider.GetPoints(points);
for (int i = 0; i < numOfPoints; i++)
{
var point = points[i];
point.x = (float)Math.Round(point.x);
point.y = (float)Math.Round(point.y);
points[i] = point;
}
collider.SetPoints(points);
}
}
}
}
@visual stag hope you don't mind the ping, been using your shape drawing tool with great success 😄
Was just curious, I wasn't able to find a way to draw filled in shapes rather than wirecubes. Was this a implemented feature I missed or just not something thats in the tool
Nope, wireframe-only, as I said at the start 😛
Ah sorry, Must have missed it. Far from a dealbreaker 😄
the real dealbreaker is D.raw constantly reminding me of one piece haha
Define the base class then interface up so you can split them up into categories you can work on conveniently.
Can you give a small example? I know how interfaces work, I just dont see how theyd be useful here.
is there a nice way to store editor only data on objects in scenes?
I'm working on a mesh creation/editing tool, and I want my custom editor-only data structure MeshData to be stored in the scene (but not included in builds)
and it would be really nice if I could have this MeshData in the editor assembly
for, many reasons
God I wish. I'm glad that's a fundamental part of Entities, because it's always been real bad in traditional authoring
If you start using preprocessor arguments with serialized data you have a bad time. So the best I've found is storing in the asset database and finding that asset loosely with a guid
hmmmmmm I guess 
feels a little spooky to have a separation between objects in the scene and the MeshData though
like if I delete an object referencing that mesh data it should technically also delete the mesh data asset, but only if it's a unique mesh associated with the scene rather than saved as an asset (from a user perspective)
and then I have to deal with like, what if a user deletes a scene and then I have assets lying around, that used to be in that scene, so they need to remember which scene they were in and get deleted, maybe?
hm hmh hm
The only other alternatives I've found are making some build thing that strips the data, but the moment someone has a custom build setup those break. We suffer because Unity never made the build process consistently extensible
I haven't tried it, but I assume hideFlags does nothing on components?
it does, but you still can't make editor assembly components, as far as I know
or components referencing editor only types
Wait does this work then? https://docs.unity3d.com/ScriptReference/HideFlags.DontSaveInBuild.html
oh, uh, not sure! I just know that you can hide components using hide flags
Oh 2022.3/2021.3+
No wonder I wasn't aware of it, but this is a goldmine of a flag haha
it's been around since forever iirc!
Where do you see that? I see it stretch back to 5.2, but maybe its behavior has changed since then
https://docs.unity3d.com/520/Documentation/ScriptReference/HideFlags.DontSaveInBuild.html
The mobile docs are lying to me then
😔
I'll be interested in how far you get with it in terms of an editor-only component that is also preprocessored away
I don't think you can add editor only components to objects
I'm pretty sure that's where you'd be stopped
Yeah, looks like this can't be worked around. Not even debug inspector mode could help :(
But what about a runtime component with a bunch of preprocessor ifs, like vertx is suggesting? It's not pretty, but with the hideFlag, you should be able to avoid any serialization bugs.
And you can make it internal to hide it from those referencing the runtime assembly.
Or just wrap the whole class declaration in , never mind, that wouldn't hide it from users using the library in the editor.#if UNITY_EDITOR 🤔
that still doesn't let it access the editor assembly
Oh right, I was thinking of UnityEditor.dll.
I wonder, does SerializeReference let you serialize types in editor assemblies from a runtime component? 🤔
If so, you could be serializing an empty base class or interface defined in the runtime assembly, and referencing the implementation from the editor assembly.
I'm assuming MeshData is a serialized class, but if it's a Unity Object, then that should be even easier, I think.
I would expect that to go poorly
Only one way to find out.
Sadly build-time serialization issues can be some of the more subtle things, I'd be very thorough with checking it
True, I don't know if HideFlags will be processed before the serializer gets its hands on it. But I feel like that must be the case.
From a quick test, Unity's serializer doesn't seem to have any problem with serializing a reference to an editor type in a runtime component. At least, not in the editor.
That is how you do it in Entities (authoring and baking in an assembly like that), so if you can combine that with the hide flag, and not make direct references to the component, and request nobody treats it as runtime, it will probably work
oh, hm, wait, I've only been using the default assembly and editor folders so far
so it's possible with asmdefs?
It's a bit of a hack, because it's technically not an editor assembly, "Any Platform" is checked and nothing is excluded. But with the UNITY_EDITOR define constraint, it won't be compiled unless the UNITY_EDITOR define symbol is present.
So it appears to be a runtime assembly in the editor, but is then ignored when building.
I haven't used this hack before, so maybe there are some consequences that I don't know about.
I am getting an ArgumentNullException for just checking if a SerializedObject.context is null
What's more, if I have that check somewhere in my code, checking if just the SerializedObject is null also throws this error and doesn't if I don't check the context:
//currentEnemyEditor.serialData.context is null//
if (currentEnemyEditor.serialData == null) //This throws an ArgumentNullException IF the next if exists
currentEnemyEditor.InitEditor(selectedEnemy, enemies.GetArrayElementAtIndex(i), data, serialData);
if (currentEnemyEditor.serialData.context == null) //This throws an ArgumentNullException always
currentEnemyEditor.PrepareFoldout();
wait, isn't what you mean is basically tagging a gameobject as EditorOnly ?
ah I see what you mean
iirc we have the same scenario for our internal tool here, we used https://docs.unity3d.com/ScriptReference/Callbacks.PostProcessSceneAttribute.html to deal with the components
oh, I meant, as in, components that are in an editor folder, and are in the editor assembly
not runtime components (that are only used in editor) that you want to remove on build
How would I start to add a checkbox or dropdown menu to the Build window?
Working on some more serialization of my data in my editor scripts, but can I get some clarification for what methods will be only called once when I create them? I would assume Awake() and such would only be called on creation, but maybe I'm going crazy but it seems to be called when I restart the editor. Also, I am wondering about the [ExecuteInEditMode] and what scripts out of both, the tool script and the editor script, should possess that attribute.
Should I be even instantiating my containers in these methods, or should they just be instantiated when I declare them?
Relating to Freya's problem, Idk if the way ive been doing things are a good solution but ive been defining structs in between #if UNITY_EDITOR. Although this has been on SO's and not in scene objects and it does get messy which is why im assuming its probably not the best way of doing things
Basically this i guess
Oh, perhaps the idea is to use a boolean to check initialization, eh?
newTile = tileSO.Construct(pivot, tileMap3D, index);
int arrayIndex = serializedTiles.arraySize;
serializedTiles.InsertArrayElementAtIndex(arrayIndex);
SerializedProperty element = serializedTiles.GetArrayElementAtIndex(arrayIndex);
element.objectReferenceValue = newTile;
serializedObject.ApplyModifiedProperties();```
Unity yells at me for using ApplyModifiedProperties() in OnSceneGUI here and it seems that me calling it in OnInspectorGUI with my other properties does not seem to update it. Will using ``EditorUtility.SetDirty(target);`` suffice, or should I be using some other method?
I'm also having a hard time understanding how to undo prefab creation. I am creating a fresh new GO from a prefab and inserting it into a serializeproperty list, yet that apparently isn't good enough for unity to undo these prefabs. Am I supposed to make some like some serializeproperties objects and insert them into this list? I think I've seen that, but how do I go about calling my assign function on that serializeproperty/object prefab then?
Forget serialize properties for this, don't really need the gui functionality. Undo.RegisterCreatedObjectUndo seems to work for what I need, but instead of destroying the gameobject instance, it just deactivates them. Actually was destroying the component and not the GO :))))
stuffs complicated. I'm already dreading to make some undo/redo manager
Undo.RegisterCreatedObjectUndo seems pretty neat though. Documentation is bare as fug, but it seems to record a bunch of actions if it detects consistent input.
May just record until the current editor event is consumed or something like that.
If anyone can give me an idea how I could type check against the history of objects undone/redone I'd appreciate it. Using OnDestroy() seems like a valid method to unbind a bunch of references, but I prefer some manager to handle it all.
for asset database when do we use SaveAssets() and Rrefresh()
they seem kinda the same
Think have SaveAssets as a 'export', it writes data from UnityEngine.Objects to the files on disk. And Refresh can be thought of as 'import' where it reads all the files in the Assets folder and make sures all of the UnityEngine.Objects are up to date, and imports and newly added files.
A SerializedProperty refuses to change its value to a previous one during an Undo action. I've confirmed with the debugger that the value is different in a previous action but the SProperty stays at the current value when Undoing. What can be interfering with this?
Ah, it was the ApplyModifiedPropertiesWithoutUndo, which I needed for a different thing
ah i see that makes sense
Does anyone know a good way to differentiate between two Project Browser tabs that will survive an editor restart? It looks like .GetHashCode() changes with each restart, and even the index order of the ProjectBrowser objects changes.
I know there has to be some way it is handled internally since each can have a different focused directory which is saved between sessions.
I say "two" but really I mean "an arbitrary amount greater than one"
Also related to that, but I assume it's okay to ask about the open source "Reference" editor code? That's what I am currently looking at to try and track this stuff down.
I have a custom inspector script that modifies all classes that extend MonoBehavior, or that's at least what it was supposed to do.
I tried this [CustomEditor(typeof(MonoBehavior))] for no avail, as typeof is specific to the exact type. Is there a way to make it apply to all subclasses of MonoBehavior?
It’s super hacky, but in a lot of similar cases I just base whatever off of the Object class and type-check in whatever function from there. Usually you can get away with casting, but not in attributes.
This is also gonna be really slow, but I’ve hit my head against similar and run into the same issue
Could maybe get away with some reflection sorcery but the root problem is that attributes need a solid type
I'll try target.GetType() and see how it turns out.
Problem is that it doesn't even execute when typeof(MonoBehavior). Tried putting a couple of debug logs here and there in OnEnable, also for no avail.
That's indeed the point. When I tried the script on a specific type, it worked flawlessly.
I'll have to do a little more research about CustomEditor attribute. It's bugging me so hard, lolol.
Tried digging into the MetaData of the class.
Haven't found that...
I'll double check.
Would be very embarrassed if that was the fix, lol.
If you’re planning on programming beyond today, get used to it :)
Indeed. Needs to be the default feeling. 😔
Here it comes
It worked. Thanks for the help!
Frick ChatGPT for that, lol.
Oof, yeah. It can do some cool things and I'd be lying if I said I didn't use it, but you gotta keep a close eye on it
It is oddly enough really good at reflection stuff.
All the repos out there are doing a good job aiding it. 😂
People love to customize their systems too, as far as I can tell. I can say so about myself, at least.
Yeah they should really have a channel for editor extensions or something
any one know how to get this to work:
var asset = CreateInstance<TestAssetSO>();
AssetDatabase.CreateAsset(mesh, _assetPath + name + ".asset");
AssetDatabase.AddObjectToAsset(mesh, asset);
AssetDatabase.SaveAssets();
I get this error: AddAssetToSameFile failed because the other asset is not persistent
how do you make it persistent
You probably have to save before adding it to another asset
Try waiting a frame or maybe calling refresh
Which one of the 2? 😛
waiting a frame
If you want to do it in one frame you may be able to call AssetDatabase.ImportAsset on it
Refresh would sometimes work unreliably if the file is decently huge
Surely it would be consistent if you used ForceSynchronousImport
I honestly did not know this api exists 🥹
They can because editor windows are serialized to file on editor close. Only thing I am thinking of is to save their GUIView path, but that will require a lot of reflection
Could get the hashcode of the pos, store it on close and read it on open?
I'm having a bit of a weird issue. When I run this code, the resulting TextArea is just black. No text in it.
private void OnGUI()
{
lineTex = new Texture2D(1, 1);
leftPanelRect = new Rect(new(0, 0), new(leftPanelHorizontalSpace, position.size.y));
consoleWindowRect = new Rect(new(leftPanelHorizontalSpace + 2f, 0), new(position.size.x, position.size.y));
GUI.color = grey;
GUI.DrawTexture(leftPanelRect, lineTex);
GUI.color = darkGrey;
GUI.DrawTexture(consoleWindowRect, lineTex);
StringBuilder sb = new();
foreach (string line in consoleText)
{
sb.Append(line).Append("\n");
}
GUI.backgroundColor = Color.white;
GUI.TextArea(consoleWindowRect, sb.ToString(), GUI.skin.textArea);
}
Can you eliminate some things like the draw textures to see if that changes?
The only thing that removes the black area is commenting out this line GUI.TextArea(consoleWindowRect, sb.ToString(), GUI.skin.textArea);
What if you pass no guistyle?
Same thing. Just a black box.
I just want a window where I can drop text like a console window.
But you can't interact with it other than copy the text
If this is an editor window you should be using EditorGUI.TextArea (or preferably, even UI Toolkit)
I'm using Unity 2021.3. How is UI Toolkit support there?
It'll be several lines of text
UI Toolkit is totally fine for the editor in many older versions afaik
I see.
I just remember trying it and not liking it due to a lot of feature incompleteness and instability so I didn't really return.
I don't have to make that many editor tools
I switched to EditorGUI and it's the same thing. Just a black box.
kinda seems like you might have borked the textbox style or something, perhaps try restarting Unity
Alright
Yeah seems like it
It is perplexing because I swear I've done this before with it just working
Restarted the editor, still just a black box
In reality I am not precious about implementation here. I just need to be able to feed lines of text to a window a la a console window to monitor network traffic and it should preferably be able to go on forever using a scrollview of some kind
The idea was just to get text on screen first
I set the Height of an element to 100%
It now extends beyond the confines of its own window into infinity.
Be ready for the jump-scares once you update to 2022.3.x. Lots of deprecated apis there 👀
I'm not afraid of red underlines 😄
Despite setting the horizontal bar to never always visible, it is:
scrollViewPosition = EditorGUILayout.BeginScrollView(scrollViewPosition, alwaysShowHorizontal: false, alwaysShowVertical: true);
I don't quite understand how I am to control the size of the scrollview with EditorGUILayout
It seems to not have any limits, just a position for where the scrollbar is
that isn't hiding it, you cannot hide it
So it's impossible to hide it?
It's what it says, the ability to always show it, regardless of whether there's a need
I see.
If I wanted just a vertical scrollbar, how would I approach it?
Should I make a vertical group first?
Don't overflow horizontally and then it'll not show the horizontal bar
I don't understand how to control the size of the scroll view
It seems to just take up the entire container
you pass GUILayout.Height as a GUILayoutOption param
Alright. Thanks.
I'm almost at the finish line I think. Now the vertical scroll doesn't show at all.
private void OnGUI()
{
lineTex = new Texture2D(1, 1);
leftPanelRect = new Rect(new(0, 0), new(leftPanelHorizontalSpace, position.size.y));
consoleWindowRect = new Rect(new(leftPanelHorizontalSpace + 2f, 0), new(position.size.x, position.size.y - 2f));
GUI.color = grey;
GUI.DrawTexture(leftPanelRect, lineTex);
GUI.color = darkGrey;
GUI.DrawTexture(consoleWindowRect, lineTex);
GUI.color = Color.white;
int counter = 0;
scrollViewPosition = EditorGUILayout.BeginScrollView(scrollViewPosition, GUILayout.Width(consoleWindowRect.xMax));
foreach (string line in consoleText)
{
Vector2 position = new(leftPanelHorizontalSpace + consoleFontSize, consoleWindowRect.yMin + (consoleFontSize * counter));
EditorGUI.LabelField(new(position, new(line.Count() * 8f, consoleFontSize)), line);
counter += 1;
}
EditorGUILayout.EndScrollView();
}
Neither does the Horizontal
But I do want the vertical
And I do have content that overflows
You have to use Layout inside of a EditorGUILayout.BeginScrollView
otherwise you're just drawing at the position and ignoring the view
I haven't used IMGUI beyond very small things for many years, so it's hard to remember and help 😛
Oh I’m already waist-deep into reflection at this point, so that doesn’t bother me. Just a matter of finding the right stuff. I don’t have my notes in front of me but there was a something something ViewData property and associated methods that was used in the serialization, but nothing that uniquely identifies one.
Navi actually had a decent idea to use the rect of the window instead. Much easier
Wouldn’t that change if the window is resized or the tab moved?
You save it as the key/id of the window when the editor closes and when you open Unity again you use that to find which window is which
So you mean like the literal, serialized Rect() and not just its GetHashCode() value or something?
No you can do the hashcode of it
I’ll try that, but in my testing at least with the ProjectBrowser itself that would regenerate on each new session. Could be that the Rect is more stable though, so I’ll let you know. Thanks for the idea!
I mean the window.position property. That is serialized. If it wasn't then every time you recompiled scripts or reopened Unity all the windows would be positioned at 0,0 🙂
Oh, yeah I had considered that. Position and size. That is probably as close as I’m going to get, but it also would get messed up anytime it is moved or resized. So if you need to make your Inspector or hierarchy a little wider and that bumps your project browser, that data is gone.
But you only need it when you close Unity though, right?
No, I need it during as well
Right, but you can just keep a actual reference to the window during.
And or, use the instance ID
Those change whenever you do a domain reload. I also tried using the index inside of a function that returns all project browsers as opposed to the one with the last focus, and even those change every reload. They are truly regenerated each time, but somehow Unity is able to restore the folder that each of them has open, and I just haven’t gotten that far into it yet.
It serializes them to disk iirc
Erh, or it is C++ fun...
I think it is the latter...
That was my understanding because each ProjectBrowser is an EditorWindow, and each EditorWindow is a ScriptsbleObject, which is an Object, which means it’s all serializable.
But I was really hoping not to need to go that route
Can you maybe give a bit more context to what you are doing/wanting to do?
To the point where I’m considering just doing an initial release with the caveat “Only works with a single Project Browser”.
I need to track actions in each project browser and maintain a history, all of which needs to survive domain reloads and application restarts. It works perfectly with just one.
I see, how are you saving between sessions currently?
That was the easiest part: a very hacky but functional serialization saved to editor prefs.
Oh odd. Btw EditorPrefs is system wide if ya didn't already know. So I don't know if I would recommend doing it that way
Just using a ScriptableSingleton would be what I recommend to do.
I got a “unique enough” prefix from the project name and just append that to the keys.
But yeah I learned that the hard way the first time I tried to test this in a clean project, lol
ScriptableSingleton is just better. No need to do any hacky stuff, no need for custom serialization. Can save to project settings, per-project user settings, or system wide preferences
Was not aware of those 60 seconds ago, just looked up the documentation and yeah that looks a lot better. Should be trivial to swap that out since I kept everything pretty separated. Appreciate that tip.
yeah ScriptableSingleton is the way to go, and having physical file of it is just much better
First time making any sort of non-trivial addon, so a lot of this is trial and error 🙃
Oh cool! 😄
Wish I knew SS years ago, sad just found out about it last year and from this channel too 🤪
Well, they were only added in 2020.2 😛
So, like early 2021
oh I see, thought it's been in unity for long, apparently not.
Btw you're the one who told me about SS too long while ago 😂 so thanks for that
Oh haha, no problem 😄
[CustomEditor(typeof(SceneSaver))]
public class SaveSceneObjects : Editor
{
private bool fileExists = false;
async void CheckExists(string cloudStoragePath)
{
SceneSaver sceneSaver = (SceneSaver)target;
// Check if the file exists in Firebase Storage
StorageReference storageReference = FirebaseStorage.DefaultInstance.GetReference("/levels/"+cloudStoragePath+".json");
try
{
StorageMetadata storageMetadata = await storageReference.GetMetadataAsync();
EditorGUILayout.LabelField("File already exists. Please try with another name.");
}
catch
{
if (GUILayout.Button("Save Scene"))
{
sceneSaver.SaveSceneObjectsToJson();
}
}
}
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
SceneSaver sceneSaver = (SceneSaver)target;
if(GUILayout.Button("Initialize"))
{
FirebaseServer.InitializeFirebase();
}
if (FirebaseServer.isFirebaseInitialized)
{
if (GUILayout.Button("Publish All"))
{
sceneSaver.MakeAllPublic();
}
CheckExists(sceneSaver.saveFileName);
// Additional GUI elements here
}
else
{
EditorGUILayout.HelpBox("Firebase is not properly initialized. Please run your application in Play Mode to use Firebase features.", MessageType.Warning);
}
}
}
So i've got this code to check if object exists in firebase, but i get error ArgumentException: You can only call GUI functions from inside OnGUI. from it. What can be cause of it?
my guess would be GUILayout.Button and EditorGUILayout.LabelField in CheckExists since it is async it is calling it... differently as it is awaiting
Is there a way to make custom attributes specific to primitive types or structs?
If I have multiple serialObject.ApplyModifiedProperties() in OnInspectorGUI(), do they create one Undo/Redo entry?
If there are no changes, I believe so, but I'm not sure
and if there are changes?
Each change will be its own item in the history if you're applying them separately.
You can restrict where attributes can be placed with the AttributeUsage attribute.
[AttributeUsage(AttributeTargets.Struct)]
Yep. That can help with enums, and I think I will have to get a little lower if I want to customize the other types, if at all possible.
In the scene view, anyone know how to do custom selection/object picking, while still having Handles work?
Whats sad is that in c# 11 we can do generic attributes 😭
Is there a built in way to grab a targets Awake and OnEnable via a CustomEditor?
I wanna do stuff on a monobehaviour in editor but want to keep the code seperate from the non editor stuff yknow
ideally didn't want to have two different scripts on the component
like ideally im looking for a way to be like
class MyClass
Awake
Start
Update
etc.
[ExecuteInEditMode]
class MyClass
Awake
Start
Update
etc.
Basic question: I made a bunch of monobehavior who generate various assets via AssetDatabase function.
Everything work fine until I try to build the project, in which I need to move those scripts into an "Editor" folder.
Except now the corresponding component show the "Associated Script can't be loaded" error message in the scene that use them.
I'm guessing there is a cleaner way than just moving those script in and out of an "Editor" folder?
Does setting a serialProperty.managedReferenceValue update its relative properties or not?
Oh wow, thanks for the tip. Just cut like 100 lines out and removed a lot of hairy logic.
Can I not use Input.GetKey in a scriptablesingleton like this? not getting any result
public void OnEnable()
{
EditorApplication.update += Update;
Selection.selectionChanged += OnSelectionChanged;
}
public void Update()
{
if (Input.GetKeyDown(KeyCode.U))
{
Debug.Log(currentlySelectedTiles.Count);
foreach (Tile tile in currentlySelectedTiles)
{
ToggleTilePrefabUp(tile);
}
}
}
oh-
Any suggestions for how to get input on this?
yea so yall can test urselves how can I just go up to Component but Object suddenly breaks editor script https://hatebin.com/efptrbckfz
label shows up with first part and wont show up with second. On script inheriting from monobehaviour
ScriptableObjects don't have an Update function, so no.
Perhaps you wanted to use a ShortcutAttribute or something similar
Bet, I'll look into that. Thank you!
Also, if you have a moment, Do you know if anything like this exists?
I have no idea what that means. You can apply ExecuteInEditMode on a MonoBehaviour, and if it's in the scene it'll receive the events. If you do it on any other script it will do nothing
Sorry, Basically I have some important classes related to my game but for easy level design iteration and such theres a lot of editor stuff i want to run on them too. I can and do achieve this by just chucking [ExecuteAlways] on them but it feels kinda yucky? ideally i'd love to have a way to have it in two different scripts but still grabbing the same functions. kinda like how CustomEditor's do editor stuff ontop of pre-existing stuff but abstracted
Usually you would not want to run an update function in the editor, and most things are done via interactions built on top of things like the EditorTool api
Fair ok. I can re-structure my stuff to be fully event pilled in that case. Would you say that what I'm looking for probably just doesn't exist to enforce those kind of standards?
There is no such thing
What's the best way to sort a SerializedProperty array of which elements have relative properties?
I tried casting to the proper array from managedReferenceValue, doing Array.Sort and putting it back but it seems that the relative properties do not change place
What dos "array of which elements have relative properties?" mean?
public class Enemy
{
public int a;
public float b;
public Vector2 c;
}
public class Enemies
{
public List<Enemy> EnemyList;
serialEnemies = new SerializedObject(new Enemies());
serialEnemyList = serialEnemies.FindProperty("EnemyList); //the list
serialEnemy = serialEnemyList.GetArrayElementAtIndex(0); //one element of that list
serA = serialEnemy.FindPropertyRelative("a");
serB = serialEnemy.FindPropertyRelative("b");
serC = serialEnemy.FindPropertyRelative("c"); //the relative properties
SerializedObject of a class that has a list of another class which has some properties
SerializedProperty of that list
How do I sort the SerializedProperty
Ahh, it is discsused here and gives a high level overview of waht is required https://forum.unity.com/threads/sorting-an-array-within-a-serializedproperty.366273/
Man, having to make a whole sorting script for this makes SerializedProperties look bad
before this I used to cast the list out of SerialisedProperty and sort that but it worked because the list elements were ScriptableObjects
Also instead of this it would be great to be able to get-set a SerializedProperty and its children together
currently you can only get a copy of a SerializedProperty
What's the usual method to handle reference bindings when it comes to redo operations? For example, I have a container that holds many gameobject references, and so when I destroy/undo these gameobjects I simply remove them from the container. Now, redo seems quite more complicated since I need to grab these previous references that were removed. It would be easier if I wasn't letting Unity handle the undo operations because then I can manage a queue of objects, but since tracking the redo/undo history is such a pain, the only way I can think of solving this problem is to simply add a list of bi-directional references on the redo object itself.
I think a Undo.RecordObject on the obj that has the reference list, along with Undo.RegisterCreatedObjectUndo/Undo.DestroyObjectImmediate should work?
How are you doing it currently?
I've the reference to the object with the container and it seems to keep the reference when it's destroyed (I guess until it exceeds the undo/redo history), so when I redo it, it just adds itself back.
So, both the child and parent have references to each other
I think the part of the problem is that the container is a dictionary, so perhaps my problem stems from serialization and how undo/redo work?
Ah well that would make sense to me
you can capture back those undod objects via ObjectChangedKind https://docs.unity3d.com/ScriptReference/ObjectChangeKind.html
Have an editor tool that replaces a prefab with a different one, On triggering the undo I'm getting a Restored Transform child parent pointer from NULL error, still seemingly undos correctly though
newTileObject = (GameObject)PrefabUtility.InstantiatePrefab(ScriptableManagerSettings.tilePrefabs[index]);
Undo.RegisterCreatedObjectUndo(newTileObject, "Created New Tile");
newTileObject.transform.parent = tile.transform.parent;
newTileObject.transform.position = tile.transform.position;
newTileObject.transform.rotation = tile.transform.rotation;
Undo.DestroyObjectImmediate(tile.gameObject);
first time using Undo so could be missing something simple
Sounds like a bug in your unity version
if found its so annoying, when we open editor window when its something error on Create GUI, then window not show.....okay this part is fine, but even after i did something to code that get error, calling window.show didnt open the window....its open, but didnt show up, that's why i doing like this
[MenuItem("Project Agni/Test Window")]
public static void Open()
{
if (EditorWindow.HasOpenInstances<TestEditorWindow>())
{
var window = GetWindow<TestEditorWindow>();
window.Close();
Debug.Log("Window Has Been Close, Please Reopen");
}
else
{
var window = GetWindow<TestEditorWindow>();
window.Show();
}
}
unrelated, but why you close the Window but then ask the user to reopen?
or that just a dummy debugLog?
Yeah just wait a frame and open it again
Is there a clever way to exclude specific gameObjects from builds?
what is the attribute to use to add a method to the right click menu in the hierarchy? im only finding other attribute stuff when googling
nvm i found it
It's [ContextMenu("My Method")] (in case someone else sees this)
i came across this which i wanted to use on a object im creating from a menu item but im getting this error and i dont know if its something i can make work in that case.
InvalidOperationException: Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true.
System.Reflection.RuntimeMethodInfo.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) (at <75633565436c42f0a6426b33f0132ade>:0)
System.Reflection.MethodBase.Invoke (System.Object obj, System.Object[] parameters) (at <75633565436c42f0a6426b33f0132ade>:0)
IconManager.GetTextures (System.String baseName, System.String postFix, System.Int32 startIndex, System.Int32 count) (at Assets/_Scripts/IconManager.cs:72)
IconManager.SetIcon (UnityEngine.GameObject gObj, IconManager+LabelIcon icon) (at Assets/_Scripts/IconManager.cs:45)
ops forgot the link hold on: https://discussions.unity.com/t/scene-color-object-marking/82562/3
this got to be the hackiest piece of code I've ever written, is there a better way to do this?
using (var scope = new EditorGUI.ChangeCheckScope())
{
var id = s_searchField.searchFieldControlID;
if (s_setSearchFilter != null)
searchFilter.value = s_setSearchFilter;
var filter = s_searchField.OnGUI(EditorGUILayout.GetControlRect(), searchFilter, s.searchField, GUIStyle.none, GUIStyle.none);
if (s_setSearchFilter != null)
{
if (recycleTextEditor.controlID == id)
{
recycleTextEditor.text = s_setSearchFilter;
recycleTextEditor.SelectTextEnd();
if (GUIUtility.keyboardControl != id)
GUIUtility.keyboardControl = id;
}
else
{
s_searchField.SetFocus();
s_setSearchFilterWait = true;
}
s_setSearchFilter = null;
GUI.changed = true;
}
if (s_setSearchFilterWait && recycleTextEditor.controlID == id)
{
recycleTextEditor.SelectTextEnd();
s_setSearchFilterWait = false;
}
if (scope.changed)
{
searchFilter.value = filter;
FilterObjects(filter);
}
}
I just wanted to set search field text, set focus on it and set cursor to the end of it
not only I had to get to cursor through reflection by getting RecycleTextEditor instance, I also have to set it after waiting otherwise it just overwrites cursor I set
VisualElement root = new();
ToolbarSearchField s = new();
root.Add(s);
root.Add(new Button(() =>
{
var textField = s.Q<TextField>();
s.Focus();
EditorApplication.delayCall += () =>
{
textField.textSelection.cursorIndex = textField.text.Length;
textField.textSelection.selectIndex = textField.text.Length;
};
})
{
text = "Focus and set cursor"
});
return root;
This is what it looks like in UI Toolkit (way easier); you may be able to do it without the delay call, but it works fine like this
Just... don't use IMGUI is my advice 🙂
It's so nice for some things though
Then nest them in UITK and cry that you had to do it
2019 uitk sucks
I'm only using it for general layout
and even then it's super buggy
Ah yeah, 2019 is dead to me 😛
anyway my solution works, it's just terrible code
We just supported 2020 support, would really consider updating if you're still on 2019
I will update eventually, just want to update a lot of other stuff along with it
I wonder what it's like updating uitk from 2019 to 2022 😄
I'm trying to get a Scrollview to work correctly. The code below;
private void OnGUI()
{
lineTex = new Texture2D(1, 1);
leftPanelRect = new Rect(new(0, 0), new(leftPanelHorizontalSpace, position.size.y));
consoleWindowRect = new Rect(new(leftPanelHorizontalSpace + 2f, 0), new(position.size.x, position.size.y - 2f));
GUI.color = grey;
GUI.DrawTexture(leftPanelRect, lineTex);
GUI.color = darkGrey;
GUI.DrawTexture(consoleWindowRect, lineTex);
GUI.color = Color.white;
int counter = 0;
scrollViewPosition = EditorGUILayout.BeginScrollView(scrollViewPosition, GUILayout.Width(consoleWindowRect.xMax), GUILayout.Height(consoleText.Count() * consoleFontSize));
foreach (string line in consoleText)
{
Vector2 position = new(leftPanelHorizontalSpace + consoleFontSize, consoleWindowRect.yMin + (consoleFontSize * counter));
EditorGUI.LabelField(new(position, new(line.Count() * 8f, consoleFontSize)), line);
counter += 1;
}
EditorGUILayout.EndScrollView();
}
Produces a panel full of labels, but no scrollbars.
I’m on mobile so it’s a bit hard to grok, but the first thing I’m noticing is that you are drawing the label with EditorGUI.LabelField and calculating its position yourself. Scroll views don’t know the size of their content unless you use GUILayout/EditorGUILayout functions
I always find Editor classes super confusing like that
So what should I do instead?
Something like EditorGUILayout.LabelField. If it doesn’t exist there, try GUILayout.LabelFiekd.
Also you’re allocating a new Texture2D every GUI update. I’d cache it, or just use EditorGUIUtility.whiteTexture
I almost always use the Layout versions of the gui functions so that everything is spaced automatically. Much easier to be consistent that way, and then only occasionally you need to position elements manually
Hello guys can I block the array copy of an object when clicking on the plus button ? Because I’m using a serialized reference, when I add an item the reference is also copied, so I need to manually reset this reference
Is this for adding an an array/list element in the inspector?
Yes
