#↕️┃editor-extensions
1 messages · Page 101 of 1
You can, substance designer does it.
does it import Texture2D assets with multiple texture sub-assets?
or are they materials?
I've never used Substance
No it is a custom asset type and it has the textures and materials as sub assets
ah right
you can do that with custom asset types
but not with the built-in asset types
The custom asset type has nothing to do with it.
You can add any UnityEngine.Object as a subasset of any other asset.
can you?
last time I checked only ".asset" types support that
Yup.
Please note that you should only add assets to '.asset' assets, imported models or texture assets for example will lose their data. from the docs
You shouldn't but you can
The reason you shouldn't is because the UnityEngine.Object (for example Texture2D) is (re)generated when the file is imported. So if you have sub-assets and reimport the texture the Texture2D asset will be recreated and lose it's subasset data.
But it is totally possible to do still.
oh, my bad then
for some reason I was completely convinced that it wasn't possible at all
😓
All good, a good example of it is any time you import a .fbx. It will have things like materials and meshes as sub assets.
yep
@gloomy chasm but is it then possible to have sub-texture asset within a main texture asset and have Unity still handle it correctly?
wouldn't it freak out if you just try to use that texture asset without any custom implementations?
Nope, you cannot have sub-subassets
but you can this
hmm I see
so you just save the new images with a swapped palette as new sprites then?
i still thinking of how i can do this with OnPostprocessTexture
yep
How are you doing it now?
with custom importer
Basically copy-paste the code I think
i agree that this is not intended
yes, but when new texture (palette texture) will appeared it will trigger OnPostprocessTexture again
No because they are not imported.
for this kind of stuff of having multiple versions of a same image I usually just use texture atlases or multiple texture assets with different prefixes or suffixes
but I guess your approach could work too
And even if it was, you can simply do AssetDatabase.IsMainAsset(..)
for me it leads to sprite hell. i'll have tons of SO with sprites, because i have pixel frame animation in my game.
imagine like 40+ sprite frames for just one animated object and multiply it with palette count
yeah I see where you come from
I'd still probably just handle that at render time instead
what you mean?
apply the palettes at runtime, either with post-processing or when the textures are rendered
my main area of expertise is not graphics, so take this with a grain of salt
i want apply palettes at runtime through shader
palette swaps are fairly easy to do, specially now with ShaderGraph
there's a bunch of tutorials online
yes, and all of them has limited color count
because guys just shows ReplaceColor node
@pearl drift the tricky thing for your implementation will be how to deal with changes in the original texture
are you remapping the original pixels based on pixel index or on the original color?
*pixel coordinates, not pixel index
well I guess if your artists do some changes in the original texture's colors, they can just adjust the palettes accordingly
yes, or i can just reimport/rePostProcess it and regenerate palettes
I would explore a solution that relies on gray-scale values instead
that way you don't have to rely so much on the original colors of the image
i think it is the same. The diff is that with "red" solution you just write [0, 255] num into red channel, which will be the index of a color in palette. Grayscale solution just pick [0, 1] and lerp through palette. In all cases you will recolor your source image. In first case it will be black-red and in the second black-white
i have seen very smart solution, when guy split index by 3 groups of 2 bits and write them into 2 last bits of each channel, then in shader he reconstruct index from bits and sample palette. The trick is that overriding 2 last bits produces really inconspicuous effect, so your "mapped" image looks exact like source
@pearl drift another issue I see with your approach, is that you need to somehow lock the Texture2D asset from having its texture type changed
because if you change the type from Sprite to any other, all your palettes will be lost
yeah that's why I said I'd go a different route
Honestly, I would just make a scriptable object store all the palette data and keep a reference to the original texture
or something along those lines
the 1st i've said was "can we pls just use tints?" and my artist have looked to me with such face i just was unable to refuse
i'm here more about auto mapped sprite generation. Palettes can be generated separately with some custom window
yes as long as you keep the data outside of the texture asset, it doesn't matter if the designer messes up the texture type in the inspector and the sprite sub-assets are lost as long as your tool can just re-generate them
but at that point I'd skip that and just have the palette tool and then feed those palettes into a shader to swap them as needed
seems better than having a bunch of different textures in the same asset
you'd have a lot less bloat in size
and more flexibility
all generates and works well, except it weird grey stripes on final render. I even can't figure where they came from
It's probably interpolating the palette indexes because the texture has filtering turned on (and obviously the index halfway between two indexes in not necessarily a sensible intermediate colour).
@icy merlin this is strange, because none of textures has filtering, i mean it is point (no filter). Also picking R (or G or B) channel from my grayscale texture will give us 0..1. Here i have 4 different colors and palette texture 4x1. So giving for UV [0, 0.25) will produce 1st color, [0.25, 0.5) -> 2nd color, [0.5, 0.75) -> 3rd color and finally [0.75, 1) -> 4th color. So i think there i no issue with interpolating index.
I haven't used ShaderGraph extensively; are you sure that passing nothing in for the sampler will definitely use the sampler set on the texture, not a generic default sampler?
(That would certainly be reasonable behaviour to expect, I just don't know if it's what it does or not.)
the problem was about TextureFormat
man am i in love with uielements
tried to go back to imgui because of an old project and the idea of rebuilding the entire UI in UIElements is haunting me
The good news is you cant since ui toolkit isnt on feature parity with the working ui
would it be possible to make a sort of TSubclassOf from UE4 that works on ScriptableObjects? i'd like to use a child class in my ScriptableObject, but it seems like that is not possible 😄
I don't understand what you mean, but you can definitely make subclasses of ScriptableObject or classes that inherit from it.
i have a scriptableitem class that has a var with type AffixEffect, that isn't a scriptableobject itself, but it has a subclass AffixEffect_Stat which has more vars that i'd like to use instead of the base AffixEffect class
sorry if that doesnt make any sense
i googled around and people said that unitys serialization doesnt support it, but i just wanted to know if there was a way to make a TSubclassOf<T> from UE4 😄
Makes a bit more sense. Can you share the code maybe, you can look in #854851968446365696 for links to bin sites for sharing code.
I am not familiar with UE4. You can just do [SerializeField] private BaseClassType field; and then you are able to assign it an instance of the base type or any types that inherit from the base type.
CObjectScriptable is just a subclass of ScriptableObject that has some extra stuff
What is CAffixEffect?
And CObject?
What does it inherit from?
Okay, I see. So can you tell me again what you are wanting?
where it says Affix Effect
i want to use the subclass
CAffixEffect_Stat
so that i can change the values that are to be generated 😄
and also other subclasses at some point
Ah, you need to use the attribute [SerializeReference] in order to have polymorphic serialization on a field.
That is because it is null 😉
You will either need to make a custom property drawer so you can chose the type, or get an extension from github that adds a drawer for it.
ah right, is there an extension that automatically can draw those, or would i have to write one? 😄
Hi, for some reason I cannot find a package that I can find in another project, why?
These are 2 windows from 2 projects of mine
By default it won't show you Preview packages that aren't installed; you have to opt-in to it in settings.
This channel is about extending the editor, this is should be asked in #💻┃unity-talk.
But to answer your question you need to enable preview packages, click on the gear at the top right. A quick google will answer any other questions regarding this.
Thank you! Sorry, I was drawing a blank on what to search. @icy merlin
No, this is for discussion about creating custom editor windows. For general editor help #💻┃unity-talk is the right place.
ok
how do i make an inspector button "stay down" once it's clicked once?
here's the script i'm using :
private void DrawViewSelectionButtons(SubViewToggle[] subViewToggles)
{
EditorGUILayout.BeginHorizontal();
if (DrawingHelper.DrawNarrowButton("X-Axis"))
{
}
if (DrawingHelper.DrawNarrowButton("Y-Axis"))
{
}
if (DrawingHelper.DrawNarrowButton("Z-Axis"))
{
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
if (DrawingHelper.DrawNarrowButton("Select All"))
{
for (int i = 0; i < subViewToggles.Length; i++)
subViewToggles[i].check = true;
}
if (DrawingHelper.DrawNarrowButton("Clear All"))
{
for (int i = 0; i < subViewToggles.Length; i++)
subViewToggles[i].check = false;
}
EditorGUILayout.EndHorizontal();
}
I want to be able to push down the "X-Axis", "Y-Axis" AND / or Z-Axis buttons & have them stay pushed down once clicked. Then if clicked again, they pop back up. More than 1 of these can be pushed down at once.
you should use check-boxes for that
You need to store the button state yourself for each one, and display the button differently depending on whether or not they're true. This StackOverflow question has a bunch of examples: https://gamedev.stackexchange.com/questions/98920/how-do-i-create-a-toggle-button-in-unity-inspector
i dont want to use checkbox buttons. I want to use regular buttons.
@icy merlin @wild edge
You can display the active/inactive status however you like, it doesn't need to be a checkbox. But you still need to store the state and display the button differently depending on it.
ok
How you guys deal with rect counting when implement custom gui? I'm trying to place EditorGUI.DrawPreviewTexture, and i can't stop looking for some GetCurrentOffset or something like this. Maybe i can somehow get size of current BeginHorizontal or something?
This what you want? https://docs.unity3d.com/ScriptReference/GUILayoutUtility.GetRect.html
@gloomy chasm What is control?
It just means the rect for the thing you are going to draw. normally you would use it for getting a rect for something like a field (int, float, object, etc.) which are all just generally referred to as "controls"
the rect of the whole thing?
i mean i want to place my DrawPreviewTexture() right after last UI element. Unity's editor tools building is the most messed up thing i've seen
Does anyone know if the Pixel Crushers assets "Dialogue System For Unity" and "Quest Machine" work with Unity’s newer UI Toolkit? I am having trouble parsing all of the UI tool names (1st and 3rd party) for compatibility haha. Thanks!
omg, i've got it finally. It reserves space of given size, as docs of GetRect() says
Is there a way I can show an inspector for an object as if it were one of its child classes?
To explain, I have an abstract class SubactionBase, and tons of things that extend it. Some of these classes have serializable public fields. I have a List<SubactionBase> on a script. I have an editor script that adds specific implementations of SubactionBase to the list. How would I go about displaying the inspector for the actual class of that instead of the nothing I get trying to serialize an abstract class? I am expecting to have to do a bunch of if (subaction is ____) in OnInspectorGUI, but is there a way I can just draw the property of that class once I have it cast to what it actually is?
Does the list have the [SerializeReference] attribute?
It does now
In theory I think it should just work in the regular inspector if it has that attribute? I haven't used that path recently myself, though.
(And assuming all the relevant classes have [Serializable] attributes.)
Basically the hard part is usually getting the list of derived classes to serialize correctly; once that's working the editor gui (hopefully) sorts itself out.
I think that might be where I'm tripped up because it doesn't seem to be showing anything
The first example in https://medium.com/@trepala.aleksander/serializereference-in-unity-b4ee10274f48 has code that (supposedly) works to do this, so you could see if it's doing anything obviously different from you? (The rest of the article is about changing the list in the editor, which is more complicated but sounds like something you don't need right now.)
Okay, so, hierarchy is this:
The script TestFighter is a MonoBehaviour, it has a public List<FighterState>
FighterState is a plain C# object that is marked Serializable. It contains several List<SubactionBase> as described above, as well as a few serializable fields like StateName.
SubactionBase is [System.Serializable], as are all of it's implementations
In the inspector, I can see the list of FighterStates, but when I add any, they're just empty elements.
That blog post seems to be exactly what I need. I expect something else in my system is making this not work
Wait, I think I see something
My list of FighterState isn't [SerializeReference]'d? Maybe that's it?
No, that wasn't it
I still don't even see the basic string fields and whatnot
WAIT. GOT IT.
FighterState itself had an abstract class that wasn't serializable
@icy merlin you wonderful wonderful person
Yeah, that would probably break it. Sounds like it's all good now!
Ahahahah it works! Now I'll go through that blog post and see what I have to do to make the rest of this list look pretty. First step, figure out a way to get Element N to be replaced by the class name. Now that I'm solidly in the realm of "stuff I can reasonably google" I'll see what I can do
The name is the label if i remember right.
is there a way to get a notification when an internal EditorWindow is closed?
I need to run some logic when a ColorPicker window is closed
@patent pebble i think it is simpler to compare current and previous color value
nope, because the logic I need to run is independent of the color value and if it changed or not
I just need to get a notification when the ColorPicker window closes so I can set focus to a different control
probably you can use GetWindow with colorpicker type and then check if it is null, which means it is closed
yeah I figured I can just check what window is focused with EditorWindow.focusedWindow
I'd prefer if there was a OnClose callback or something that I can subscribe to, would be more readable
how do i use
if (DrawingHelper.DrawNarrowButton("X-Rotation")) { rotationAxisSelected = 0; }
as
GUILayout.Toggle ( enableToggle, "Toggle Me", buttonStyle );
?
Does anybody know if there's a way to add a button in the bottom bar of the editor?
I'm going to make some tools to report some details and warnings about the project and the bottom bar is a perfect location for a visual status icon/button
but I have no clue how to add stuff down there, nor where to look in the source code 😅
Go injection
Look for AppStatusBar, AppToolbar, those types
or just open the Visual Debugger
someone can help?
how do i use
if (DrawingHelper.DrawNarrowButton("X-Rotation")) { rotationAxisSelected = 0; }
as
GUILayout.Toggle ( enableToggle, "Toggle Me", buttonStyle );
only posting it 1 more time
@onyx harness aaah right right, thanks for the reminder! I always forget about the IMGUI Debugger 🙏
What do you mean by your question? You want to have a toggle act like a button?
@whole steppe use a toggle with the style of a button
someBool = GUILayout.Toggle(someBool, "Toggle with button style", GUI.skin.button);```
^ Then in addition to that, throw a if-statement for whatever you set your toggle for, below the toggle whenever you need it, if(someBool){ ... }
@whole steppe when doing this sort of thing it's usually more helpful to think "I want this control to LOOK like this other control"
because you are not changing logic, just the way they are rendered, i.e.: changing their GUIStyle
most IMGUI controls have overloads that use styles
a "control" in this case is the term used for any IMGUI thing (buttons, labels, toggles, etc)
i just want the button to be held down until i click on it a 2nd time. @patent pebble
ok
@patent pebble : & I want the logic to work with the button. When it's down,
rotationAxisSelected = 0;, AND / OR rotationAxisSelected = 1 AND / OR
rotationAxisSelected = 2;
& you can have more than 1 set value at once
@whole steppe do you want only 1 button, or do you have multiple buttons?
@patent pebble : I have multiple buttons. "X-Rotation", "Y-Rotation" & "Z-Rotation"
@whole steppe can all of those buttons be turned on at the same time? or are they mutually exclusive?
if they are mutually exclusive you can use GUILayout.Toolbar, if they are independent you can just use toggles with button styles
@patent pebble : They can be turned on at the same time.
use toggles as we told you on previous messages
and handle the logic inside a bool check
that's what i'm doing.....
EditorGUILayout.BeginHorizontal();
// if (DrawingHelper.DrawNarrowButton("X-Rotation")) { rotationAxisSelected = 0; }
// if (DrawingHelper.DrawNarrowButton("Y-Rotation")) { rotationAxisSelected = 1; }
// if (DrawingHelper.DrawNarrowButton("Z-Rotation")) { rotationAxisSelected = 2; }
if ( GUILayout.Toggle ( enableToggle, "X-Rotation", buttonStyle ) ) { rotationAxisSelected = 0; }
if ( GUILayout.Toggle ( enableToggle, "Y-Rotation", buttonStyle ) ) { rotationAxisSelected = 1; }
if ( GUILayout.Toggle ( enableToggle, "Z-Rotation", buttonStyle ) ) { rotationAxisSelected = 2; }
EditorGUILayout.EndHorizontal();
@patent pebble
you need to cache the toggle's bool
and you need to use a separate bool value for each toggle
i told you on the code snippet I shared
someBool = GUILayout.Toggle(someBool, "Toggle with button style", GUI.skin.button);```
then do an if with the someBool
and the rotationAxisSelected logic inside
ok
if (someBool)
{
// Do thing
}
ok
but by the look of your code, I would guess you only want to select one axis at any given time
in which case, use GUILayout.Toolbar
nope, because i want to be able to rotate an object on 2 or more axes at the same time @patent pebble
ah, then yeah, toggles
storing the value in variable in the script
yes, but that doesn't really tell me anything as i'm using private bool enableToggle = false; at the top of my script
@patent pebble
then you are caching the result of the toggle in that bool
if you are struggling with this, I suggest you go to #💻┃code-beginner and ask there for help
so im already doing it? for some reason when i click the button, it doesn't stay down even though im caching it already.
@patent pebble
share the code then
ok
i literally copypasted you multiple times how the toggle is supposed to be used, you can also check the documentation
I'm sorry but I just can't keep copypasting the same thing over and over if you refuse to use the information we give you 🤷
@patent pebble :
public class StudioEditor : Editor {
private GUIStyle buttonStyle;
private bool enableToggle = false;
public override void OnInspectorGUI() { EditorGUILayout.BeginHorizontal ( );
bool xRot = GUILayout.Toggle ( enableToggle, "X-Rotation", GUI.skin.button );
EditorGUILayout.EndHorizontal ( );
}
}
You need to set enableToggle, not create a new bool variable.
how would i set it, @gloomy chasm ?
enableToggle = GUILayout.Toggle(..)
I do do that already, @gloomy chasm :
bool xRot = GUILayout.Toggle ( enableToggle, "X-Rotation", GUI.skin.button );
...no you are passing enableToggle as a parameter, now you need to also set it to be the returned value.
@gloomy chasm hey iirc you mentioned you are quite experienced with the whole View, GUIView, HostView, etc thing, and I was wondering what would be a good approach to insert stuff into existing Views
I've been digging for a couple hours and so far I've only figured I can use the position of an existing View, create my own View and then draw whatever I need to insert there
I'm trying to add stuff to the top toolbar and the bottom toolbar of the Editor
That depends completely on where and what you are trying to insert.
What version of Unity?
2020.3.3 and upwards
Im trying to add buttons there
but in the top Toolbar they would mess up with the auto layout of unity
For above you can just use UITK
In later versions the AppStatusBar is UITK as well. But for 2020.3 idk if you can do much without using something like Harmony.
@gloomy chasm hmmm, I'm trying to stick with LTS versions for now
I'll check out UITK
I guess for now, I will try to just overdraw on top, and for cases where the main window is too small and the layout gets shrunk in, I can just draw on top of the small "packages in use" yellow dropdown
and on the bottom on top of the generating light info area
(whenever it's not generating lighting settings)
@gloomy chasm oh, that's pretty neat!
I wonder if something like that is possible just with IMGUI, there's a ton of methods and properties on the Toolbar class that I haven't tested yet
Nope, the only way it would be possible is if there was an event property, but there isn't.
Just come to the dark(UITK) side! You cannot resist forever!
You know, this may be the final straw of my laziness
i may actually have to finally learn UITK 🙃
I'm struggling with color field. I need to place dynamic count of color fileds in a row (horizontally) but i can't figure out why those fields not adapt to window width whatever GUILayoutOption i pass and i get this editor view, where you can see just one and a little part of color field but there are 14 more in right lands
@pearl drift share code
@patent pebble ```csharp
EditorGUILayout.BeginHorizontal();
for(int i = 0; i < palette.Count; i++)
{
palette[i] = EditorGUILayout.ColorField
(
new GUIContent(string.Empty),
palette[i],
false,
false,
false,
GUILayout.MaxWidth(_paletteElementSize),
GUILayout.ExpandWidth(true)
);
GUILayout.FlexibleSpace();
}
EditorGUILayout.EndHorizontal();
I think there is some default color field width, because GUILayout.MaxWidth() + GUILayout.ExpandWidth(true) helps
@pearl drift you can just do GUILayoutUtility.GetRect and then edit the values as you want
Perfectly i want some logic to move elements to next line if window's width capacity was reached. Must be easy as just call Begin and End horizontal on over width
i have a tool that does a grid of rects that flow like that
I can share the logic for the rows columns
also, for your thing you may want to use the internal Color field without the picker
looks cleaner
private void DoColorField(Rect rect, SerializedProperty colorProp)
{
int id = EditorGUIUtility.GetControlID(FocusType.Passive);
object[] args = new object[] { rect, id, colorProp.colorValue, false, false, false };
colorProp.colorValue = (Color)EditorGUIProxy.DoColorField(args);
}
private static partial class EditorGUIProxy
{
public static System.Reflection.MethodInfo m = typeof(UnityEditor.Editor).Assembly.GetType("UnityEditor.EditorGUI").GetMethod("DoColorField", (System.Reflection.BindingFlags)60/*Instance|Static|Public|NonPublic*/);
public static object DoColorField(params object[] args)
{
return m.Invoke(null, args);
}
}
it would be so cool
Why there used SerializedProperty instead of regular color?
because SerializedProperties are the best way to deal with Editor data
private void CalculateGridDimensions()
{
int elementCount = Data.currentTexturesSearched.Count;
float usableWidth = Structure.GridViewRect.width - Structure.gridViewMargin.x * 2 - Structure.scrollbarWidth + Structure.gridElementSpacing;
int maxColumns = Mathf.FloorToInt(usableWidth / (Data.GridElementSize + Structure.gridElementSpacing));
Data.rows = Mathf.CeilToInt((float)elementCount / (float)maxColumns);
if (elementCount < maxColumns)
{
Data.columns = elementCount;
}
else
{
Data.columns = maxColumns;
}
}```
here's the code to calculate a grid
it's a bit out of context
but you get the idea, instead of assigning to the Data.rows / Data.columns you can return a Vector2 or something
thank you 👍
for the "usableWidth" you pass the total width of the area you are drawing in, usually the inspector or editorwindow width - some margin values
and for the maxColumns you just divide the usableWidth by the width of an element
this is assuming all your elements have the same width
yep, this is clear 🙂
if for some reason this doesn't fit your use case, just google "C# calculate grid" and you'll find a bunch of examples online
What with UI Toolkit? Can we do same things with it more easily
i don't know how to use UITK, so all my tools are still using IMGUI
i'd assume the logic itself would be pretty similar
To do a grid? Yes much, much, much easier, a grid with a lot of elements, not easier.
@gloomy chasm IMGUI is a pain in the ass to do some basic things
like grids or radio buttons
Actually, grids are not even too bad in IMGUI, but it depends if you are doing scrolling or not.
Radio buttons, you mean like where only one can be toggled on at a time?
Really? I didn't find it too bad to do my self.
yeah, I mean it's not that bad once you just make your own control
it's not super horrible, but could definitely be better
doing a grid with scrolling in both axis, zoom in/out, free flow, different element sizes and drag and drop features
first time I did it it took me a while
Ah, yeah. I think it ended up taking me a day or so to do? But I was also making a more 'generic' base so I could have a 'grid view' control and a 'list view' control.
yeah I need to convert my implementation so it can be reused
but I don't do a lot of stuff with grids, so there's no rush for me
are there plans to be able to serialize custom classes on base class variables?
or is the only way rn is to use scriptable objects/monobehavior?
Are you aware of SerializeReference?
nope
thank you, very veyr much
im about to lose my mind
It's not a complete solution on its own (you may need custom editor code depending on what you want to do) but it should handle the serialisation part.
THANK YOUUU
it worked!
just had to undo my changes and add "SerializeReference"
Are PropertyDrawers using UI Elements currently broken?
I have this quick test, but it shows No GUI Implemented
PropertyDrawer TestTypeDrawer.cs
#if UNITY_EDITOR
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;
[CustomPropertyDrawer(type: typeof(TestType), useForChildren: true)]
public sealed class TestTypeDrawer : PropertyDrawer
{
public override VisualElement CreatePropertyGUI(SerializedProperty property)
{
Debug.Log("Active");
VisualElement container = new();
FloatField floatField = new(label: "Fancy Label");
floatField.RegisterCallback<ChangeEvent<float>>(callback: evt =>
{
Debug.Log(evt.newValue);
});
container.Add(floatField);
return container;
}
}
#endif
Type TestType.cs
using System;
using UnityEngine;
[Serializable]
public struct TestType
{
[SerializeField]
private Int32 i;
public TestType(Int32 i)
{
this.i = i;
}
}
Usage Usage.cs
using UnityEngine;
public class Usage : MonoBehaviour
{
[SerializeField] private TestType testType;
}
```EDIT: Fixed fault in example code.
The debug messages are never logged.
If I remove the property drawer it works just fine.
I haven't used UIElements, but shouldn't you do something with the floatField? Like, add it to the container?
UI Toolkit editors will only be used inside another UI Toolkit editor. Since your MonoBehaviour doesn't have a custom editor it's being drawn with IMGUI, so your UI Toolkit drawer isn't being used
Whoops, that's what I get for stripping my examples down for Discord. :P
Thanks, yeah that'd be it. That's annoying!
So that means that they're basically not usable for this purpose atm as I can't guarantee that the end user will be using a custom editor.
You could supply a drawer that overrides the default drawer for Objects to make them draw using UI Toolkit.
Yeah, that's what I did now.
However, that might break third-party dependencies. They might be doing the same things and that could be troublesome.
I made such a thing although I can't guarantee it will work everywhere but so far I've not encountered issues, see my post here: https://forum.unity.com/threads/property-drawers.595369/page-2#post-7644859
Unfortunately my fears were not unfounded.
The inspector breaks when importing Odin.
Does Odin make their editors support UI Toolkit Property Drawers? Might work when they've wrapped it.
Nor does it change when I change the execution order, but that would likely still break things.
Not yet they don't.
Welp that sucks a bit. The latest Unity 2022 Alpha supposedly now supports UI Toolkit Property Drawers out of the box though, so maybe by 2023 Toolkit is viable for such a thing?
We'll have to wait and see. UI Elements certainly has a lot of promise - so I'm looking forward to it.
Bit of a shame it wasn't done when the new editor UI was introduced.
Tried it in the latest version, didn't work for me sadly.
Not that I'd wanna be using an Alpha for Unity, but still.
Hey, I'm using VSCode with C# extension to edit Unity scripts, but for some reason there's no autocomplete for whatever I'm trying to write
on linux btw
If this is IMGUI, create a modifed GUIStyle
no, this is custom editor window
IMGUI or UIToolkit.
oh, not UIToolkit, then it is IMGUI
but i see no method to pass GUIStyle to color field
Then your other option is to position them manually with EditorGUI instead of EditorGUILayout
i was making an extension method to get the array from a SerializedProperty
public static T[] GetSerializedPropertyArray<T>(this SerializedProperty property)
{
if (property == null || property.arraySize == 0)
{
return null;
}
if (property.isArray == false)
{
throw new ArgumentException($"{property.name} is not an array property");
}
...
but it seems to fail with any kind of multidimensional, or nested collection
[SerializeField] string[,] _test;
My Unity serialization knowledge is rusty
is this not allowed?
string[,] is not serializable
you can just look in the debug inspector and see if it's there
if it's not, it's not serialized
@visual stag aaah right right. I should've checked if it was displayed on the inspector
I was doing this for an EditorWindow tool so the thought didn't cross my mind
thx for the answer
The only collections that Unity can serialize is List<T> and T[]. Specifically those, nothing else.
thx for the clarification
does the new [SerializeReference] change anything regarding collections and serialization?
Generic Lists and array fields decorated with [SerializeReference] apply the attribute to the elements of the list/array not the list/array instance itself. only found this on the docs
Not in any way that is different than when using it on another field type that is not a collection.
What this says is all that it does. There is nothing to add.
@gloomy chasm i see, thx again 🙏
Anyone know how to get the values of a List<Type> using serializedProperty?
Yeah, that gives you a property reference to the element, but how do you modify the element value
Yeah System.Type
System.Type is not serializable by default
Hm okay, so I was going off the advice from the web that it's better to use serializedProperties instead of directly modifying the values yourself...
When I directly modify them and then call EditorUtility.SetDirty(target) the object doesn't seem to save
Any way to go that route instead?
That advice is correct
But your type won't save
You'll have to write something to serialize it yourself
So you're saying the scriptableObject itself will refuse to save non-serializable fields?
Not the scriptableobject, but the serialization system that saves fields to files on your disk
There's a bunch of open source serializable types
Aye, but what I'm asking in effect is: Without Type being serializable by Unity, no method of editing the value with the CustomEditor will result in the object saving that value
Yes
Okay, good to know. Thanks
I am creating assets and wondered if I can manage all my assets in 1 project. I want to have 1 main folder with the company name, with 1 subfolder per asset. To upload the asset I have to select the company folder, without being able to select the subfolders.
Does this mean I have to use 1 project per asset? I would like to manage it all in a similar way because the assets can support each other.
How do you tell the inspector to display a variable like this?
I'd like to have a range setting with a min/max
[Range(0,100)] int value;
That only gives a slider unless im mistaken?
Owhh understood it wrong
Do you mean with an attribute? You would have to do it your self, or use one already made like this one (I have not tested it my self) https://gist.github.com/frarees/9791517
Yeah with an attribute, thank you for the link, i'll look into it
Any idea what causes e.DrawHeader(); to do... This? And any way to fix it? O.o
Component[] components = Selection.activeGameObject.GetComponents<Component>();
for (int i = 1; i < components.Length; i++)
{
Editor e = Editor.CreateEditor(Selection.objects[0]);
e.DrawHeader(); //withtout this, everything works fine but I want to also include a header, is there another way?
Editor editor = Editor.CreateEditor(components[i]);
EditorGUILayout.InspectorTitlebar(true, components[i], true); //this just displays the header "Transform", "Box Collider", "Mesh Filter", etc
editor.OnInspectorGUI(); //this is supposed to display the serialized variables of "components[i]", which works but why DrawHeader cause it to get squished regardless of the width of my custom editor window?
}
Is there some other line I need to "end" or "close" the draw call or something? Why would it cause everything to get squished like that?
(sorry image didnt get attached in my last message o.o)
Presumably something is changing EditorGUIUtility.labelWidth and not setting it back
Hmm, interesting, for the time-being I basically just tried to replicate the header manually (downside is I cant get the static dropdown and icon change menu but I guess thats not terrible), that GUIUtility code might give me a place for research though, so thanks for that
Oh, turns out you were right, if I set labelWidth to 150 after the DrawHeader line, it fixes everything, very odd though cause theres no where in my code where I ever modify labelWidth or any GUI styles o.o - thanks for the help btw
Is there a way I can draw a property only if a list is expanded? I have a List of a serialized class and I want to add in a special add button to the list, but I only want it visible while that list is expanded. I know I could make a custom class that extends List and do a property drawer, but is there another way to do this without making a new class?
Okay, I tried the "make a class that extends list" solution and it doesn't work. It doesn't seem to display the list properly.
it depends a lot on the situation
if you want a button only on the top of the list or if you want it on every element of the list
you can use a custom attribute to add buttons to variables, there's a bunch of them online
https://assetstore.unity.com/packages/tools/utilities/stackable-decorator-111270 this one has a buttons
and I think NaughtyAttributes also does, but I don't know if they are only method buttons or not
Fellow editor extenders
I am confuse
I have a bunch of ScriptableObjects with custom inspectors, and for some reason only one of them keeps its values when I close down the project
The mysterious vanishing data is in a List and is represented using a ReorderableList
The code in question:
{
FieldInfo[] fields = typeof(PlayerData).GetFields();
foreach (FieldInfo field in fields)
{
SerializedProperty serializedProperty = serializedObject.FindProperty(field.Name);
if (serializedProperty.isArray)
{
ReorderableList reorderableList = new ReorderableList(serializedObject, serializedProperty, true, true, true, true);
reorderableList.drawHeaderCallback = (Rect rect) => EditorGUI.LabelField(rect, serializedProperty.displayName);
reorderableList.drawElementCallback = (Rect rect, int index, bool isActive, bool isFocused) => EditorGUI.PropertyField(rect, serializedProperty.GetArrayElementAtIndex(index), GUIContent.none);
reorderableList.onAddCallback = (ReorderableList reorderableList) => serializedProperty.ArrayAdd(toAdd => toAdd.isExpanded = true);
reorderableLists.Add(reorderableList);
}
else
{
serializedProperties.Add(serializedProperty);
}
}
}
public override void OnInspectorGUI()
{
foreach (SerializedProperty serializedProperty in serializedProperties)
EditorGUILayout.PropertyField(serializedProperty);
EditorGUILayout.Space();
foreach (ReorderableList reorderableList in reorderableLists)
{
reorderableList.DoLayoutList();
EditorGUILayout.Space();
}
if (serializedObject.ApplyModifiedProperties())
AssetDatabase.SaveAssets();
}
private List<ReorderableList> reorderableLists { get; } = new List<ReorderableList>();
private List<SerializedProperty> serializedProperties { get; } = new List<SerializedProperty>();```
Ah, looks like I solved it
Why does Don't Save actually save?
Am I missing something?
Dumbest thing I've seen in a while
So it's Save modifications, discard changes, and do nothing on Save/don't/cancel?
It returns true if the user selects 'Save' or 'Don't Save'. It only returns false when the user selects 'Cancel'
Note: Currently a window with three buttons is shown. Save and /Don't Save/ both cause the Scene(s) to be written. Cancel leaves the Scene(s) untouched
From the Docs ^^
Like who would ever want that?
@pure siren are you sure the "Don't save" option actually saves the scenes?
last time I used it, only the 1st option saved scenes
I'm pretty sure the Save and Don't save both return true, but only the first one will save the scenes
If that's the case then the documentation is wrong, which would be bad too.
you use 'Save' or 'Don't Save' to continue and do whatever you do (usually open a new scene or something like that)
and you use Cancel to just cancel the thing you would do
at least that's how I remember it
I agree that the return value behaviour makes sense, though it should be more clearly documented.
docs seem to be updated in the recent versions
but not on the current LTS doc versions
If the user selects Save, the Editor saves the modified Scenes. If the user selects Don't Save, the Editor does nothing. However, both Save and _Don't Save__ indicate that the user is okay to proceed with the current operation (closing the Scenes). Therefore both these choices return true to indicate that the operation can continue.
@pure siren there's your answer
they should update the current versions of the docs 😓
I've left feedback on that docs page. But i have no clue how long they take to fix this sort of thing
Thanks that clarifies things. I was originally calling SaveOpenScenes based on the return value, but now I realize that's unnecessary.
It still doesn't allow you to check if Save or Don't Save was clicked. Although I don't really see a use case for that, it could be implemented manually with DisplayDialogComplex.
@pure siren i believe there's events that notify you when a scene is saved
so you can just use those to check if Save or Don't Save was clicked
Is there a way to add a function to EditorGUILayout.Foldout like we can do with button.onClick.AddListener? I want to execute function whenever user clicks on the foldout or label.
AFAIK you cant extend the Foldout directly, though because it returns a bool, you could setup your own event with a "last state" of the returned bool, for example:
System.Action OnSomeEvent;
bool isFoldoutExpanded;
bool lastFoldoutState;
//Somewhere in OnGUI()
isFoldoutExpanded = GUILayout.Foldout(isFoldoutExpanded, ...);
if (lastFoldoutState != isFoldoutExpanded) {lastFoldoutState = isFolderExpanded; OnSomeEvent?.Invoke();}
Then if you need to if(isFoldoutExpanded) {DisplayGUIStuff();}
The correct way is using the Event.current field and check the type etc... But that can get quite complicated so if you need something simple then the above works
hi, i wonder if there is a straightforward way to make Foldout Headers. Like i would like a header to foldout all variables inside of it.
i can use foldout to find Transform, or specific properties, but how do i tell him to foldout all headers?
Does anybody know how to check if the Inspector window is currently showing the vertical scrollbar?
I'm making a custom editor for some scriptable objects and I need to know so I can adapt my rects accordingly
Hi all
Just wondering how can i check if the selected is an fbx asset?
Selection.activeGameObject.name.EndsWith(".fbx") this doesn't work it seems
O i can use AssetDatabase.GetAssetPath
I'm attempting to make a custom editor window for my dialog. I'm having two nagging issues I cannot seem to figure out. First, when editing text in the text area, the undo is not recording at all. Second, when I make a change in script and it reloads, I lose all my drawn Beziers until I add a new node. Any help would be greatly appreciated. https://paste.ofcode.org/yt6D5pRDkSWquzri66eXNv
Have you tried currentViewRect?
what's that? I can't find on the docs or in the source code
You're not serializing anything so no undo can occur. Undo uses the serialization system.
Losing data over script reloads is also a lack of serialization
When I kept normal serialization, it was adding a new node every script change.
That is why I stopped serialization on most of the values. private SO_Dialog selectedDialog; private GUIStyle nodeStyle; [NonSerialized] private DialogNode draggingNode; [NonSerialized] private Vector2 dragOffset; [NonSerialized] private DialogNode queuedNodeParent; [NonSerialized] private DialogNode queuedRemoveNode; [NonSerialized] private DialogNode queuedNodeToConnect;
should I also be specifically telling it to serialize something?
nope, this seems to just return the window's width, scrollbars don't change it 😓
i also tried an approach similar to this
https://pastebin.com/8Xu5SeDX
but I can't get the value from the m_scrollPosition
inspector.GetType().GetField("m_ScrollPosition").GetValue(inspector)
I can't get that, i don't know if it doesn't exist anymore in the InspectorWindow class or what
Another easy way is to use guilayout to get a rect with max width
OH MY GOD
I can't believe it was that simple 😶
I have been struggling with this issue for months, and every time I just gave up and made all my tools preemptively add a buffer margin to account for scrollbars
There's a lot going on that I can't speak to, but yes, if you're expecting values to persist in an Editor Window they need to be serialized (same way it works in a MonoBehaviour, except when the window is closed they're lost)
If you're having issues with duplication/new data then it's likely your logic isn't handling something correctly
@waxen sandal thanks a lot 🙏 do you know if getting a rect with 0 height can cause problems for the layout system?
Rect testRect = GUILayoutUtility.GetRect(EditorGUIUtility.currentViewWidth, 0);
I remember having situations where my entire Unity exploded when getting zero-height elements in ReorderableLists
I haven't had issues with that
But it might add a few pixels of padding if you use more guilayout
@waxen sandal I see, I'll keep an eye for that. Many thanks
alright. thank you.
Why am I getting this in my output
[fail]: OmniSharp.MSBuild.ProjectManager
Attempted to update project that is not loaded: /home/araraura/Unity/Projects/test/Assembly-CSharp.csproj
[warn]: OmniSharp.Roslyn.CSharp.Services.Navigation.FindUsagesService
No document found. File: /home/araraura/Unity/Projects/test/Assets/test.cs.
I'm trying to use unity on linux through vscode and I've installed everything the arch wiki told me to, and still
if anyone knows then please ping me
Also I have another issue where Rider doesn't appear in external tools
where would that be?
Hi! I have a question regarding a custom inspector editor. I'm trying to draw the contents of a list where each entry should be on a new line. I'm using EditorGUILayout.BeginHorizontal and EditorGUILayout.EndHorizontal around each entry, but they still all draw on the same row. I'm not super familiar yet with all the gui layouts yet
You probably want some BeginVertical
Replacing the horizontal with vertical draws each element below each other
Just to confirm, each number should be on a new line. I wasn't really clear about that 😄
That works and I just realized why.. Thanks!
Is there a way to make a MenuItem async? I want to open all scenes and take a screenshot of each one for a thumbnail for a level selector. This only screenshots the last scene as it's not asynchronous.
You might want to use coroutine
async/await probably works as well
@summer creek where ever you installed rider, just manually point unity to rider's executable
yea i installed it through the AUR so i didn’t know where it was
Does anyone have any tips, or an editor extenstion, to help with placing objects in a scene? For example, I want to place a reflection probe in the scene on the ground in front of where I'm currently standing in the scene view. But if I create a new reflection probe in the heirarchy it appears at 0,0,0 and finding it and dragging it to my current scene location is a chore. Often I will create the object as a child of something nearby and then drag it out, but that too is problematic when I have hundreds of placed objects in my scene, so then I have to open two hierarchy windows and lock one of them to the probes section, which is also a pain. Why can't I simply right click in the scene, and get a context menu, with add item, and maybe a toggle to select "under cursor" with it doing a raycast into the scene that can collide with terrains, or "at my location"? This would save literally thousands of hours and I don't understand why Unity doesn't have this as a built in feature for scene construction.
I can't even drag the object I created into the scene view to have it placed where the mouse is...
Well that does work with prefabs... Maybe if I create a prefab of a reflection probe? The idea is ridiculous but...
Well that seems to have worked, though I can't seem to slide the probe around on the terrain keeping it at the terrain height by holding shift, which I thought worked with other objects...
Ah, I see, it's shift and ctrl to do that. It's called surface snapping:
https://docs.unity3d.com/Manual/PositioningGameObjects.html
I've craeted scripts in the past to move objects in front of the camera
Or to raycast into the scene and instantiate an object at the hit point
There are couple of easy-to-miss commands in the GameObject menu that might help; "Move to View" sounds like it's the closest thing to what you want?
Is there a way to change this via a script ?
Basically to check quick multiple resolutions to see if everything UI related behaves correctly
Reflection can do it iirc
Thanks, I never noticed that! This in spite of having been using Unity for like three years... Probably because I almost never need to access that menu except when importing an asset and not even then if I just drag it into the window. Might have been better for that to be on a right click menu when you have the object selected.
Set whichever field that is using reflection. Refer : https://github.com/Unity-Technologies/UnityCsReference/blob/e740821767d2290238ea7954457333f06e952bad/Editor/Mono/GameView/GameView.cs
As far as I know it's all internal apis, so as Navi says you'd need to use reflection to call them. Take a look through https://github.com/Unity-Technologies/UnityCsReference/blob/master/Editor/Mono/GameView/GameView.cs ; SizeSelectionCallback seems like the most reasonable entry point.
@heady shadow @icy merlin You are great, thanks for the pointers.
Is there a way to force Unity to refresh the priority order on the menu items on the top bar?
usually I have to comment out the [MenuItem(...)] attribute in the script, recompile, uncomment and recompile
only that seems to update the order of the menu items
there has to be a better way to do this, anyone has info on this?
sad... 😓
restarting Unity seems to work too, but it gets annoying with heavy projects
The whole menu item thing is a big mess
yup
maybe it's possible with reflection to update the value, it has to be cached somewhere
but I have no idea where to begin looking
Not sure but I vaguely remember trying to look into it and not finding anything before
the weird thing is that sometimes they refresh just fine, but other times they don't 😅
found these two classes on the source MenuService, MenuItemScriptCommand
i'm hoping some of the methods there can be used to solve this
https://github.com/Unity-Technologies/UnityCsReference/blob/master/Editor/Mono/MenuItem.cs#L63
https://github.com/Unity-Technologies/UnityCsReference/blob/master/Editor/Mono/EditorMode/MenuService.cs
*Edit: crap, they were both added in recent versions, they aren't available in the current LTS version 💀
In the past I've found Unity to be quite aggressive in caching things based on attribute data; scripts would often continue running in edit mode for a while after I removed their [ExecuteInEditMode] attributes, for example.
What Unity does or does not reload on script recompilation has always been extremely confusing to me.
I followed the Unity Guide for making the project, but wonder:
If my asset isn't that big, and a tool, would it be better to put the asset in a Plugin folder in the root or still the name of my company?
Always in a folder with either the name of the asset, or company name or something else unique to you. The Plugins folder is made for native DLLs typically written in C/C++.
Good to know, thanks!
Still finding a way to manage multiple assets from the same folder sadly (https://forum.unity.com/threads/multiple-assets-in-1-folder-on-asset-store-publisher.1197730/#post-7660879)
Really should be a default feature imo
what's the correct way of copying a SerializedProperty?
i have PropertyA and PropertyB
they are both arrays
I want to copy the values from A to B
do i need to iterate over every element individually and copy it? Or is there a simple way of just copying the entire array?
SerializedObject has a copy method.
serializedObject.CopyPropertyValue(..) or something like that
but from what I've seen that's used to copy 1-to-1 representations of serializedpropertys between 2 different SerializedObjects
I'm not sure tho
You mean copy properties with the same path?
Are the properties you want to copy at different paths?
i think so, I've found this example online
they seem to be using it to copy values from one SerializedObject to another SerializedObject
You think so...?
If CopyFromSerializedProperty doesn't work for you, I think you need to be more specific in what you are doing exactly.
I've never used that method, so I don't know exactly how it works
I'll share some context on my situation
One way to find out 😉
yeye I'll test it out now. But I wanted to ask first just in case
Yeah, thinking about it, it uses the path.
So if the path is different it will not work.
I have a wrapper class that has an array, and a container class that has multiple wrappers
[Serializable]
public class Wrapper
{
[SerializeField] private Color[] _array;
}
public class Container : ScriptableObject
{
[SerializeField] private Wrapper _originalWrapper;
[SerializeField] private Wrapper[] _modifiedWrappers;
}
in my particular case, I want to make copies of the _originalWrapper and paste them in the _modifiedWrappers array
looping through the color array and assigning individually every element works fine, but it's ugly and has a lot of boilerplate code
so I was wondering if I can just straight up copy the entire property
I see, I don't think that there is a built-in way to do it. You could write an extension method that does it though.
I had made an extension to get the array value from a property
so I guess I'll go the same route and make one for setting arrays
I would switch on the target property's type, and if it is a basic type, then copy it, otherwise iterate through both of the properties recursively calling the method.
hmm I see, will do
You could do some checks first like make sure they are the same type, and name and such.
Yeah that's probably a good idea
found this online
seems to work for any property
Well if you are going to go that path then you may want to just use mine since it supports [SerializeReference] and imo is easier to read. It would just take a tiny bit of editing to behave the same as that one. https://github.com/MechWarrior99/Bewildered-Core/blob/main/Editor/Extentions/SerializedPropertyValueExtensions.cs
ah neat, thanks for sharing! 🙏
Yeah, hope it helps.
it will! thanks a lot
2022.1.0a15
Serialization: Added: SerializedProperty.boxedValue property.
Serialization: Added more examples to the reference for dealing with Arrays with SerializedProperty.
Serialization: SerializedProperty.boxedValue property supports reading and writing entire Structs.
That is amazing!! 😄
What is the type of boxedValue do you know?
I also wonder why it is just structs and not classes considering that on the serialization side they are both treated as value types.
Yeah, I would assume that it would be object, just curious ya know.
it is object
Alrighty, thanks.
On interesting, that could actually be quite handy.
Why is the Integer just a break?
Ah, got it.
Huh, so how does the struct part work
Looks like it is just a object field called structValue
Oh, I see
Certainly still unclear whether that would work on a class
I also wonder when the CsReference updates
seeing as we are behind again
Won't change anything, GetStructValueInternal is external
I know, I'm just speaking generally
I would assume it doesn't work for classes since the method name specifies struct.
Though again, I wonder why.
Well, that's never meant much in serialization land
Yeah
everything mentions "properties" and that's not talking C#
Yeah, I just mean that since they specify struct.
Will have to wait until someone tests it 😄
I won't be able to test it until this evening, but if no one else has by then I will and will let you know. 🙂
I added uml diagrams to my serialized object how-to the other day https://help.vertx.xyz/?page=programming/editor-issues/serialisation/serializedobject-how-to
now I might have to include boxedValue 😓
I've already forgotten that other addition to serialization that happened last release (maybe I'm hallucinating)
Beautiful
I feel really outdated in Unity now
I don't think there were any additions last update.
I might have just been thinking of that weird UIToolkit property drawer mention
It would be easier to keep up (or get caught up) if Unity actually made even half way okay change logs 😛
I'm glad they're putting packages under headers now.
I also note in this release that they've dealt with the overhead of just having the Visual Scripting package in your project
So for those that didn't just remove it as the first step, rejoice
They put packages under headers now?
I mean this
Oh, yeah I guess that is slightly better. But imo they are still some of the worst changelogs.
Sad my basic-ass bug is still active https://issuetracker.unity3d.com/issues/ui-toolkit-uielements-text-fields-in-arrays-stop-accepting-keyboard-input
Previous release got a bug with this much code fixed:
using UnityEngine;
public class Container : MonoBehaviour
{
public Object[] Data;
}```
Next release I report this one with this much code:
```cs
using UnityEngine;
public class Container : MonoBehaviour
{
public string[] Data;
}```
just feels stupid
(and while reporting that one, I find another one)
Sad. I bit ago I finally submitted the bug about custom asset dark theme icons not work I hope it will be fixed sometime... it has been in since at least 2018. I can't believe no one reported it before me... https://issuetracker.unity3d.com/issues/custom-assets-do-not-use-dark-theme-icons-when-the-editor-theme-is-set-to-dark
What am I seeing?
https://www.youtube.com/watch?v=cDiLpFWBT1g
Just arrays containing text fields in UIElements just not working at all
What the....??
That's so broken, that should be a high priority bug... right... right??
You would think so
I never even saw that it was in preview, was it ever a public preview? I will have to check it out!
No preview
I would have thought that they would have tbh.
The needle guys pick up on these packages a little earlier than the notes do so if you do want to find stuff early I'd recommend their server https://discord.gg/8ubk9xqE
Hahaha
will changes to a scriptable object will persist in Build ?
( when u reopen the app , would it have the same data as the last play session )
Nope
I haven't noticed this before - is this a 2022-specific bug?
Look at the issue tracker link and it will tell you that
Hadn't scrolled back that far 👍 - that's a relief
is odin editor any use?
If you want low effort, decent editors sure
But you'll have to spend time learning it
If you already own it (e.g. from Humble Bundle) then it can be quite a timesaver. Whether it's worth the money if you don't is more dubious.
guys why my editor is not have unity intalisions?
sorry but i dobt understand your english
but if you are talking about the code editor: you need to go tu unity preferences and select it in the external tools
When I run undo on this code it brings the file back but how do I make undo include all the operations in this function? I.E. When I control+Z the file comes back but the list is still missing the node ect. ```
public void RemoveNode(SO_DialogNode queuedNode)
{
foreach (SO_DialogNode node in nodes)
{
node.RemoveChild(queuedNode.name);
}
nodes.Remove(queuedNode);
CreateLookup();
Undo.DestroyObjectImmediate(queuedNode);
}
You do Undo.RegisterCompleteObjectUndo(..) at the start of the method.
Thank you.
You most likely want to Undo.IncrementGroup()(Or similar name) at the end so that if you remove multiple nodes one right after another they will be separate operations.
Good call.
Anyone know if there's a way to get the editor to respect visual studios "exclude from project" setting on source files? I've been digging a bit but can't seem to find anything about it.. not sure I want to roll my own editor extension yet
I have some source files that I want access to as I refactor, but don't want compiled (since obviously the refactor is breaking those files as well)
<ItemGroup>
<Compile Include="Assets\Archived\Scripts\ARCHIVED_GameManager.cs" />
... x 10,000 ...
Essentially getting unity to read/use this Compile group in the Assembly-CSharp.csproj file..
Not as far as I know; the "Hidden Assets" folders at the bottom of https://docs.unity3d.com/Manual/SpecialFolders.html is the only way I know to have files in the assets folder that aren't imported. I don't know whether the integration will include those files in solutions, though; it would make sense if it didn't?
Ah, interesting. I could try just making an .Archived folder under scripts
success!
That is .. lovely. Thanks @icy merlin. So, if you want to have a script (that's not mass-commented out) you can just create an .Archived folder (note the dot) and then exclude the items in Visual Studio. VS won't compile them and unity won't import them (and hence, won't write them to the .csproj file) and voila, you can keep that old nasty smelly code around and copy and paste it to your shiny new codebase however you please
done but in vscode my editor does not work?
try clicking the relode files button
@onyx harness So as I do every couple of weeks/months I went back try and make a window/system for editing the menus from the editor. I stopped last time because the 2020.3 and 2021.1 menu system was so different it didn't seem worth it. But I decided to take another crack at it for only the latest 2021.2.
2021.1 has the nice Menu.AddExistingMenuItem(..) method, so I try to use it and find that they removed it in 2021.2, and as far as I can tell there is no replacement for it...
The whole ModeService internals have been rewritten again too which is where it was being used! What is a guy to do!
Why can't they just keep their internals stable, I'm trying to use them here! 😛
Lol, it's a running gag among Unity dev I guess :D
@gloomy chasm But why dont you use AddMenuItem?
That requires me to have the action and the validation logic.
To be honest, I dont even know what does AddExisting
What I think it does is move it, but maybe not. (Doesn't matter any more I guess 😛 )
They did? Where?
Type : public sealed class UnityEditor.Menu
5.0.0f4 ⟩ 2022.1.0a15
Unity Doc
Event : internal static menuChanged { add; remove; }
2022.1.0a7 ⟩ 2022.1.0a15
GitHub Source
Well that would be ideal wouldn't it, but again I some how need to get my hands on the logic that they call.
I wonder if that means they rewrote the ModeService a third time 😛
In I think 2020.1 they added a more limited version of the editor called "safe mode" for when you open a Unity project when there are compile errors. ModeService handles that, but is capable of having any number of modes.
Oh I see
And as far as why? Idk, why did they rewrite it from 2021.1 to 2021.2?
I am trying to make a custom property drawer for IPAddress and I have this code just to test but nothing shows up in the editor when i have a field of the IPAddress type.
[CustomPropertyDrawer(typeof(IPAddress))]
public class IPAddressDrawer : PropertyDrawer {
public override VisualElement CreatePropertyGUI(SerializedProperty property) {
var container = new VisualElement();
container.Add(new Label("Test"));
return container;
}
}```
It's in an editor window, if i change it to a struct i made just to test it works properly, System.Net.IPAddress is serializable and it is used properly in both cases, do you know why this isn't drawing anything?
or could you point me to an already completed implementation of an ip address property drawer
im also very new to editor extensions so it could be something very stupid
Not sure, but probably the Serializable is not the same between native C# & Unity
Does it show up normally if you dn't even use a PropertyDrawer?
no, nothing shows if i dont use a property drawer, but i figure thats because unity doesnt know how to handle an IPAddress
i just checked and its just System.Serializable
should be the same, putting that on a struct makes it work in unity
Struct made by you
yes
As a little tip, if you put anything in a normal way in a public field, and it doesn't show up in the Inspector
It just mean it is not serializable
(In the Unity way)
but isnt the purpose of PropertyDrawers to make something serializable in the unity way?
Nope, I understand it can be confusing at first
PropertyDrawer does not make things serializable
It allows to draw on something serializable
is there a way to make something unity serializable? maybe using extension methods or something
i suppose... could i subclass it?
if you can
I'll just make a struct for an ip address, then write a drawer that makes it look like an ip address
Yes
how would I limit the integers?
yeah
oh and should i use imgui or uielements
The future is in UIToolkit
uielements seems closer to other gui systems ive used
I'm a bit old & outdated
uitoolkit?
UI Toolkit is the new name of UI Element
Yes, I know, this is confusing
just a new name
Unity loves that, confuse people
unity is just a big rolling ball of features that are constantly either deprecated or in preview
i swear
Welcome 🙂
so now i have this
public override VisualElement CreatePropertyGUI(SerializedProperty property) {
var container = new VisualElement();
container.Add(new Label("Test"));
return container;
}```
and it's showing up as this in the editor
Do I need to enable ui toolkit somewhere?
show me the complete class
UIToolkit Property Drawers require the editor to use UIToolkit, right now that means it requires a custom Editor. If you don't want to do that you will need to use the IMGUI implementation instead of UIToolkit
You can't do UI from a PD? O_O
then why is there literally an example of a propertydrawer using ui toolkit on the docs
this is such a mess
ok thank you
ill just use imgui ig
Not with UITK. That is because the default editor for a component uses IMGUI to draw the fields.
is there no way to switch it?
ok ok fine, imgui it is
hate this for me tbh
there goes 30 mins lmao
There is-ish. You can enter internal mode to switch to it. Or you can create a custom editor for all MonoBehaviours (There are several online that do this already)
could you point me towards that? imgui really seems so complicated to me
The internal mode or the custom editor?
Here is one. You should be able to just copy paste it in it looks like.
https://github.com/pirhosoft/PiRhoUtilities/blob/master/Assets/PiRhoUtilities/Editor/DefaultEditor.cs
What? It should...
I think in your case, I would just use a string, make PD on it to customize it the way you want. And then IG I convert it to IPAddress
can you use pds for validation?
Yes
...would you happen to have resources or something to point me towards for that?
In a PD you draw everything yourself, therefore using IMGUI for validation is quite straight
var newValue = TextField()
If (editor detects a change)
{
// validate
}
nothing fancy in there
For UITK you would
field.RegisterValueChange(evt => {
if (evt.newValue /*valudation*/)
{
// whatever...
}
};
ty both again!
i ended up using uitk and I have this so far. Would you happen to know how to make the first octet line up with the port field?
Sorry for the delay, you just added them to a container VisualElement and set its FlexDirection style to row
could I dm you? the codes gotten a bit complex and i dont want to send everything here
I guess so, but it should be pretty easy to do.
So I'm doing some hacky serialization of ScriptableObjects. I create instances during edit mode and serialize them. After seralization, the instance IDs are 0 in the serialized file. Is there any gimmick with ScriptableObject instances created from code during edit mode that I should be aware of? I assume the garbage collector for some reason disposes of the instances since they don't exist in any files?
You probably need to craete them as files
Non file backed SOs are only really supported (iirc) if they're on a component in a scene
If that GO becomes a prefab it breaks
It is a long shot, but does anyone happen to know of a way to prevent a window (custom or non custom) from updating its layout?
What I want to do is to animate an editor window to look like it is expanding out (0 width > final width).
Thanks!
is there an easy way to display attributes based on a selected enum or similar in the inspector? i only kinda recently learned about the whole serialization thing.
i have prefabs that have different "actions" such as "attack" or "heal", both of which will have different attributes and i don't want to list attack stuff if the action is a heal for example.
By attribute, you mean field?
more or less
You can use that if you want:
https://gist.github.com/Mikilo/8cb969a50a1eac87c9500d4f9f181324/edit
thassa lotta lines
There is no native showif attribute in Unity
would be cool... thanks tho, it's a good reference
You use it like this:
public bool blabla;
[ShowIf(nameof(blabla), Op.Equals, true)]
public string foo;
Do i just put the files in an "Editor" folder and use the tag wherever?
Yep
dope, okay
does it compile?
I guess yeah, ShowIfAttribute is from NGTools namespace
you need it
or put it in your namespace
right, makes sense
i might need some clarification on the usage, despite the example provided.
i have my own enum which is either "Attack" or "Heal". How do I show something using this if i have one or the other selected?
The 3rd argument
instead of true, you put Attack or Heal
Read the attribute humanly
Show if "blabla" is {Equals} to {true}
right. im just getting an exception, but i think that's cause of the first argument im using.
public ActionType actionType;
[NGTools.ShowIf("actiontype?", NGTools.Op.Equals, ActionType.Attack)]
public AttackCharged attackCharged;
public int saveDC;
public bool needsRecharge;
im not sure what to put into the first field cause i can't use actionType in it
what is "?"
just a placeholder
But it is supposed to be the exact name of the field
nameof(actionType)?
actionType doesn't work, cause it's not a string, or something. tostring doesn't do anything
nameof gives me an index out of range exception.
hrm. i'll try to restart unity. it's not working with a regular bool either using the same example
What version of unity are you using?
the only plugins i have is DOTween
Well show me the logs
might sound dumb but which logs?
I know what is a OOR exception 🙂
lmao my bad
the class itself is used as an array, since a card can have a variable number of actions
Totally possible that ShowIf won't work for nested stuff
It works correctly for rooted fields
but for array in class, in field, in whatever, a PropertyDrawer is gonna have a hard time to correctly display
bleh
also, keeping that kind of information is not a good habit if you seek for help
Just remember that
i didn't figure it was that important
Like the callstack, I see 🙂
It's fine it's fine, but remember, to less we have to ask you back, the faster you're gonna get your solution 🙂
Is there an editor window style that is a combination of the normal style and the popup style, meaning that it is the normal window but with the editor, aka the popup style but with a border and shadow?
It doesn't have a dropshadow or border
First is popup second is normal.
That is an aux window or maybe utility.
I mean winow.ShowPopup()
window.ShowDropdown(..) is the style I want. But it closes on losing focus which is not what I want.
You can always draw a border yourself if that's the biggest issue
I need to work for other windows than my own unfortunately.
Can someone tell why it's giving me an error?
install the developer pack it's asking you to install?
This one?
I would assume so
Okay
Does anyone know why I'd get this error when trying to attach an MB from an editor assembly to an object? In my test project I could create an object tagged "EditorOnly" and it just worked.
Is this something new in 2021 maybe?
I tested in 2020
Yeah, this is straight up broken in 2021 it seems
Why should you be able to attach a script from an editor assembly?
I personally don't remember that ever being a thing
Did you add the editoronly tag?
Yes
It worked for me in 2020.3.18 I think. I might need to double check now
But I'm pretty sure it just attached
Maybe I'm confused
The script must derive from mono behaviour. I'm pretty sure you got the wrong script
It's a MonoBehaviour in an editor assembly
I don't know your project. But just move it out of the editor assembly and test
pretty sure you've never been able to do this, and need to use the editor preprocessor
Hm, okay. I must have done something wrong in testing then
Not clear how the editor preprocessor could help though.
If I'm not permitted to add the script at all
You add the editor preprocessor while it's in a runtime assembly, so it's stripped from the build
Ah gotcha. I can exclude the assembly from the build?
The scene is not intended to be included in a build so it's okay
Script and/or assembly
Not that I know of, but you can exclude the script
Separate assembly definition can exclude build
I think it would need to be marked editor only for that?
Which brings me back to the beginning
I've never used the preprocessor before but it sounds like it could achieve what I want
You just put #if UNITY_EDITOR at the top of your script and #endif at the bottom
The real hack is to add the assembly definition to a platform you never build for
then it's runtime but practically editor-only 😄
and hope it doesn't freak out when you make a build
Meh, sounds hacky, what if you at some point do want to build for that platform?
It's just not what I'm looking for.
Choose one you never will?
But it'll work
Not really.
It will
It's a scene of example usages of a library that is distributed with the package. Users end up with the example assembly in their builds.
That will exclude specific code from compilation.
I want to exclude a DLL from being included in a build.
You were talking about scripts though
Examples are usually distributed in .unitypackages in packages, I imagine for that reason
You're right @visual stag perhaps I hadn't applied the asmdef definition or something because it's not working now. mb
Yeah, or not distributed at all (which would be my preference). I'm just trying to find a solution for this open source package which satisfies the maintainer and strips the DLL from build.
I just did some googling to see if there was a solution, I guess I misinterpreted that thread.
Yeah, so script assemblies get turned into DLLs when you build.
"scripts" == C# files
It's much nicer in 2019.1+ apparently, you don't even need to unitypackage it https://docs.unity3d.com/Manual/cus-samples.html
No. Code == C# files. Scripts == unity scripts
Oh that's nice. So they'll be treated as separate assemblies that are optionally imported? @visual stag
I could play with that, it sounds good.
I'm not sure what you mean sorry.
They're not imported at all (appending a folder with ~ will exclude it from being imported), and when you click the sample in the package manager it'll throw the referenced subfolder into the Assets directory
Yeah, that's great. This could well be the answer. Thanks @visual stag
A dll is not a script anymore
Sorry if I confused you!
@visual stag FYI I tried moving the asmdef into the "samples" folder and it's still automatically included in the build even when not imported. Was a good thought though!
Samples~?
I can try renaming it, I wasn't sure what the ~ meant there
It's being picked up by the package manager as is
During the import process, Unity ignores the following files and folders in the Assets folder (or a sub-folder within it):
Files and folders which end with ‘~’.
Oh nice!
Ah, cool. Yes that works but it also hides it from the development project which is not ideal. Perhaps we can achieve something with a symlink from the main project.
just rename the folder when publishing, you can even automate that
The thing is that it's possible to actually depend on a subdirectory of a repo at any commit, so there is not necessarily a divide between publish and commit, esp. if someone needs to grab a hotfix or something.
FYI the symlink is working perfectly so far!
I just link from Assets/Samples to Assets/ThePackage/Samples~
And unity only sees the files under Samples instead of Samples~ (which it ignores)
👌
A git hook with a rename might work too, but this feels more elegant
Does anyone know how to make a Dropdown field using UIElements, on version 2020.3?
I think you may need to roll your own using DropdownMenu.
@gloomy chasm I thought that is only available from 2021.1
DropdownField is, but not DropdownMenu
Thanks, ill take a look
private static void HandleHierarchyWindowItemOnGUI(int instanceID, Rect selectionRect)
{
//HandleBackground(instanceID, selectionRect);
Color fontColor = Color.red;
Object obj = EditorUtility.InstanceIDToObject(instanceID);
if (obj != null)
{
var prefabType = PrefabUtility.GetPrefabInstanceStatus(obj);
if (prefabType == PrefabInstanceStatus.Connected)
{
if (Selection.instanceIDs.Contains(instanceID))
{
fontColor = Color.white;
}
Rect offsetRect = new Rect(selectionRect.position + offset, selectionRect.size);
EditorGUI.LabelField(offsetRect, obj.name, new GUIStyle()
{
normal = new GUIStyleState() { textColor = fontColor },
//fontStyle = FontStyle.Bold
}
);
}
}
}```
I am attempting to edit someone else's code to highlight certain game objects in my hierarchy.
The above code works to change the font color of all Instanced Prefabs to red.
I would like to change it to be able to change any prefab that contains specific components to specific colors.
current functionality visualized
I can't seem to figure out how to detect if the thing is the thing I want it to be, I tried this but it returned null:
GameObject prefabtype2 = PrefabUtility.GetNearestPrefabInstanceRoot(obj);
if (prefabtype2.TryGetComponent(out MrManPlayerCharacter mrMan))
{
// code here
}```
prefab.utiltiy has a ton of methods but I cant seem to find one that returns what I need to be able to test if thing is/contains thing that Im looking for
I can get this far, but when I try to do anything with prefabtype2, the console gets spammed with hundreds of errors per frame
I got it to work, scrtch all the above
private static Vector2 offset = new Vector2(18f, 0);
static CustomHierarchy()
{
EditorApplication.hierarchyWindowItemOnGUI += HandleHierarchyWindowItemOnGUI;
}
private static void HandleHierarchyWindowItemOnGUI(int instanceID, Rect selectionRect)
{
//HandleBackground(instanceID, selectionRect);
Color fontColor = Color.red;
Object obj = EditorUtility.InstanceIDToObject(instanceID);
if (obj != null)
{
GameObject prefabtype2 = PrefabUtility.GetNearestPrefabInstanceRoot(obj);
//Debug.Log(prefabtype2);
if (prefabtype2 != null)
{
if (prefabtype2.TryGetComponent(out MrManPlayerCharacter mrMan))
{
ColorThisElement(Color.yellow, instanceID, selectionRect, obj);
}
}
}
}
has this effect
I've been working on a sidebar like VS, Rider, UE5 etc.
I'm pretty with how it is going.
I feel pretty clever for the resizing because the window is a popup window I added a UITK element to the window that you drag to resize (only in the 'wide' direction of the window)
Anyone has/know good tutorial on how to simulate update in editor,
Is it possible to detect keypresses in an editor window class when the window is closed?
Or is it possible to have an editor class that persists the whole time the editor is open?
I basically want to store a reference to a GameObject in the scene and either toggle its active state or visible state on a keypress
Why not add a gameobject+component to the scene with the hideflag HideAndDontSave.
Wasn't aware of that flag, I guess that would work. It'd be nice to not have to do that every time I change scenes though.
How are you planning on getting the GameObject that you want to reference?
You would need to get that reference each scene change anyway right?
Thinking out loud here, I would open an Editor Window and click a button that would store a reference to the currently selected gameobject in the hierarchy. With that gameobject+component I'd have to add it everytime I change scenes
Rather than just opening a window
Why so manual? Why not just add a listener to the change scene event and get the gameobject then and add the gameobject+component?
Okay yeah that would work, I could have a custom window with that button and when its pressed it would get the selected gameobject and create that gameobject+component with HideAndDontSave or update it if it already exists.
Thanks as always 🙂
I have a monobehaviour with a list of a Serializable object, and that object also has a list of serializable objects, even If set the root monobehaviour dirty, the changes to the sub objects fields aren't saved in my editor script. Any special thing to do for this case ?
Going to need to see both the data code and the editor code. There are just too many places that something could be missed to be able to tell just from this.
You can imagine monobehaviour class A, has a list of class B (serializable), B has a list of class C (serializable).
- I double for loop through both lists and assign a vector3 field on class C.
- EditorUtility.SetDirty(object A)
I know there are ways to use the serialization wrappers for unity objects etc, can't find docs on how to propertly save custom classes marked as Serializable - when they are child objects or in lists.
No, that sounds like it would work. Again if you want show the code I could tell you better.
It should work even if I set the values using raw c# and not the special serialized wrappers? SerializedObject / SerializedProperty - but those can't be used since thy require Unity objects.
Yes, though it is much better to use SerializedProperties if you can
class A is unity object though....
Yea, but the field i'm after is on a non unity object. I must be missing something simple. Will keep digging.
Thanks for the help.
You create a SerializedObject for class A then use FindProperty(..) and FindReletiveProperty(..) to get the serializedProperties of the sub fields.
Ah, I'll give that a try, thanks alot!
This might not be editor-specific, but I have a editor script that logs pretty much whenever you do anything (like delete a file, move an asset, rename a object in the hierarchy, etc), is it bad to send a System.IO.WriteAllText(...) to every time anything is done, or should I maybe "queue" a bunch of messages then write the whole queue at once? Im just wondering if I move like 20 files at once, thats 20 "save" calls to a text file ina short time, is that "bad" to constantly write like that or is it better to do it periodically/as infrequent as possible?
20 would be insignificant, but you probably ought to do it a better/different way - perhaps by keeping the file handle, opening it, writing as events come in, disposing it as your application closes, and periodically flushing it (every five minutes? one minute? whatever you feel is appropriate). Alternatively, not making 20 save calls, but instead making a "saveOperations(list<operation>)" kind of interface or usage pattern.
I see - what would periodically flushing it help with? I dont think I ever used it with filestream before, since most times I never needed to actively keep a file open to write to it
Also, im guessing with the "saveOperations(List<T>)" approach, would be kind of like "once the list reaches x count, write to stream and clear operations list"?
Mostly just in case your application crashes it doesn't bring the entire buffer with it. You also probably want to check the file from time to time (while the app is running)
Ah I see, ill try that out - thanks for the guidance :)
seems like unity console window adds it
what i did was : Start() { Debug.Log( Application.consoleLogPath ); }
u can subscribe to the event and add the time manually tho :
Application.logMessageReceived += delegate (string condition, string stackTrace, LogType type )
{
_myTextField.text += condition;
};
also the console has this if that's what u were asking for
then use logMessageReceived and add your own
Hi.
How do I add a list like this in a custom inspector?