#↕️┃editor-extensions
1 messages · Page 15 of 1
have a bunch of fields in custom window, for some reason since most of other controls are custom the active "selection" is stuck on a last used EditorLayout.Toggle, clicking anywhere doesnt drop the focus from it, so pressing space toggles it, for example
escape doesnt drop focus either
tried ```cs
if(Event.current.type == EventType.MouseDown)
{
EditorGUIUtility.hotControl = 0;
GUIUtility.hotControl = 0;
}
at the end of onGui
fixed
GUI.FocusControl(null);
In PrefabUtility class there are so many static methods for applying changes made to a prefab that I dont know which one to use.
If I want to apply ANY changes made to that game object or its children on ANY component, which method should I use to apply them?
Easiest way is to use the scope for editing it https://docs.unity3d.com/ScriptReference/PrefabUtility.EditPrefabContentsScope.html
But otherwise you want this one iirc https://docs.unity3d.com/ScriptReference/PrefabUtility.SaveAsPrefabAsset.html
And here is a thread all about it https://forum.unity.com/threads/how-do-i-edit-prefabs-from-scripts.685711/
can someone explain to me why this piece of code does not import the normal map correctly cs private void OnPostprocessTexture(Texture2D texture) { TextureImporter importer = (TextureImporter)assetImporter; if (importer.importSettingsMissing) { string textureName = System.IO.Path.GetFileNameWithoutExtension(importer.assetPath); if (textureName.Contains("_Normal")) importer.textureType = TextureImporterType.NormalMap; if (textureName.Contains("LitMask")) importer.sRGBTexture = false; EditorUtility.SetDirty(importer); importer.SaveAndReimport(); } }
What do you mean "correctly"
it is treated by the shaders as if it is not a normal map
but the gui in the editor says it is
this is the result when I first drag the normal map into the project and use it
wait what
ok
I tought that if (importer.importSettingsMissing) was for the case of initial import
It works but the question is why does it touch .shadergraphs with Normal in the name too
Wait, it does? That is so strange...
well
it did not chage anything
but then plastic is like
ooo this is checked out
even tough it says files are identical LOL
Amazing
I need to maintain Action subscriptions within the context of the Editor and/or PlayMode. The issue right now is that when Unity reloads, the ScriptableObjects lose their Action subscribers, which are POCOs stored in other UnityObjects (other MBs or SOs). The POCO has a SO property that, when setting, subscribes to its Action. The reference is kept, but there's not real way to trigger the resubscription on start/reload. What's the cleverest, most optimal way to resubscribe on Unity start/reload?
When you say the reference is kept in the POCOs, do you mean it's being serialized by Unity?
Maybe a UnityEvent would be better for your use case
Can you add persistent listeners to a UnityEvent through code? There's no method for it in the type, but maybe there is a secret utility method for it?
Yup, that
My suggestion was going to be to use ISerializationCallbackReceiver on the POCOs, assuming they are serialized by Unity, and use OnAfterDeserialize to subscribe again.
Both solutions require the POCOs to be serialized by Unity.
I am actually using both Actions and UnityEvents. I want to account for other workflows
Interesting. I have to check how this is applied. I'm not very familiar with using UnityEvents
UnityEvent is basically a serializable System.Action. Which sounds like what you want
I think this might be a good solution. WIll test
If the goal is ultimately to add a System.Action to a delegate/event, then you would have to wrap the UnityActions you get from the UnityEvent in a System.Action, since annoyingly delegates cannot be converted between each other, even if their signatures match.
Can UnityEvent even serialize an instance method listener on a serialized POCO? I've never seen that in the editor, you always have to reference a UnityEngine.Object and then a method on said object, or reference a static method.
This would suggest no:
https://github.com/Unity-Technologies/UnityCsReference/blob/e7d9de5f09767c3320b6dab51bc2c2dc90447786/Runtime/Export/UnityEvent/UnityEvent.cs#L964
"Could not register callback {0} on {1}. The class {2} does not derive from UnityEngine.Object"
Hello. I wonder about initialization of GUIStyles, and the adding of custom GUIStyles, when facilitating for multiple instances of the same EditorWindow.
In this static version, it uses a static class Style with lazy initialization of GUIStyle, so that they are initialized via OnGUI
https://gist.github.com/Rovsau/3d7982a235446fa3ea2b13e50005f726
In the new version I am forced to use a null check property getter
public GUIStyle MainArea
{
get
{
if (_mainArea == null)
{
_mainArea = GetDefaultStyle_MainArea();
}
return _mainArea;
}
}
And for this purpose, that is fine.
But how would I go about allowing people to add their own custom GUIStyles?
make it virtual
Hm. How would that work? Can you elaborate?
Depends on the implementation, but if the user can make a derived class, making the property virtual makes it possible to overwrite it in the derived class. You can also make it so that the _mainArea is a SerializeField and just edit that directly
I sort of am confused by the way you phrased that 😛
The way my system works is that the Listeners are MBs with an UnityEvent field. The event raiser is a SO. The listeners inject themselves into the event raiser SO. The event raiser is set on the SOs that then use them.
I guess hotswapping GUIStyle could work, but I want to create an API with a wrapper, so that people can write:
var window = SelectAssetWindow.GetNewWindow(...)
window.SetWindowTitle("My Window Title");
window.SetStyle_Button(myCustomGUIStyle); // But this is tricky; where is myCustomGUIStyle initialized?
window.Open();
Maybe I can pass in a method 🤔
Or pass a Settings/Data SO that the user can modify and have it referenced (with lazy instantiation)
What I mean is that this would cause an error:
public class MyScript : MonoBehaviour
{
public UnityEvent myEvent;
public MyPOCO myPoco;
private void Awake()
{
UnityEventTools.AddPersistentListener(myEvent, myPoco.OnEvent);
}
[Serializable]
public class MyPOCO
{
public void OnEvent() {}
}
}
But this would be fine:
public class MyScript : MonoBehaviour
{
public UnityEvent myEvent;
private void Awake()
{
UnityEventTools.AddPersistentListener(myEvent, OnEvent);
}
public void OnEvent() {}
}
And that's because UnityEvent serializes listeners by pairing a UnityEngine.Object instance with a method name. In the case of MyPOCO, it's not a UnityEngine.Object, so UnityEvent can't serialize it as the instance.
That will probably work.
I've been contemplating to also implement making multiple asset instances, which could be a requirement to modify GUIStyle.
Thanks for the input 👍
Where are the POCOs?
They store UnityEventRaiserSO, plain TValue or SO<TValue>. They make the logic connection between the Values and the Events. Sort of like turning any value/struct/class type into a more powerfull entity with more features. I can't say more :c
If you only need to add static listener methods, you can use UnityEvent to serialize them. If you need to serialize instance methods, then as long as those methods are defined in a class that derives from UnityEngine.Object, i.e. MonoBehaviour or ScriptableObject, then you're also fine. But if the instance method is defined on a POCO that you are serializing in a MonoBehaviour or ScriptableObject, then UnityEvent cannot serialize that method because it doesn't know how to find that method when deserializing.
anyone seen this one before ? ( double clicking the err message opens the object inspector )
did you try to wrap it with via Create.Delegate? I'm assuming you already did that due for a fact you're using persistent listener anyway
ah didn't see the example you posted.. ignore that
@gloomy chasm do you know what api to use to create something like this in scene-view edit mode?
It's presumably just all Handles
ah yeah that makes sense, thanks! 👍
how does marking as dirty work?
like in unity, all i know is that you need to do it when working with scripted objects with an editor script
wait, nevermind i got it
Yeah as Vertx said, just handles. Specifically Handles.CircleHandleCap for the circles, Handles.DrawPolyLines for the main line, and then probably just Handles.DrawPolyLine for each arrow (might look at DrawLines instead idk atm)
Doesn't really matter, polylines and lines are effectively the same
Just need to do a little math to get the angles (and points) for the arrows
Yeah it all just GL lines internally iirc. One might be more performant than the other, but probably doesn't really matter.
aight, thanks a lot folks 👍
How can a PropertyField's value be reverted on RegisterCallbackValueChanged? Other fields pass in ChangeEvent<TValue> which implement ChangeEvent<TValue>.newValue and ChangeEvent<TValue>.previousValue.
you mean similar to undo?
I guess that could work
it should work ootb
ChangeEvent<TValue>.previousValue is just getting the backing-field, nothing special
Why do my UIToolkit based custom attributes work in Unity 2021 but not unity 2022?
I thought 2022 is suppposed to support UIToolkit more and yet it seems to be the other way around.
This is incredible frustrating because now i can't upgrade to 2022
Am i not supposed to override CreatePropertyGUI in the property drawer?
Is the 2022 version the LTS version?
Yes 2022.3.1f1
I've had this problem for about 10 months now but had other things to work on and now i that i've come back to the issue after the LTS release it's still a problem
Hello,
I am doing an editor script, just to make the header bigger, with background colors, etc...
Can somebody help me with this error :
'CustomHeaderDrawer' is missing the class attribute 'ExtensionOfNativeClass'!
I tried to add this:
[ExtensionOfNativeClass(typeof(PropertyDrawer))]
but apparently i can't access it due to protection level
The code ```C#
using UnityEditor;
using UnityEngine;
[CustomPropertyDrawer(typeof(CustomHeaderAttribute), true)]
public class CustomHeaderDrawer : PropertyDrawer
{
private const int HeaderHeight = 30;
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
return base.GetPropertyHeight(property, label) + HeaderHeight;
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
CustomHeaderAttribute customHeaderAttribute = (CustomHeaderAttribute)attribute;
Rect headerPosition = new Rect(position.x+5f, position.y, position.width-10f, HeaderHeight);
EditorGUI.DrawRect(headerPosition, customHeaderAttribute.BackgroundColor);
GUIStyle headerStyle = new GUIStyle(EditorStyles.boldLabel)
{
fontSize = (int)GetHeaderFontSize(),
fontStyle = FontStyle.Bold,
alignment = TextAnchor.MiddleCenter,
normal = { textColor = customHeaderAttribute.FontColor }
};
EditorGUI.LabelField(headerPosition, customHeaderAttribute.HeaderText.ToUpper(), headerStyle);
Rect propertyPosition = new Rect(position.x, position.y + HeaderHeight, position.width, position.height + HeaderHeight);
EditorGUI.BeginProperty(propertyPosition, new GUIContent(property.displayName), property);
EditorGUI.PropertyField(propertyPosition, property, new GUIContent(property.displayName), true);
EditorGUI.EndProperty();
}
private float GetHeaderFontSize()
{
float maxWidth = EditorGUIUtility.currentViewWidth;
float baseFontSize = 1f;
float maxFontSize = 30f;
float fontSize = Mathf.Lerp(baseFontSize, maxFontSize, maxWidth / 1000f); // Adjust the divisor to control the scaling factor
return Mathf.RoundToInt(fontSize);
}
}```
@trim pollen try solutions here: https://forum.unity.com/threads/class-is-missing-the-class-attribute-extensionofnativeclass.1295823/
looks like regenerating your library folder and/or deleting the file meta works
Well that fixed it ^^
Thanks a lot !
Oh strange, now i'm getting the NoGUIImplemented in the insepctor in 2021 and 2022 in this new small scale test of an attribute i just tried.
Can anyone see something i'm doing wrong?
The TestShowHide.cs file goes on a GameObject and then the ShowHideAttribute.cs script is the attribute itself
Try making a custom Editor for TestShowHide using
public override VisualElement CreateInspectorGUI()
{
var root = new VisualElement();
InspectorElement.FillDefaultInspector(root, serializedObject, this);
return root;
}```
Or just make a custom editor for MonoBehaviour where you make editorForChildClasses true. I think this also works.
This works but i don't understand why there is a need to create a custom editor for the Attribute property drawer to work, because now if i wanted to use that ShowHideAttribute on a field in another script i would need to create a custom editor for the new script, which wouldn't make the atttribute very easy to use for others
I'm not sure what editorForChildClasses is but i'll look into that
Because in 2021, the default inspector is IMGUI
that changes in 2022, where the default inspector becomes UIToolkit
Right so in 2022 attributes just don't work on thier own?
Do you mean in 2021?
In 2021, if you are making custom PropertyDrawers using UIToolkit, I guess not.
[CustomEditor(typeof(MonoBehaviour), editorForChildClasses:true)]
public class MonoBehaviourEditor: Editor```
No well what i mean is that before UIToolkit/UIElements and visual element based UI you just had to create a property attribute and a property drawer and the drawer would use OnGUI(Rect position, SerializedProperty property, GUIContent label) to handle what gets shown in place of your original variable. So i thought the only difference with UIToolkit would be that in the property drawer you use public override VisualElement CreatePropertyGUI(SerializedProperty property) instead of OnGUI because that's visual element based. But it's not really a replacement if you have to go through the extra step of creating a custom inspector for every script that uses an attrubute just for it to work
same issue unfortunately
Because i've been creating a ton of custom editors and windows for the company i work at over the last year to extend finctionaliy but man i am still struggling to get attributes to work properly with UIToolkit / Visual Elements
If you use 2022.2+, the default inspector is UIToolkit. You shouldn't have to create custom Editors for custom PropertyDrawers that are using UIToolkit.
i know that's the idea of how it's supposed to work, but i'm using 2022.3 LTS and it doesn't work unless i create a custom editor like you suggested earlier with this:
[CustomEditor(typeof(TestShowHide))]
public class TestShowHideEditor : Editor
{
public override VisualElement CreateInspectorGUI()
{
var root = new VisualElement();
InspectorElement.FillDefaultInspector(root, serializedObject, this);
return root;
}
} ```
Now when i tried that it worked but that's not a viable option if i have to do that for every script
[CustomEditor(typeof(MonoBehaviour), true)]
public class MonoBehaviourEditor : UnityEditor.Editor
{
public override VisualElement CreateInspectorGUI()
{
var root = new VisualElement();
var itShouldWorkThoLabel = new Label("It should work tho");
InspectorElement.FillDefaultInspector(root, serializedObject, this);
root.Insert(0, itShouldWorkThoLabel);
return root;
}
}```
I'm in 2022.3 LTS
Oh yeah that works
I can confirm that attributes should work by default in 2022.3.
I made some for a client's project
So what you're saying is you don't have to create a custom inspector for your property drawer to work, and what i'm experiencing is actually a bug and a version issue?
Yes it should work. If it is a large project, there could be an asset that is doing a default editor like what was shown above, but for IMGUI.
Yeah well ideally i would like to support 2021 and 2022 as i'm slowly beginning to phase out 2020 now at my job so i'm not too worried that far back. But the problem is that it's not working by default for me as it should be with 2022.3 LTS
You could open the UIToolkit debugger window, and look at the editor of the component in the inspector to see what is drawing it.
But i can add script defines later to support different ways of doing it for different versions once i figure out how to just get it working as it should in 2022
Otherwise, I would try it in a fresh project. But yes, it should be working so if it does not work in a fresh project, it is a bug.
Ok i'll give that a shot later. My laptop is about to die though and there's a power outage in my area so i'll have to continue later when i'm charged up. Thanks so much for all the help guys i'll ask you guys again later for further help if that's cool
Sure thing!
EditorWindow partial class
I have a public static Open() method which uses GetWindow.
In the most simple form, it looks like this:
public static void Open()
{
_window = GetWindow<SelectAssetWindow>(windowTitle);
if (_isOpen)
{
_window.Close();
}
else
{
_isOpen = true;
// here I initialize private static fields
_window.Show(); // This is apparently redundant
}
}
Sidenote: Until now, I didn't realize .Show() was being redundant, because it is already called with GetWindow<T>().
After that, the script initializes other things via OnEnable(), and is then shown in OnGUI. Normal stuff.
This all works, but if I make my EditorWindow derived class a partial class, the order of initialization is different.
OnEnable then runs before the static fields have any values, and throw null reference exceptions.
Is this expected behavior? Is there any method to the madness?
Ultimately, I will make my own custom Get/CreateWindow() method, to allow initializing values before .Show() is called.
Idk, how Unity handles Partial when it comes to UnityEngine.Objects but simply using HasOpenInstance instead of GetWindow should be what you are doing and would solve your issue https://docs.unity3d.com/ScriptReference/EditorWindow.HasOpenInstances.html
PS: By making it a partial class, I simply included stuff that isn't used.
I am aware OnGUI etc must be in the main file.
Erh, I did misead a bit
what should be initialized before Show?
No wait, I was right
values passed into Open() that end up in static fields
I don't think HasOpenInstance will help me, as I am aiming for multiple instances simultaneously.
Plus, I already have a solution.
The question is why it behaves this way; if it can be explained, or should be reported as a bug.
I think this would solve it... maybe...
public static void Open()
{
if (EditorWindow.HasOpenInstance<MyWindow>())
{
EditorWindow.GetWindow<MyWindow>().Close();
}
else
{
var window = EditorWindow.CreateInstance<MyWindow>();
// Initalize...
window.Show();
}
}
I already have a solution. Please do not bloat away.
The only question is if this behavior is to be expected.
alright, just gonna yeet away
Alrighty. 🙂
Well about the behavior. I suspect it would be because of the way Unity creates a C++ instance of the object. But yeah, I would say 'bug'.
I do feel like I remember reading somewhere that Unity objects were not meant to be used with partial, but I could be mistaken as it was a while ago, and I am not 100% sure
Alright, thanks for that insight.
From what I read, they encourage using partials, but I had to learn later that all the Unity-related calls must be in the main file.
The other partials can be in files with different names.
(I haven't tested this with a subfolder and an identical name)
From what I'm observing, the current code works if the script is not partial.
But once it becomes a partial, and a second partial instance exists, it starts throwing null reference exceptions, because the static field is null.
I'm not sure if that makes sense in relation to EditorWindows.
Because from what I've learned, my original code, which works, __should be flawed. __
Sure thing. And doing a little reading, yeah it seems partials work fine, at least for components.
Not sure I quite understand the setup really, so hard to weigh in on it.
partials should be treated by the compiler as a single class, so it's strange that you'd be seeing a difference in behavior
Just gotta ask, did you already restart Unity? You never know, ya know. 😛
it may not be related to the partial -- how are your static fields being initialized?
They said it works when not partial, so it wouldn't be that I would think
around these parts we question our assumptions, pardner
Setup (non-partial)
https://gdl.space/yitetuseyo.cs
https://gdl.space/elificexag.cs
https://gdl.space/qarexokase.cs (Tester : MonoBehaviour)
This is in the middle of a rewrite
It's a very small project, so I do Reimport All on the reg 😆
it's possible that your static state was preserved in some way, and that the partial change was a symptom of losing the shared state rather than making it a partial
This sounds plausible.
idr off the top of my head if editor classes serialize statics automatically
Well, no need to guess about this, just make a minimum possible recreating of it
Narrow it down real quick
I would be interested in reporting it, to make partials more stable in the future
rn looks like your architecture is very dependent of execution order to work, so my first stab would be to re-architect it to be more robust
which since you're mid refactoring seems like you're already doing that 😄
indeed, as stated above, I'm making a custom GetWindow that doesn't automatically use .Show()
so that I can make initializations before OnEnable, and use partial
But if this is true, the current solution should throw errors if you run it, the first time.
It only requires 1 scene to exist in the project, as that is what it's trying to find.
is there a reason you cannot initialize things after onenable?
GUI Logic
hm
From what I understand, I need to initialize values before OnGUI runs.
I've never had any issues with execution order or initializing things in/after onenable with my editor windows
which is why I've used OnEnable
I mean, you can initialize things in OnGUI, not sure I understand why that would be an issue?
Unless I am misunderstanding
sounds inefficient, since that would require polling
the only one particular thing i know is cloning GUI.skin styles
why not do it in OnEnable
no, initializing stuff in OnEnable makes sense
Yeah, I mean OnEnable is the right place to initialize things for sure
I don't think OnGUI gets called directly after OnEnable
pretty sure you can change stuff after OnEnable, after GetWindow
The class I'm working on is named SelectAssetWindow
it is designed to be used by any other script in the project.
var w = SelectAssetWindow.Open(Type type, MyReturnMethod<string[]> selectedGUIDs);
Which will then open an EditorWindow with names of assets found,
allowing them to be selected, and then returned.
so ideally, everything should be initialized before the window ever opens
ok, seems easy enough to do
cachedType = type;
GetWindow()
Assuming this is what you were thinking of?
the rest of the initialization I'd take care of in OnEnable tbh, since type is the only thing you're passing in
Not entirely sure I follow your example.
There will be strings, too, but I don't see how that would be more complicated.
Alternatively, if you do new MyWindow or ScriptableObject.CreateInstance<MyWindow>(), you'll get a window that doesn't automatically open.
indeed, which will be the custom Get/CreateWindow() method I'm making to solve the partial class problem.
was shorthand pseduocode:
fn Open(type, callback) {
cachedType = type;
// whatever other statics you want to initialize
GetWindow()
}
since it's static state you don't need to get the window first to initialize it
thank you for revealing the simple solution that completely evaded me at this point 😂
🤣
but I think I agree that making your own init function is the way I'd go about it personally -- then there's no need for static state at all
better encapsulation
yeah, I'm moving away from statics.
Just needed the script to have no errors, before actually making it more clean.
glad I could help 🫡
Thanks to all of you guys 🖖
Wait, so did we figure out if/what was going on with the partial? Or is it just some bug/unexpected behaviour where the OnEnable method is not called when expected?
for that I use a public static class outside the EditorWindow class, which will be lazily initialized, once called upon from OnGUI.
Not really. Mad had a plausible explanation, but I don't fully buy it.
I might still report this behavior as a bug.
That said, he did show a simple way of bypassing the problem
I'm really fond of the nested static class pattern
class Outer {
static class Style {
// declare styles
static Style () {
// init styles
}
}
}
probably on partial as well
yah idk why partial would be causing issues -- only thing I can think of is that unity is picky about filenames and that is somehow causing a hiccup
I haven't used Outer yet.
I tried to have Style inside SelectAssetWindow, but if I observed correctly, Style is then initialized when the parent class also is (leading to error)
@tawdry kraken in this example Outer would be your MyWindow : EditorWindow
i have a base for all windows with specific virtual InitializeStyles
for styles used in multiple places ofc you'd want it in a different location
Well damn. I need to test this then. Just need an entertainment break to cool off.
yeah, enables usage of Style.whatever in your OnGUI code, really handy
- no leaking of local styles to the rest of the namespace
and if you want to be really lazy you can just make it public and then share styles via MyWindow.Style.whatever 😄
Don't you still need to declare them?
gotch
rather not the window class
interesting idea
that's basically the same idea then, just using a virtual instead of the static constructor directly
my windows are usually very short code wise
they just declare panels, panels subclass base panel, and in the panels they all receive config
yes i got real tired with styling and boilerplate all over the place
Yeah SessionState is great, though tbh I end up just using a ScriptableSingleton without the FilePath attribute
check this out
public sealed class AssetRefEditorPrefsValue : EditorPrefsValue<UnityEngine.Object>
{
public AssetRefEditorPrefsValue(string name, UnityEngine.Object defaultValue) : base(name, defaultValue) { }
public override UnityEngine.Object Get()
{
string guid = EditorPrefs.GetString(name, string.Empty);
if (string.IsNullOrEmpty(guid))
return null;
return AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(guid), typeof(UnityEngine.Object));
}
public override void Set(UnityEngine.Object value)
{
if(value)
{
AssetDatabase.TryGetGUIDAndLocalFileIdentifier(value, out string guid, out long _);
EditorPrefs.SetString(name, guid);
}
else
EditorPrefs.SetString(name, string.Empty);
}
}
static AssetRefEditorPrefsValue _assetRef = new AssetRefEditorPrefsValue("game.asset", null)
static ScriptableObject _asset;
void OnEnable()
{
_asset = _assetRef.Get();
}
void OnDisable()
{
_asset = _assetRef.Set(_asset);
}
forgot cast
Interesting. I can't quite wrap my head around it all. Haven't used Panels yet.
The only thing that stands out to me is EditorApplication.update, which should obviously be used sparingly, but seems okay here.
Have you ever looked into replacing that polling with an event?
(technically, the editor update is an event, but it runs up to hundreds of times per second; thus I call it polling 😆 )
it runs at whatever the throttling setting in preferences allows it to, by default its somewhere in the screen refresh rate ballpark
OnGUI is called many times a frame
update in editor is happening outside of OnGUI and many things you can only do in update
Great news it does indeed work in a new project, you see i have this unity framework that I've been working on for a couple of years and it gets used in all projects as a submodule to every projects repository just to add a base for additional functionality and speed up work for other devs and it's become so second nature to add the framework into a new project immediately that i didn't even register it as "not an empty project" 😂
So i guess before when i said i had tried it in an empty project i unintentionally lied 😅 whoops
Yeah so now i just have to comb through the tens of thousands of lines of codes and see where i messed up haha. But it's a relief to know i just did something stupid somewhere rather than it's a unity bug. Thanks @gloomy chasm and @alpine bolt for all the help, it's much appretiated.
What a great community!
yeah that the issue is definitely (probably) what I said before. You have a editor that you set as the default fallback editor for all MonoBeahviours/ScriptableObjects
Yeah must be, that makes sense. Now I just have to search and find it 🔍 , shouldn't take too long 😁
It's this script that was the problem
[CustomEditor(typeof(Object), true, isFallback = true)]
public class DefaultEditor : Editor
{
public VisualElement DefaultInspectorVisualElement()
{
var result = new VisualElement();
var iterator = serializedObject.GetIterator();
if (iterator.NextVisible(true))
{
do
{
var propertyField = new PropertyField(iterator.Copy()) { name = "PropertyField:" + iterator.propertyPath };
if (iterator.propertyPath == "m_Script" && serializedObject.targetObject != null)
propertyField.SetEnabled(value: false);
result.Add(propertyField);
}
while (iterator.NextVisible(false));
}
return result;
}
}```
That's actually one i one on github a while back, so that person probably had the same issue but must have fixed it by now
What i'm using that for is to draw the default inspector in cases where i mostly want the inspector to remain unchaged but just draw like a button or something above or below the default inspector. is there another way to easily show the default inspector in visual elements based inspectors?
This should work, but what are you doing in OnEanble, it should be in CreateInspectorGUI
Yeah sure, i could do it in CreateInspectorGUI.
So i just made DefaultInspectorVisualElement() a helper function in a VisualElementHelpers class instead of having classes inherit from DefaultEditor and using DefaultInspectorVisualElement, because now i don't have some custom editor for Object that seems to be causing the problem. So yeah, no more issues with attributes saying NoGUIImplemented
is there a way to override disabled gui color globally
huh it just sets color it seems
nope
found solution
I'm trying to align my bool values next to each other in one row.
I somehow managed to do this using
EditorStyles.label.alignment = TextAnchor.MiddleRight;
But that moves the label to the value, not the other way around.
Is there a "value" equivalent to "label" in EditorStyles?
You gotta calculate the positions yourself
Any way to add automatically the assembly folders that are dependencies of another assembly to a “export package” checked items without just selecting the whole project?
Maybe you are resetting/restarting the animation at every iteration of your code
Also, maybe this isn’t the right channel to place this question
#🏃┃animation maybe?
didnt see the channel
why propertydrawers can access only serializable data easily with FindPropertyRelative, and everything unserialized needs some workarounds(i was able to find those on google, i admit),
like there are so many unity types that are unserializable; forexample: List inside list(list matrix), any array, any tuple, dictionaries, and propably lot of other stuff too....
it seems like im not supposed to access data of those types because it doesnt want to allow me.. is there a reason for this, or should i just think that unity is dum dum and implement those workarounds
or is there some other(better) way to access properties than FindPropertyRelative
If it doesn't serialize then it's not saved to disk, aka it's lost on restart
Whether it's too strict is up for discussion, I think it's fine
For the record you can do lists in lists as long as you make the inner list non-generic
Like class MyList : List<Thing>
hello! does anyone here know any sort of workflow that can allow me to stream the output of my Unity Editor as webcam source for my zoom call?
OBS can serve a virtual camera that Zoom can use, but it will have to capture the screen. Surely easier to let Zoom screen share?
yeah zoom screen share would probably be the easiest way to do it, but for my usecase i've built a 3d scene which i am compositing as a realtime background for my webcam stream. to make obs work, will it mean that it will capture the entire screen and stream it as a virtual camera or can i just have the Game output of my editor be streamed?
I have this editor extension (the Add To Library/Setup button specifically) that sets its own ID based on the prefab name and then adds itself to a library of PoolableObj. The PoolableObjLibrary is a Scriptable Object that holds a Dictionary of Keys and their Prefabs. The idea is that you can spawn prefabs and pool them with just a simple string and I like how it works very much... when it does work. There are 2 MAJOR issues. The ID it gives itself won't always get saved and the SO won't always save the objects that have been added to it, and I can't for the life of me recognize a pattern to it... it's just random whether or not the ID gets saved or the SO saves the obj or not
Sorry I know that's hella lengthy but I don't know what the heck to do about it
Those above 3 objects got added just fine
But now the Grenade Lobber won't stick in there on reloading Unity
The ID it gave itself did stick though, sometimes it won't even stick until runtime
OBS will capture a single window (which means it doesn't need to be foregrounded) BUT Unity Editor confuses it with multiple panes. Easiest to capture entire desktop and crop that to the gameplay window. You can also chroma key your webcam as an overlay in OBS and share the resulting mix as a virtual camera to Zoom. It's built for Twitch streaming so it's extremely versatile.
Sounds like you need to explicitly mark the SO as dirty and then prompt it to save?
I think I tried setting it as dirty and it didn't really work, but I don't think I fully understand it
I'll try it again, I never actually deleted the code for it
I just commented it out
ok setting the SO as dirty seems to have fixed that
Maybe I was just being silly before idk
But then what about the PoolableObj not saving its ID?
Yeah for whatever reason
The ID won't stick
I just tried it again
Do all the PoolableObjs need to be dirty then?
Oh that ID is saved into the scene containing the PoolableObj, so you need to make sure that is also saved...
I don't think so
Unless it's in a prefab?
I'm pressing the button while in the prefab
yeah
Lemme get a pic
It's beautiful I know
My best guess is that changing the data via script bypasses Unity's undo/redo/dirty code, so you'll have to mark the prefab as dirty as well.
Yeah I'll give it a shot
Even if this works I gotta read up on what dirty means again
I've read it like twice and keep forgetting
also should it be set dirty and then added to the library or vice versa
Dirty just means modified. Set it after you're done making changes, and then poke the editor to make sure it saves immediately.
If you're working with source control you might also need to check the asset out in order to save it.
So anytime I make a change to a dirty obj I want to be permanent I should call
it's not just a one time thing I should do, I need to keep calling that every time I change something right?
Marking things dirty just tells the editor they need saving.
Calling Save actually writes the dirty data to disk.
It's an optimisation; if you didn't have the dirty flag, it would have to write EVERYTHING in memory back to disk every time you hit ctrl-S.
Ok I got it
So every time I make a change I have to call make dirty
I just doubled checked and it wouldn't save the changes unless I kept calling setdirty
Everything works as intended now
I wish the docs were more clear on the fact that you had to call it every time
Ah well
Anyways thank you so much for the help Chris
this is insane https://stackoverflow.com/a/44097609
this actually works, the dude is a genius
Or you just use UIElements which has properties for all of this
I want to write a custom asset placer, but wanted to include a visual picker/browser in my editor window.
-
Is there a built in unity asset browser layout element? that looks like the search results / object picker? (but allows selecting multiple objects/prefabs?)
-
I wrote an object placer years ago, using
previews[i] = AssetPreview.GetAssetPreview(item)and(GUILayout.Button(previews[i],...(but I'd have to ammend that to allow multiple selection) but worse of all this code stopped working completely. I never get the previews andAssetPreview.IsLoadingAssetPreviews())returns true all the time, but I'm not getting any errors, did something change since 2020?
(re: 2) I switched my project browser to 2 columns and the previews appeared!) so back to 1) is there a built in element I can use? or should I simply rely on user selection in the project browser?
this is what I have now, it's just square Buttons() with the assetpreview. I can extend this to handle multiple selection. but I pretty much want the default object picker, but allowing to pick multiple objects.
(I could use a list of game objects but want easier selection then adding list items one by one)
How can I add an entry to the object creation context menu? (So next to plane / cube / sphere I want to insert my custom object, kind of like "Terrain", but it would be an empty gameobject with my monobehaviour attached?)
I'm asking chatgpt a lot, and it's super helpful but there's an issue it can't figure out for me. I'm using a BoxBoundsHandle to define a volume, and it worked perfectly until my transform is rotated. gpt suggested this code:
Matrix4x4 originalMatrix = Handles.matrix;
// Set the matrix to align with the selected transform's axes
Handles.matrix = Matrix4x4.TRS(selectedTransform.position, selectedTransform.rotation, Vector3.one);
...
Handles.matrix = originalMatrix;
but now the bounds appears rotated correctly but doesn't align with my transform. (Transform's scale is all 1's)
hard to say withou seeing all of the code. But I my guess is because the matrix makes it local to the position you pass it, and in the bounds you are also using the position, so it is acting as an offset. Try using Vector3.zero (for testing) as the position of the bounds intead.
use Handles.matrix = transform.localToWorldMatrix
I tried zero and I tried transform.localToWorldMatrix... everything is off :/
ok let me get into it
@wide kraken what do you want to achieve?
draw bounds in editor?
Sorry, had a feline emergency. Im making a "spawner", want it to be a volume in space. It currently works great as long as I don't rotate it (because the boxboundinghandle is Addis aligned) I'm trying to make it so the handle renders at the transform center and aligns to its rotation
so in my game, I have a ScriptableObject with a list of derived classes since the base class is abstract, I know I have to [SerializeReference] instead of [SerializeField] to get it to show, and it almost works, but I need it inside of a ReorderableList since I don't want users to be able to add and remove from this list freely, but it's just showing the Element 0 or Element 1 or whatever. It has the correct height, but doesn't show anything else, it's just blank
There is no default drawer for SerializeReference. Without a serializable value assigned it will be blank
my drawElement callback is just EditorGUI.PropertyField(rect, _events.GetArrayElementAtIndex(index));
yeah but it works without ReorderableList
and it worked on another project I had
wait
that's right
there was custom editors on the last one
thanks
(ugh this is gonna suck)
https://github.com/vertxxyz/Vertx.SerializeReferenceDropdown I have a drawer that makes things easy. It may or may not do it for you (it's a complex thing to support due to nested property drawers)
yeah
the hard part for me rn is gonna be because of the nested drawers and I have a bunch of UnityEvents that will change size obv based on how many Events they have and stuff
ok I got one displaying...
ok got them all displaying
gonna stop spamming now lol
is it possible to make a ReorderableList skip an element?
I tried just setting the height to 0 but that didn't work well lmao
You can pass a modified list into it?
^
Hey ppl!! One question, I just figured out that Matrix4x4 is not Serializable for Unity. Since Matrix4x4 is basically 16 floats in memory I don't see why it would not be serializable. Is there anything I can do to persist an array of Matrix4x4 in a component without having to wrap the whole thing or making TRS to Matrix4x4 transformations just to persist the data?
use Get/SetColumn, write into array, use ISerializationCallbackReceiver to serialize/deserialize from that array
you can also use indexer
That's something.... but 😭 whyyyyy??????? It's really frustrating.....
Thanks a lot though @karmic ginkgo
This I don't get, could you give me a few more keywords?
matrix[0]
[] is called indexer
yes I do understand that but how would it help me serialize the matrix
haaaaaaaaaa I get it
just instead of the Get/Set
ok ok, sorry!! I got confused, I thought it was not related to the first msg
hahah 😄 I was blinded by my hope that another solution would be there that elegantly solved my problem hahaha
you can use Odin
or other serializer that does it for you
but they most likely do the same thing
you can wrap it into extension method
[SerializeField] float[] _serializedMatrix;
void OnBeforeSerialize()
{
_serializedMatrix = matrix.ToArray();
}
That's cool! 🙂
it's a nice idea!!
I need to reduce dependencies so external serializers would be a pain for me
Also Mathematics' float4x4 should be serializable if you want something else with implicit conversion
hoooo nice one as well!!
you guys rock!
Thanks a lot @karmic ginkgo and @visual stag!!
that gives me enough to go on confidently
Damn!! 😭 I was so happy with this, but it's not serializable either....
Matrix4x4 is also serializable
whaaaaat?? nooo!
but perhaps just by Unity and not by other things that look for the Serializable attribute
float4x4 has the attribute, so that should work in all scenarios
Holyyyy S@#*&... you're right!!
what's happening then???? hoooooooooooooooo...... let me see
If you're trying to serialize something in the inspector then you probably have a custom editor overriding it, or you're using a plain C# object that isn't marked as Serializable
Changing a script name shouldn't invalidate any references because the meta file should be renamed too, and that contains the GUID that is used to reference the script.
"shouldnt" 😄
I see what's going on.... but I don't necessarily understand yet why....
public Matrix4x4 matrix = Matrix4x4.identity; // <-- This serializes
public Matrix4x4[] matricesArray = new Matrix4x4[1023]; // <-- This serializes
public List<Matrix4x4> matricesList = new List<Matrix4x4>(); // <-- This serializes
public List<Matrix4x4[]> matrices = new List<Matrix4x4[]>(); // <-- This DOES NOT serialize
Unity doesn't support nested collections.
If I wrap Matrix4x4[] ?? 😉
Yes, you can serialize a collection of objects which themselves contain a collection.
[System.Serializable]
public struct MatrixArray
{
public Matrix4x4[] matrices;
public static implicit operator Matrix4x4[](MatrixArray m) => m.matrices;
}
...
public Matrix4x4 matrix = Matrix4x4.identity; // <-- This serializes
public Matrix4x4[] matricesArray = new Matrix4x4[1023]; // <-- This serializes
public List<Matrix4x4> matricesList = new List<Matrix4x4>(); // <-- This serializes
public List<Matrix4x4[]> matrices = new List<Matrix4x4[]>(); // <-- This DOES NOT serialize
public List<MatrixArray> matricesWrapped = new List<MatrixArray>(); <-- This serializes.........................
....
this definitely adds to the hate side of my love/hate relationship with Unity.... but I get it..... It's hard.... it's ok... I'm ok.... 
Now,
Any arguments why should I not make this??
[System.Serializable]
public class NestableArray<T>
{
public T[] array;
public int Length => array.Length;
public T this[int index]
{
get => array[index];
set => array[index] = value;
}
public static implicit operator T[](NestableArray<T> na) => na.array;
public static implicit operator NestableArray<T>(T[] a) => new NestableArray<T> { array = a };
}
None from me. Except, you could change the indexer to return by ref, which is what System.Array does:
public ref T this[int index] => ref array[index];
Good one!!
@whole steppe this section is for developing plugins/assets/modifications for the editor itself
I don't think unity has an autosave in vanilla
I know there are assets that do autosave
im having trouble setting vec4 material values
var mat = new Material( t.materialTemplate.shader );
AssetDatabase.CreateAsset( mat , path );
AssetDatabase.Refresh();
mat = AssetDatabase.LoadAssetAtPath<Material>( path );
mat.CopyPropertiesFromMaterial( t.materialTemplate );
mat.SetTexture("_Control", splatTexture ); // works as expected - changes can be seen in the created material asset ! ! !
...
Debug.Log( ST ); // prints something like 20,20,0,0,
mat.SetVector("_Splat0_ST", ST); // does not work and the default value is used instead (1,1,0,0) ! ! !
AssetDatabase.SaveAssetIfDirty( mat );
try EditorUtility.SetDirty(mat) before you save
im not sure whats going on there sorry
How does the tutorial have these recommendations? I cant seem to get them in any way and they would be super useful:
Is your ide properly configured?
im not sure I guess. just launhced how it is and I added intellisense but it wasnt doing that before intellisense anyways
Intellisense should provide the correct suggestions if so
no I mean that suggestion box isnt showing
I don't know what you mean by suggestion box.
like where it tells where you need the method and vars. it only recommeds a finished line
If your IDE is not autocompleting code
or underlining errors, please configure it:
• Visual Studio (Installed via Unity Hub)
• Visual Studio (Installed manually)
• VS Code*
• JetBrains Rider
• Other/None
*VS Code's debugger plugin is unsupported.
We recommend using VS or Rider instead.
heres mine:
I want it to say
InvokeRepeating(string methodName, float time float repeatRate);
Try checking
Options > Text Editor > C# > IntelliSense > Automatically show completion list in arguments list
Or manually with control + shift + space within the parenthesis
does vscode have intellisense or intellicode for c#?
It's in the list of IDEs in the bot message above
For classes that implement UnityEditor.Editor, is there a way to make Unity remember information such that when I close my project and open it again, it is still there? Like SerializeField for MonoBehaviours. I don't really need this, just curious.
I suppose I could delegate to the MonoBehaviour to store all the information I want saved, and retrieve the information when I restart Unity, just curious if there is a better way.
EditorPrefs
SessionState
if you want to store a reference to an asset you can do something like
public sealed class AssetRefEditorPrefsValue : EditorPrefsValue<UnityEngine.Object>
{
public AssetRefEditorPrefsValue(string name, UnityEngine.Object defaultValue) : base(name, defaultValue) { }
public override UnityEngine.Object Get()
{
string guid = EditorPrefs.GetString(name, string.Empty);
if (string.IsNullOrEmpty(guid))
return null;
return AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(guid), typeof(UnityEngine.Object));
}
public override void Set(UnityEngine.Object value)
{
if(value)
{
AssetDatabase.TryGetGUIDAndLocalFileIdentifier(value, out string guid, out long _);
EditorPrefs.SetString(name, guid);
}
else
EditorPrefs.SetString(name, string.Empty);
}
}
note EditorPrefsValue is my class
of interest is code in Get/Set
Good ol' ScriptableObject
If I have [ExecuteInEditMode] attribute on my MonoBehaviour, what is the difference between Awake and OnEnable? According to the documentation, "Awake is only called when the script is instanced." But I couldn't find anything on OnEnable. I am trying to get the one that is called whenever I make an edit to my scripts and the Unity Engine reloads as a result.
use ExecuteAlways
Awake is called for everything everywhere in the editor when its loaded
assets call it prefabs call it
while being assets
onEnable is called when its enabled in hierarchy i believe
your editor reloads?
Awake => On Unity Start
OnEnable => On Unity Start/Reload
That's easy to test. Just made your use case and tested it myself with Debug.Log.
However... There's this handy dandy callback attribute [UnityEditor.Callbacks.DidReloadScripts] you can use on a static function (editor only)
Here's how you can use it
[UnityEditor.Callbacks.DidReloadScripts]
private static void YouSpotABeautifulLady()
{
Debug.Log("Hey baby");
}```
Im adding a components with some flags on it like so:
private static void AddTracker(Component obj)
{
MM_PrefabTracker tracker = obj.gameObject.AddComponent<MM_PrefabTracker>();
tracker.hideFlags = HideFlags.HideInInspector | HideFlags.NotEditable | HideFlags.DontSaveInBuild;
}
But for some reason after restarting editor these flags seem to dissapear. Component is visiable and editable when I start new session. What am I doing wrong here?
is it DostSaveInBuild? its doing something else that i think it is?
This is the first time I've tried to do something with the editor. I want to make a script that displays the health variable at runtime. I tried using the script below, but the health is not showing during playtime
using UnityEngine;
using UnityEditor;
[CustomEditor(typeof(CreatureClass))]
[CanEditMultipleObjects]
public class EditorSerializableHealth : Editor
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
CreatureClass creatureClass = target as CreatureClass;
if (Application.isPlaying)
{
EditorGUILayout.FloatField("Health:", creatureClass.health);
}
}
}
it seems like ages since I was using IMGUI for the last time, but shouldnt FloatField take a SerializedProperty as a parameter?
EditorGUILayout.FloatField("Health:", target.FindProperty("health"))
Nah
Is there a way to move a gameobject by drawsphere gizmo? I have a script that generates the gizmo, but I can't seem to figure out a way to move the object around in the editor. As a secondary question, is it possible to have an editor script running that draws the gizmo's on every gameobject that contains X script, so I can move the gizmo monobehavior off my gameobjects? Preferably under my editor scripts.
I have trouble finding resources on this, because searches just come up with how to use the built in movement gizmo's.
You will want to create a custom Editor for your component and use the OnSceneGUI method
https://docs.unity3d.com/ScriptReference/Editor.OnSceneGUI.html
You will use the Handles API instead of Gizmos
Hope that gives you a place to start.
@gloomy chasm Interesting, I'll dig through it, thanks
Hey, so im trying to do an experiment where i have two unity projects and i want the game view of one project be somehow be fed into the other project. any ideas on how to do this?
Would have to use reflection and other hackery. But my first idea would be get the render texture from one, export it as a texture file, have the other project read the bytes of the texture file and turn it in to a RenderTexture, and use that to render to the project view.
No idea what the performance would be like on that, but it would work in theory. There could also be a nicer way to go about it I am not thinking of.
The GameView has a m_RenderTexture field you could set, I see it is also set at different places within the GameView, so it might get cleared/reset. But it is a place to start
yeah im not really worried about performance. so if i export the render texture as a texture file, will it be updated in realtime as both the projects will be running simultaneously?
In theory it would be. But I am also not sure what if any staging Unity might do in regards to rendering.
But it should be I think.
One issue might be that you have to read and write from the same file... hmm...
yeah
Another way could be to use ports to communicate between the two Unity instances and send the bytes. It would be cleaner and probably more performant. But also a lot of setup
yeah that was also one of the suggestions i got, but it feels like too much work just for an experiment
A lot is relative I guess. It has always caused me headaches when I have tried to communicate between processes
I mean, you could probably do the whole experiment in less than 2 hours, even with using the ports
sure, i guess i will give both approaches a try. thanks!
Sure thing, and please do report back in with the results, success or fail! 😄
So I sort of have moving a gizmo around with handles, but it's really finicky
Alright, I have it to the point where I can drag around my gameobjects if they are selected, and I have all my gizmos showing me what i need. The only thing I'm missing is the ability to select the object in the editor. I can only select it in the Hieararchy.
[CustomEditor(typeof(AssemblyDefinitionImporter), true)]
public class CustomAssemblyDefinitionInspector : Editor
{
private Type _assemblyDefinitionImporterInspectorType;
[SerializeField] private Editor defaultEditor;
private void OnEnable()
{
_assemblyDefinitionImporterInspectorType = typeof(Editor).Assembly.GetType("UnityEditor.AssemblyDefinitionImporterInspector");
defaultEditor = CreateEditor(target, _assemblyDefinitionImporterInspectorType);
if (defaultEditor == null) return;
var onEnableMethod = _assemblyDefinitionImporterInspectorType.GetMethod("OnEnable", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
onEnableMethod!.Invoke(defaultEditor, null);
}
private void OnDisable()
{
if (defaultEditor != null)
{
var onDisableMethod = _assemblyDefinitionImporterInspectorType.GetMethod("OnDisable", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
onDisableMethod!.Invoke(defaultEditor, null);
DestroyImmediate(defaultEditor);
}
}
public override void OnInspectorGUI()
{
if (GUILayout.Button("Hello World"))
Debug.Log("Worked");
if (defaultEditor != null)
defaultEditor.OnInspectorGUI();
}
}``` has anyone achieved a successful AssemblyDefinitionImporterInspector extension?
What is that supposed to do?
Add a button
Any clue on how unity serializes references? I guess it doesn't use instance IDs since they change all the time. So how are references to other objects handled? I'm asking since Unity.Objects when serialized to json are serialized as their instance ID. Say I want to save an inventory to JSON with a list of Item ScriptableObject, saving the names/GUIDs and loading from the addressables seems a bit intense for such a "simple" task
For UnityEngine.Object references it uses the GUID in most cases
any cool trickes to have a foldout (UITK one) expand/collapse only when arrow is clickedn, and not the whole element? Like game objects in hierarchy, where you expand children by clicking arrow, but clicking object itself only selects it.
Probably put a button on top of the label and consume the event when you click it
Hierarchy foldout is a custom component iirc
Since it's a tree view
yes, also depends on your unity version. Before 2022.2 override the HandleEvents then do evt.StopImmediatePropagation after 2022.2, override the ExecuteDefaultAction iirc
then inspect in the debugger see whats the arrow called then do query and register your callback to it
proly just this var arrow = myFoldout.Query("arrow").First() then register your callback to the arrow
So still I need to create new class inheriting from the foldout?
you can register PointerDownEvent to the arrow then do stopImmediatePropagation and it would work too I think. Note that PointerDownEvent is a higher priority than MouseDown or any other input events in uitk I think
also note, most default elements in uitk has both PointerDown and MouseDown assigned to them by default, so there's a chance the default will be executed 1st nah, the latter assigned event will always be executed 1st pretty sure
this is preferred, yeah. Unless someone else has a better idea
Yeah but arrow is a child of a toggle which consumes event first if Im correct, and this toggle works as a whole header for a foldout, thus clicking anywhere changes its value
aight, just do it the janky way then 😅 if you really don'w want to make custom foldout class.
Addd another PointerDownEvent callback to the Foldout, then check the target
myFoldout.RegisterCallback<PointerDownEvent>(evt =>
{
var arrow = myFoldout.Query("arrow").First();
//Another option is to Check if the pointer localPosition is within the rect
if( arrow != null && (VisualElement)evt.target == arrow)
{
myFoldout.value = !myFoldout.value;
}
evt.StopImmediatePropagation();
});
@glad cliff
Seems reasonable XD
it is not, I mean, it's obviously super ugly.. making your own custom foldout would cost you about 5 minutes of yout time tbfh
Although at this point I'm really confused when stop propagation and all of its variants work, bacause switching from 2021 to 2022 made half of them in my code not working...
yeah, they obsoleted bunch of apis in 2022 lts
either way your ide should tell you how to replace them with the new apis, so shouldn't be an issue
Is it possible by default in Unity to make something that works just like an enum (has a value attached) and can be choosen in a dropdown list in the inspector, but also shows an image (basicaly a dropdown list of images to choose from in the inspector / enums with images) or do I have to make something custom for that?
you can use ListView and do your own custom template
I'm speaking of uitk tho
Thanks, I'll take a look into that
@peak bloom idk those events are messing me up so badly...
unity-checkmark is this arrow in a foldout
but whole header including arrow and a laber is in a Toggle, so clicking it cosues value change
protected override void ExecuteDefaultAction(EventBase evt)
{
if(evt is PointerDownEvent)
{
var arrow = this.Query(name: "unity-checkmark").First();
if ((evt as PointerDownEvent).button == 0 && (VisualElement)evt.target == arrow)
value = !value;
}
else
{
base.ExecuteDefaultAction(evt);
}
}
Is this what u meant by overriding ExecuteDefaultAction?
eh almost there
when you set myFoldout.value it will trigger the INotify so what you're doing will be useless, so you want to myFoldout.SetValueWithoutNotify(!myFoldout.value)
then do evt.StopImmediatePropagation after
@glad cliff
nothing changes...
put a debug, so make sure your PointerDown is executed
ive been testing and it fires only when i click an empty space like here
ive tried registering callback on Toggle itslef too but for some reason it fires only on right click
and doesnt work as supposed either
try change your arrow pickingMode
nothing
that';s weird, are you sure you're getting the correct element?
im aint sure of anything at this point
i wrote also this:
foldout.Query(className:"unity-base-field__input").First().RegisterCallback<PointerDownEvent>(e =>
{
if (e.button == 0)
{
Debug.Log((e.target as VisualElement).GetClasses().First());
var arrow = foldout.Query(name: "unity-checkmark").First();
if ((VisualElement)e.target == arrow)
foldout.SetValueWithoutNotify(!foldout.value);
e.StopImmediatePropagation();
}
});
but debug log says that target is always base-field_input and never toggle_checkmark and this debug fires only when clicking arrow or empty space next to a label but not when clicking label itself, however when I change arrows picking mode to Position it doesnt fire when clicking it either, other than that behaviour stays the same
Ok now it works but...
foldout.Query(className:"unity-base-field__input").First().RegisterCallback<PointerDownEvent>(e =>
{
if (e.button == 0)
{
e.StopImmediatePropagation();
e.PreventDefault();
}
});
foldout.Query<Label>().First().RegisterCallback<PointerDownEvent>(e =>
{
if (e.button == 0)
{
e.StopImmediatePropagation();
e.PreventDefault();
}
});
foldout.Query(name: "unity-checkmark").First().RegisterCallback<PointerDownEvent>(e =>
{
if (e.button == 0)
{
foldout.SetValueWithoutNotify(!foldout.value);
e.StopImmediatePropagation();
e.PreventDefault();
}
});
XD
holy god 😅 ... if it works then it works.. I guess
public static class EventsExtensions
{
public static bool DisableLeftClick(this PointerDownEvent pointerDownEvent)
{
if (pointerDownEvent.button == 0)
{
pointerDownEvent.StopImmediatePropagation();
pointerDownEvent.PreventDefault();
return true;
}
return false;
}
public static void Test()
{
var foldout = new Foldout();
foldout.RegisterCallback<PointerDownEvent>(e => e.DisableLeftClick());
foldout.RegisterCallback<PointerDownEvent>(e =>
{
if (e.DisableLeftClick())
foldout.SetValueWithoutNotify(!foldout.value);
});
}
}``` you can reduce the footprint by making extension methods like this.
- In custom inspector, can i recursively draw default properties for all fields except some of them? My scenario is to handle several fields manually, and draw defaults for the rest without having to manually search for them
- Kinda like drawing a default inspector, but excluding some fields
DrawPropertiesExcluding?
what is it? The is no such thing in API O.o
I remember this question poping up quite frequently, and I dont think there is solution for that :/ you either write whole custom inspector or not...
one solution I can think of is that you can mark these fields with [HideInInspector], then draw default inspector and on top of that manually find these hidden properties and draw them on your own
Idk why it's not in docs
hmm yeah wierd
I have a small problem now too:
Ive read somewhere that when you create Editor through code you need to manually destroy it later cause Unity wont Dispose it automatically, So I did just that, and in my EditorWindow when OnDisable is called i call DestroyImmidiate() on all Editors within that window, but when OnDisable is called when scripts are recompiled it throws NullReferenceException because serialziedObject of SerializedProperty havs been disposed. So I assume in this case it has been disposed already so I dont need to worry about that, just catch and ignore it... but I cant catch it XD it is logged somewhere along the path
so I need a way to determine if I need to destroy that editor or not. editor != null and editor.serialziedObject != null doesnt work
- Epic, exactly what i need. Thanks a lot!
https://github.com/HokageMinato/SerializedTuplesForUnity/blob/main/README.md
Made a SerializedTuple drawer and custom attribute.
Core idea is to have a generic data transfer bridge object which enables data transfer from unity context (inspector mostly) to Non-mono systems (I use those mostly 😅 ).
Lemme know if there are any suggestions/improvements/critic reviews(most appreciated 😉 ).
SerializedTuples
hide flags dont work on prefabs and they are cleared as soon as prefab is marked dirty 😦 just learned it the hard way
What hide flags on what part of the prefabs?
On components
I wanted to have editor-only component that doesn't show in the inspector
And it supposed to be a component reserved for prefabs
That isn't supported
I mean editor only components
Well... there is DontSaveInBuild flag
Doesn't it make editor only when set to a component?
Nope, it can be used on prefabs though, and maybe on GameObjects
Anyway my component destroys itself on awake if not editor XD almost same thing
What is this component doing? Why editor only?
The plan was that I have a custom class attribute that whenever added to a monobehaviour it creates this component that automatically makes a prefab in a specific folder, and then I have a window to edit all prefabs in that folder. It's oversimplified, but more or less this is the idea
Does anyone know how to add an event listener with UnityEventTools.AddPersistentListener to a property setter?
I thiiink I need to use reflection unfortunately. Am I headed in the right direction?
var setter = tmp.GetType().GetProperty(nameof(tmp.text))!.GetSetMethod();
UnityEventTools.AddPersistentListener
(
unityEvent: localizeStringEvent.OnUpdateString,
call: // somehow get a UnityEvent<string> from the methodinfo
);
Just using setter.CreateDelegate should do, no?
So the attribute on a component, makes a prefab with an editor only component inside of a special folder?
Basically yeah
Ig I don't need this component for that, but the point is that it automatically applies any overrides too
TIL! Thank you 🙏
No problem 😄
I am just wondering what why the editor only component, or I guess what it does. Obviously all the other stuff you have mentioned is doable though.
Maybe there is a nice workaround for it
I made it all work with no problem, I just don't like the idea that user sees this component
Should be able to at least do HideInInspector
Flags are still cleared when switching scenes. :/
All flags...?
Idk, at least this one it seems
Weird... so I can get it to hide when you select the asset, but not when editing the prefab... 🤔
var a = (FontAsset)EditorGUIUtility.Load("Fonts/Poppins-Black SDF");
if (a == null)
Debug.Log("Is null");
``` i dont get it, why its cant fint my Font Asset?, total path is "Assets/Editor Default Resources/Fonts/Poppins-Black SDF.asset", and i believe the path that i need to fill in EditorGUIUtility.load are like abouve, so where did am wrong?
https://github.com/HokageMinato/Scriptable-Enum-For-Unity
Another one!
Scriptable Enums with Property Drawers. (Might be very basic ig but seemed worth a share).
Idea is to utilize values in scriptable objects as instance identifiers or categorizer values.
Partially limited as it doesnt allow access to value like {EnumName.EnumValue} but no way around it rn,
Open to suggestions on it!
Lemme know if there are any improvements and critic reviews are most appreciated 😉 .
how to save changes and record Undos of an object variable (not the target) that's being used in a [CanEditMultipleObject] custom Editor?
Alright I discovered EditorPrefs which I think is the thing I need
But I don't think it automatically supports Undo history
When I open my Unity project this method is invoked:
[DidReloadScripts]
private static void OnScriptsReloaded()
{
if (managerContainer == null)
{
managerContainer = FindOrCreateManagerContainer();
}
EditorApplication.delayCall += AddComponentsWithManagerAttribute;
}
Where managerContainer is a ScriptableObject with some data in it, but inside AddComponentsWithManagerAttribute method it appears that List inside this SO is empty, despite having some serialized values in it. Overall it all works fine when scripts are recompiled, this issue appears only when project is being opened. Why is it so?
am I trying to read values that were not deserialized yet or something?
What is this SO? ScriptableSingleton? Something else? I would need to see more of the code to really be able to say. My guess would be it either isn't being serialized to disk, or DidReloadScripts is called before deserialization. But my guess would be on the first one.
ohhh I didnt even know such thing as ScriptableSingleton exists. I will dive into that later
public class MM_ManagersContainer : ScriptableObject
{
public List<MM_SceneManagerPair> Managers = new();
}
[Serializable]
public class MM_SceneManagerPair
{
public SceneAsset Scene;
public GameObject Prefab;
public string Path;
public string DisplayName;
public string Type;
}
this is my ScriptableObject
private static MM_ManagersContainer FindOrCreateManagerContainer()
{
string[] guids = AssetDatabase.FindAssets("t:MM_ManagersContainer");
if (guids.Length > 0)
{
Debug.Log("Assigning managers container");
string path = AssetDatabase.GUIDToAssetPath(guids[0]);
MM_ManagersContainer existingContainer = AssetDatabase.LoadAssetAtPath<MM_ManagersContainer>(path);
return existingContainer;
}
else
{
Debug.Log("Creating new container");
MM_ManagersContainer newContainer = ScriptableObject.CreateInstance<MM_ManagersContainer>();
//newContainer.hideFlags = HideFlags.HideInHierarchy | HideFlags.NotEditable | HideFlags.DontSaveInBuild;
string newPath = "Assets/MM/Managers/ManagerContainer.asset";
AssetDatabase.CreateAsset(newContainer, newPath);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
return newContainer;
}
}
This is how it is assigned at startup
Yeah, if you only need the data in editor, 1000% recommend ScriptableSingleton. The issue is that Managers is empty, right? What does AddComponentsWithManagerAttribute look like since that is what the issue would be with if it was a serialization to disk issue
great... i was doing this thing with a component that I wanted to hide in a prefab, then rewrote it all to use some more static methods and SO, now im getting introduced to something like ScriptableSingleton and I will rewrite it all again XD lovely
it iterates through game objects on currently open scene and if some have Behaviour with specific attribute checks if it is connected to one of prefabs from that list in scriptable object
normally it should detect that it is already connected, but as this list appears empty when opening a project it tries to create new prefab out of it resulting in creation of a prefab variant :/
Wait, so is it checking every component on every GO...?
yeah dont tell me how un optimal it is XD
Very 😛
That is beside the point though haha
Are you setting dirty and what not when you are assinging the Managers list?
Or am I misunderstanding the issue?
yeah but i had no better idea, yet i did my best to call it as rarely as possible, some things are cached along the way and some checks are skipped etc.
im not sure if I understand what you mean
Well I am not sure I understand what you mean haha
Can you share the AddComponentsWithManagerAttribute method maybe?
list is populated with new entries any time component with my custom attribute is added to go
its freakin massive man XD
but list isnt populated there, the only thing that happens there is trying to acces values in that list, nothing more
So where is it populated then?
ObjectFactory.componentWasAdded += OnComponentAdded;
Actually something to check is to open the SO in a text editor and check if the entries are actually there
That will tell you right now if the issue is that the entries are not being serialized to disk or if you are trying to access it before it is fully deserialized.
u mean ASSET file?
yeah the .asset file
bunch of if's and if it passes all of creates a prefab out of go and adds refference to it as follows:
MM_SceneManagerPair pair = new()
{
Prefab = prefab,
Scene = AssetDatabase.LoadAssetAtPath<SceneAsset>(obj.gameObject.scene.path),
DisplayName = obj.GetType().GetCustomAttribute<Manager>().DisplayName,
Path = obj.GetType().GetCustomAttribute<Manager>().Path,
Type = obj.GetType().AssemblyQualifiedName
};
managerContainer.Managers.Add(pair);
Don't see ya setting the manager container dirty
ooook...I feel stupid now thinking it supposed to be done automatically
Haha, it happens, all good. 😄
For getting the components, if you are not already, this could be handy for ya https://docs.unity3d.com/ScriptReference/TypeCache.GetTypesWithAttribute.html
Can then loop through them and the root GOs of a scene and use GetComponentsInChildren
but there is still an edge case when user modified script and deleted the attribute from it, so I need to check components without this attribute to see if it was stored as a prefab before :/
but I will think about it, for sure it can be still used to optimise it to some degree
I don't have a good grasp of the system you have. But I think you should just be able to keep a list of the ones you found, and check if the store prefabs are of that type and any that are not can be removed.
But yeah, it is something that can be optimized later without effecting the larger structure of the project or running in to data loss or anything when refactoring
yeah funnily in this industry optimalization comes after the release, isnt it? XD
It is the whole "premature optimization" thing haha
There is a balance to be struck
just embrace the chaos! At my last job GoHorse was a required coding style
I'm not sure I posted my question in the right chanel since it's also for a custom editor, so I'm posting a link to it here : #1127691268995170376 message
@gloomy chasm im gonna try those ScriptableSingletons, but do you know if they need to marked dirty as well, or just call the Save() method inside? The fact that this method is there makes it confusing on how you should actually save data to disk...
You have to manually call Save
And you're not supposed to use SerializedProperties with them for some reason
hmmm ok, this is not an issue, I can set everything to public and not use properties if it is editor only at the end of a day XD
so it is Save insted of marking it dirty if using ScriptableSingletons, easy as that?
yeah understandable, only this part confused me
somewhere in my code a prefab instance is being unpacked and a prefab itself is being deleted. Simple thing, but when I switch scenes and then open that scene again, this unpacked prefab instance is no longer a simple game object, but again appears as a prefab instance with missing refference to a prefab.
Where could I be missing dirtying something? Scene should be marked as dirty after this unpacking or something else?
I hate it when something is called differently in api/docs and in actual editor, casue you never know if this subtle detail changes the meaning or actually not...
EditorSceneManager.sceneClosing is invoked when scene is removed from hierarchy? Api says "scene close", but in editor when you have multiple scenes opened additively context menu says "Scene remove" and im panicing over if I can use that XD
w8... ok api also says something about removing scene, it is not the same as closing it, but im not sure if i grasp the difference
ok so closing is just closing, removing is actually removing from a scene manager, but in case of EditorSceneManager closing and removing is same thing cause hierarchy is basically a manager in this case
Unloading might be closing
oh no no no... unloading is even another different thing XD
open/close, add/remove, load/unload, all these things are separate things that can be done with a scene, all different 🤯
hi, I'm poking around learning how to make an EditorTool. I seem to be in a place where if I use my tool, the Inspector stops updating when I click on game objects on the hierarchy. It updates when I swap to Debug/Normal, but not at all if I'm clicking on hierarchy objects. None of the code on my tool is being called that I can tell. I have this hook on BeforeSceneGUI:
{
if (!ToolManager.IsActiveTool(this))
return;
if (!_receivedClickUpEvent && Event.current.type == EventType.MouseUp && Event.current.button == 0)
{
_receivedClickUpEvent = true;
Event.current.Use();
}
}
public override void OnActivated()
{
_currentMode = Mode.FIRST_NODE;
SceneView.beforeSceneGui += BeforeSceneGUI;
}
public override void OnWillBeDeactivated()
{
SceneView.beforeSceneGui -= BeforeSceneGUI;
}```
and this is the very simple OnToolGUI code:
{
if (window is not SceneView)
return;
if (!ToolManager.IsActiveTool(this))
return;
if (_currentMode == Mode.FIRST_NODE || _currentMode == Mode.SECOND_NODE)
Handles.DrawWireDisc(GetCurrentMousePositionInScene(), -Vector3.forward, .1f);
if (_currentMode == Mode.FIRST_NODE && _receivedClickUpEvent)
{
firstNode = GetCurrentMousePositionInScene();
_currentMode = Mode.SECOND_NODE;
_receivedClickUpEvent = false;
}
if (_currentMode == Mode.SECOND_NODE)
Handles.DrawWireDisc(firstNode, -Vector3.forward, .1f);
if (_currentMode == Mode.SECOND_NODE && _receivedClickUpEvent)
{
secondNode = GetCurrentMousePositionInScene();
_currentMode = Mode.SHOW_LINE;
_receivedClickUpEvent = false;
}
if (_currentMode == Mode.SHOW_LINE)
Handles.DrawLine(firstNode, secondNode);
window.Repaint();
}```
any idea what might be going on?
Unity version is 2021.3.16f1
hm, it seems like calling Event.Use() on the mouse up event causes it
ok, I fixed it after some googling. It seems like I need to set a hotcontrol ID in order to use this properly
{
_receivedClickDownEvent = true;
GUIUtility.hotControl = GUIUtility.GetControlID(FocusType.Passive);
Event.current.Use();
}
if (_receivedClickDownEvent && Event.current.type == EventType.MouseUp && Event.current.button == 0)
{
GUIUtility.hotControl = 0;
Event.current.Use();
}``` This seems to make it work
midnight rubber-duck practice XD nice
btw you can put your code with proper formatting on dc, most of us are not colorblind ig, so it is easier to read :V just use
```cs
//Your code
```
Yo, I'm trying to make a cutom inspector for my scriptable object but I keep on getting NullReferenceException, seems it cannot find the properties in OnEnable()
Does it have to do something with it being the variables being a property and not a field? Or does it only work for MonoBehaviours and not ScriptableObjects? Or is it something else that I'm not noticing?
if my memory is not too bad, serializedObject only work in "OnInspectorGUI".
you can also "Debug.Log()" stuff to find if it's indeed the thing that is set to null
I watched a short tutorial on youtube on custom inspectors and the guy there used serializedObject outside of OnInspectorGui (in OnEnable, same as me here) and it did work correctly tho
tutorial can easily become outdated.
better be safe and print Debug.Log(serializedObject) to check if it's null
which is line 38?
Whoops, I mean, which line is the line where the error is?
^
Show me the enemy type declaration in the UniqueEnemy_SO
[field:SerializeField, Rename("Enemy Type")] public EnemyType enemyType { get; private set; } = EnemyType.None;
Make it a field, not a property
Oh, ok
you can make it [SerializeField] private EnemyType _enemyType and make a property passthrough for runtime code referencing, if you must.
That's what I was about to do
But you'll be using the "_enemyType" property name from now on.
Basically I have to make all these properties into private fields (for custom inspector) and use public properties for outside access, right?
Good, thanks

... or protected or public. It's really up to how you design it.
If you want to close off outside editing, seems like a good way to go
Probably private since it will be neither inherited nor edited from the outside
Yep... everything works correctly now.
Thanks once again 
I also have a custom property drawer for my enum that draws a little icon of the enemy next to the value in the inspector.
It works for MonoBehaviours but not for ScriptableObjects (I even commented out the custom inspector to check if that's the issue but it stays the same)
Is there a way to make my custom property drawer work also for scriptable objects (or is there some other class other than PropertyDrawer that I need to inherit from for this to work)?
it should work on both
And yet it doesn't for some reason..
Go through your code, maybe you have multiple ScriptableObject editors?
show the ScriptableObject implementation of the EnemyType
If you mean the custom inspector for this scriptable object then it's just
EditorGUILayout.PropertyField(enemyTypeProp);
The ScriptableObject script itself
The ScriptableObject is a Unity built-in class if that's what you mean
I only inherit from it, didn't touch anything else related to ScriptableObject
Oh ok, sorry then, I got confused for a bit there 😆
Oh, wait.
Maybe it's just my code that's messed up
I deleted the attributes and made it public
the icon appeared
Weird
_enemyType should appear in the inspector. However, I don't know what the RenameAttribute does.
oh.
it's the RenameAttribute fault
But as it turns out I don't really need it here since Unity automatically renames _enemyType to Enemy Type
It's all good again
Thanks
Same goes for the renamed variables below. No need for them to have the RenameAttribute.
PrefabUtility.GetNearestPrefabInstanceRoot() works only on in-scene instances? Cause I need to get nearest root having some game object that is s part of a prefab asset, not instance
and I get null this way :/
are ther alternative for in-asset game object, or do I just need to iterate through parents until there is none?
oh w8... transform has something called root too XD nvm
Is it possible to have the Editor create a new asset (like a scriptableobject instance) whenever a prefab varaint is created and then attach that scriptableobject to the prefab?
I'm guessing I would need to use AssetDatabase.CreateAsset?
Yup, and PostProcessAllAssets, along with AssetDatabase.AddObject. reading in to those 3 should get you what you want 🙂
How can I run the "Reconnect Prefab" command via code? I tried doing this:
PrefabUtility.ConvertToPrefabInstance(newRoot.gameObject, basePrefab.gameObject, new() {
logInfo = true
}, InteractionMode.AutomatedAction);
But it doesn't merge the prefabs properly.
Found the answer here: https://github.com/Unity-Technologies/UnityCsReference/blob/2022.3.0f1/Editor/Mono/Prefabs/PrefabReplaceUtility.cs#L317-L328
PrefabUtility.ConvertToPrefabInstance(newRoot.gameObject, basePrefab.gameObject, new() {
objectMatchMode = ObjectMatchMode.ByHierarchy,
componentsNotMatchedBecomesOverride = true,
gameObjectsNotMatchedBecomesOverride = true,
recordPropertyOverridesOfMatches = true,
changeRootNameToAssetName = true,
logInfo = false,
}, InteractionMode.AutomatedAction);
I do not quite understand how horizontal spacing works in custom inspectors... could someone explain to me why all of these are so different and how do I do it correctly?
Or if there is any property that I could access which returns the current total available width of the inspector window, so that I could calculate every property width manually.
Nwm, found it, it's EditorGUIUtility.currentViewWidth
Hello, anybody know some "visual editor" for scene objects.
I want to manage gameobjects like "nodes"
I mean i want this
manage as this
because when i make some action on scene it turns into hell
I have a question: I have a polimorphic base class inside a monobehaviour instance, with [SerializeReference] and a custom [PolimorphicList] attribute. I am trying to change the class type (childA, childB, etc) through the attribute's property Drawer, using managedReference, but it does not change. Why?
No idea without seeing the code.
I managed to solve it, it required a property.serializedObject.ApplyModifiedProperties();
But now I ran into another issue: when I change the field's type, it only updates when I deselect and reselect the object. Here's the code:
public class PolimorphicListDrawer : PropertyDrawer
{
private VisualElement _root;
private SerializedProperty _property;
private Type[] _subtypes;
private Type _baseType;
private Type _currentType;
public override VisualElement CreatePropertyGUI(SerializedProperty property)
{
_root = new VisualElement();
var label = new Label(property.name);
label.style.fontSize = 15f;
_root.Add(label);
_property = property;
_baseType = fieldInfo.FieldType;
_subtypes = _baseType.GetTypesInheritingFrom();
_currentType = _property.managedReferenceValue.GetType();
FieldInfo[] fieldsInfo = _currentType.GetFields();
foreach (FieldInfo fieldInfo in fieldsInfo)
{
SerializedProperty fieldProperty = _property.FindPropertyRelative(fieldInfo.Name);
_root.Add(new PropertyField(fieldProperty, fieldInfo.Name));
}
label.RegisterCallback<MouseDownEvent>(OnOpenContextMenu);
_property.serializedObject.Update();
return _root;
}
private void OnOpenContextMenu(MouseDownEvent evt)
{
var menu = new GenericMenu();
var menuRect = new Rect(evt.mousePosition, Vector2.zero);
foreach (Type subtype in _subtypes)
menu.AddItem(new GUIContent(subtype.Name), false, () => ChangeSubtype(subtype));
menu.DropDown(menuRect);
}
private void ChangeSubtype(Type newSubtype)
{
_property.managedReferenceValue = Activator.CreateInstance(newSubtype);
_property.serializedObject.ApplyModifiedProperties();
}
}```
And the class where this script is on:
{
[SerializeReference, PolimorphicList] public BaseClassDebugging testArray = new ChildClassADebugging();
}
Btw, it's not a List... please ignore the List in the name.
It is a work in progress and I'm still learning UIToolkit, so there is a lot of redundancies in the code yet.
as you can see, it does not change instantly. This is what I'm trying to fix.
The code in CreatePropertyGUI is only meant to run when you select it the first time and view it in the inspector. The only thing you do when you use the context menu is that you update a serializedObject, but you don't reflect that change in the GUI anywhere. You need to have a method that will update the contents of the _root VisualElement. I suggest you make and cache a subroot VisualElement container and have that be Clear()/repurposed and repopulated, with new bindings being made, on change.
GUILayout.Button(image.texture, GUILayout.MinWidth(20f), GUILayout.MaxWidth(propWidth), GUILayout.MinHeight(20f), GUILayout.MaxHeight(propWidth));
Is there a way to resize a button image?
I am trying to make an editor that allows me to snap prefabs onto a grid of a fixed size, and then export that collection of prefabs into its own object that I can spawn later. Should I build this from scratch using editor tools or does anyone know a package I can use that does what I want for me?
Thank you so much for the answer! I did exactly that, but for some reason it didnt worked. When I populate through CreatePropertyGUI using the exact same method, it works, but when I change through the mouse input callback, it doesn't draw the new fields
{
_root = new VisualElement();
_subRoot = new VisualElement();
label = new Label(property.name);
label.style.fontSize = 15f;
_root.Add(_subRoot);
_property = property;
_baseType = fieldInfo.FieldType;
_subtypes = _baseType.GetTypesInheritingFrom();
Refresh();
label.RegisterCallback<MouseDownEvent>(OnOpenContextMenu);
return _root;
}
private void OnOpenContextMenu(MouseDownEvent evt)
{
var menu = new GenericMenu();
var menuRect = new Rect(evt.mousePosition, Vector2.zero);
foreach (Type subtype in _subtypes)
menu.AddItem(new GUIContent(subtype.Name), false, () => ChangeSubtype(subtype));
menu.DropDown(menuRect);
}
private void ChangeSubtype(Type newSubtype)
{
_property.managedReferenceValue = Activator.CreateInstance(newSubtype);
_property.serializedObject.ApplyModifiedProperties();
_property.serializedObject.Update();
Refresh();
}
private void Refresh()
{
_subRoot.Clear();
_subRoot.Add(label);
_currentType = _property.managedReferenceValue.GetType();
FieldInfo[] fieldsInfo = _currentType.GetFields();
foreach (FieldInfo fieldInfo in fieldsInfo)
{
SerializedProperty fieldProperty = _property.FindPropertyRelative(fieldInfo.Name);
_subRoot.Add(new PropertyField(fieldProperty, fieldInfo.Name));
}
}```
results:
the propertyFields are not redrawing
i'm learning custom editors, but i have a problem with gameobject preview, what i'm doing is this:
gameObjectTemp = EditorGUILayout.ObjectField("Temporary GameObject", gameObjectTemp, typeof(GameObject), true) as GameObject;
if (gameObjectTemp != null)
{
if (gameObjectEditor == null)
{
gameObjectEditor = UnityEditor.Editor.CreateEditor(gameObjectTemp);
}
gameObjectEditor.OnPreviewGUI(new Rect(0, 0, 100, 100), GUIStyle.none);
}
DrawDefaultInspector();
the problem is certainly on the new Rect(...) but i'm not sure how to handle that.
you are mixing layout and non layout
EditorGUILayout
layout apis use automatic placement, if its not layout you have to manually place everything using rects
to solve your problem you have to define layout in such way that it allows you to draw preview in a specified area, which takes layout into account
for example you can define a horizontal group, draw your preview first in a BeginArea(), and then draw a vertical group with default inspector
or you can just define area, and then draw default inspector and it will be drawn under the preview
because default layout group with which you start is vertical
i see, thanks for the explanation!
will dig into it
I'd have to test it myself on my machine to try see what's going on.
Any chances it is caused by a bug?
I could share the git
or just the files, It's just a few scripts
You can DM me a Unity Package
Thank you so much for your help! I'l DM you
Idk if you already got it figured out. But why are you creating a property field for each sub property? A PropertyFIeld for the _property should do exactly the same...?
I want to change how it show up in the inspector in the future. Also, I'm still experimenting
The issue is still there. The fields of the new class type are being recognized but not drawn
Try calling propertyField.BindProperty(fieldProperty) after creating it
I'd like to show a given Editor conditionally, is there a simple method or property that's meant for this purpose,
or do I have to grab the internal Editor of a given object and display that when the Custom one isn't needed?
What do you mean show and editor conditionally?
for example:```cs
// NOTE: Edited
if (targets.Length < 2) ShowMainEditor();
else ShowCustomEditor();
so when there's multiple objects selected at the same time, I'd like to have a different Editor shown.
the example sucks I know xD
Do you mean you want the inspector to show a different properties. Or do you mean in your Custom editor, you want to show different properties/values/info when multiple objects are selected?
second! yes!
IMGUI or UITK?
whatever this is xD
Ahh, then you just do an if statement and check if it is multi selected or not
and when there isn't multiple, nothing gets shown xD
That is what you want?
nah, I'd still want the internal Editor to get display when there isn't multiple selected!
which can and I've done using Reflection, but I was curious if there's an easier an more reliant way of display the default Editor.
see, the thing is with the AnimationClipEditor it doesn't support multi-object editting...
so I wanted to make my own, however! I'd still want the normal Editor when there isn't multiple AnimationClips selected xD
DrawDefaultInspector();
that's what I thought as well xD except...
Ooh, you are overriding the AnimationClip editor. Nah, no way to access the default custom editor for it.
I guess going back to the Reflection way... thanks for assisting lovely warrior ❤️🔥
Nooo problem! Best of luck
sex!!!!
would you know how the (-) (icon?) could be displayed in a Toggle field?
it usually is displayed when multiple objects are selected but have conflicting values...
say A object has a boolean of false and B has it set to true and both are selected, this would appear:
notice how the Receive Shadows doesn't have a checkbox mark, nor is it empty!
I'd like to be able to obtain a similar result in a Toggle field! how would that be done?
It is a static property in like GUIUtility, or EditorGUI, or EditorGUIUtility called showMixedValues that you set to true before drawing the field.
This is the solution @fleet cargo
I was convinced that new PropertyField(serializedProperty) would automatically bind.
Yeah... you would think... but nah. It took me a good bit to realize that haha
Seems like something report-worthy
I am pretty new to extending the editor. I want my EditorWindow to draw handles in the scene, but I don't see a way to draw handles since there is no OnSceneGUI in EditorWindow. How do I connect my editorwindow to the scene view?
I searched through the history on this channel and I found a dead link to the forums 😢
Ok, I got it working by registering a callback to the SceneView.duringSceneGui delegate
Nice job searching about! That is indeed the right way to go about it. Just make sure to unsubscribe from it in OnDisable of the editor window.
;)
Hey friends! I'm pretty competent with C# but I've never done proper editor extensions before and just wanted abit of a vibe check, not asking for people to fully handhold me through it though don't worry,
Where would I start looking if I wanted to use custom icons for gameobjects in the Hierarchy?
You would subscribe to this event, and basically draw the Icon over the GameObject icon. https://docs.unity3d.com/ScriptReference/EditorApplication-hierarchyWindowItemOnGUI.html
Yes!! It worked! Thank you all so much \o/
My question doesn't fully fit this channel but the people doing stuff in this channel is who i'm looking for,
Has anyone here had experience in custom editor icons/sprites and how to match unity's built in sprite filtering settings?
I can't seem to replicate how the built-in ones are rendered
top is mine, bottom is built in
Just change the texture type to editor/GUI, everything else should be default
I don't think so but I didn't know about that texture type so thank you
the built in ones are using mipmaps
Well, that is what I do when I make them for my asset or work for clients.
It also depends on what you exporting. You might be exporting textures with hard edges.
Actually, looking at it, it does look like that to me. is the texture fully from scratch or are you getting it from somewhere?
the above comparison was extracted from unity
public void OnGUI()
{
GUIStyle areaStyle = new(GUI.skin.box);
areaStyle.margin.left = 10;
areaStyle.margin.right = 10;
areaStyle.normal.background = this.blackTexture;
if (!showUI) return;
GUILayout.BeginVertical($"Smyte v{Globals.smyteVersion}", areaStyle);
GUILayout.Space(20);
foreach (string replay in allReplays)
{
GUILayout.Label(replay);
bool attackingShipSelected = GUILayout.Button("Attacking");
bool defendingShipSelected = GUILayout.Button("Defending");
}
}
because im dynamically drawing buttons, how do i know which buttons are clicked?
IMGUI is handled immediately. You know whether a button is clicked because the boolean is true. You handle the side effects of the button being pressed immediately.
@south cedar
if( GUILayout.Button( "Attacking" ) ) {
// Attacking button was pressed
}
Trying to think of a way I can mark a mesh as temporary in our pipeline.
I have a custom scene builder (so I can merge scenes in source control) but im not entirely sure how I want to visualize it in the editor that a mesh is temporary and needs to be replaced. If a mesh is temporary or not is flagged in the scene builder metadata.
Any suggestions?
I assume you mean a mesh being temporary mean that a final art asset needs to be created for it still?
I guess the question would be, visualize to who or what? To developers, artist, whoever is building the scenes, source control or code?
either the final art piece needs to be created or the current asset is rejected by the designer.
I want to visualize it to the artist and flag it in the editor for them to adjust.
I managed to get it mostly working on the meantime, with some help from #archived-code-general,
by storing a tag in the labels of the assets that got rejected. then drawing something in the project view to show that the asset is indeed rejecting by using EditorApplication.projectWindowItemOnGUI
Got it, yeah that is a pretty decent way to go about it.
just need to fix the rect to draw on top right corner
Hey, I tried to make a custom editor to change the values of an array, but for some reason when I close the inspector and reopen it, the values are reset, any idea why this might be happening?
First be sure to share your !code but also, are you calling EditorUtility.SetDirty?
📃 Large Code Blocks
Large code blocks should be posted as links to services like:
https://gdl.space/, https://paste.ofcode.org/, https://hatebin.com/
https://paste.myst.rs/, https://hastebin.com/
📃 Inline Code
Surround code with three backquotes. Not quotation marks.
To get C# formatting the first line should only contain cs or csharp.
Add a comment with a line number if there is an error message.
```cs
// Your code here
```
Do not share screenshots of code unless requested.
I am!
Here's my code https://hatebin.com/qvbepwejma
I'm walking my dog and can barely see my phone because sun but somebody should be able to help you diagnose the issue, Unity's serialization can be a bit funnicky
no worries^^
If anyone can take a look at my code and help me I would appreciate it^^
https://hatebin.com/qvbepwejma
Unity can't serialize 2D grids. Also, no needto SetDirt, MakeSceneDirt, or SaveAssets. ApplyModifiedProperties takes care of all of that.
Well technically I don't need to serialize the arrays, I all want is the button grid to change the values inside the array
You mean change the value inside of the 2D array...?
yes
I have a 2D array, and by clicking the buttons in the grid, it changes the values inside it, so I can later use them to spawn walls or other objects
It's basically just a vizualizer, so I can see how the layout will look
If Unity can't save 2D arrays, what's the alternative?
Flatten it to a array. And convert it to a 2D array for runtime use.
Alright I'll look into it, ty!
Yeah, there is a lot of info online about how to serialize 2D arrays in Unity. So you should be able to find some good resources
A jagged array is easy to implement
Unity doesn't serialize jagged arrays either
(You can get around it be wrapping an array in a class I guess though)
I'm thinking of a manually implemented one
Yeah, but really just using a flat array and ISerializeCallbackReciver or OnEnable to reconstruct the 2D array is easy enough. But if you are going to use them a lot, a implementation makes sense.
Personally I hate writing custom serializers/deserializers and prefer to write a serializable alternative but that's just personal preference
Sorry, I wasn't trying to derail your suggestion, yours is good
Yeah, for me it depends on the situation and use-case. But yeah, both are good 👍
I got a few issues with the code in the following link <https://hastebin.com/share/puvaciyevo.csharp>
where an internal EditorWindow (obtained using Reflection) won't update on EditorWindow.Repaint() method call.
it's worth mentioning that when manually switching between AnimatorControllerLayers (which repaints the EditorWindow in a way), the changes visually appear!
something else that's also unexpected is when calling the Undo.RecordObject() method an AnimatorStateMachine object,
the call is successfully, however changes (on the given object) won't revert when an undo action has completed. (specifically the changes done in the above code reference)
I'd appreciate any type of help! <
>
Hi there, in Unity 2023.1.4f1 I can't find package for Visual Studio Code as script editor?. It's deleted or what?
Sad news then :/
thanks for informations
yeah, which is kinda dumb tbfh... they happilly announced it only to deprecate it two years later... so dumb
I was loving much more the load times and customization ways in VSC than VS
gets annoying when unity has a dementia moment and opens another vstudio window 😭
Hi. I am trying to write custom editor for string selector.
public abstract class StringSelectorPropertyDrawer : PropertyDrawer
{
protected List<string> stringList;
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
if (property.propertyType == SerializedPropertyType.String)
{
EditorGUI.BeginProperty(position, label, property);
var propertyString = property.stringValue;
if (stringList.Contains(propertyString) == false && stringList.Count > 0)
propertyString = stringList[0];
var index = -1;
for (var i = 0; i < stringList.Count; i++)
if (stringList[i] == propertyString)
{
index = i;
break;
}
index = EditorGUI.Popup(position, label.text, index, stringList.ToArray());
property.stringValue = stringList.Count > 0 ? stringList[index] : "";
EditorGUI.EndProperty();
}
else
{
EditorGUI.PropertyField(position, property, label);
}
}
}```
I have a problem: the label inside a struct is shown left. How can I fix it?
public class CardAnswer
{
public string text;
public List<RequiredResource> requiredResources;
[Serializable]
public struct RequiredResource
{
[ResourcesSelector] public string resource;
public float a;
}
}
public class ResourceSelectorPropertyDrawer : StringSelectorPropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
stringList = new List<string>();
stringList.AddRange(CardResources.instance.resources);
if (stringList.Count == 0)
{
Debug.LogWarning("Add resources to Card Resources asset");
}
base.OnGUI(position, property, label);
}
}```
How does one access PropertyField's native elements? Q<> goes straight to contentContainer it seems. I want to avoid using Reflection.
EDIT: I've used propertyType == SerializedPropertyType.Generic to work around this in other ways, but still not happy
Try using EditorGUI.IndentedRect on your position
Nothing changed
public abstract class StringSelectorPropertyDrawer : PropertyDrawer
{
protected List<string> stringList;
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
var pos = EditorGUI.IndentedRect(position);
if (property.propertyType == SerializedPropertyType.String)
{
EditorGUI.BeginProperty(pos, label, property);
var propertyString = property.stringValue;
if (stringList.Contains(propertyString) == false && stringList.Count > 0)
propertyString = stringList[0];
var index = -1;
for (var i = 0; i < stringList.Count; i++)
if (stringList[i] == propertyString)
{
index = i;
break;
}
index = EditorGUI.Popup(pos, label.text, index, stringList.ToArray());
property.stringValue = stringList.Count > 0 ? stringList[index] : "";
EditorGUI.EndProperty();
}
else
{
EditorGUI.PropertyField(pos, property, label);
}
}
}```
Welp, out of guesses then. Maybe the IMGUI debugger shows you something
@zealous tusk Can you delimit with a colored rectangle what exactly the PropertyDrawer changes? Each PropertyDrawer instantiation
EditorGUIUtility.labelWidth = 15f; and EditorGUIUtility.labelWidth = 150f;
15
That's an interesting bug you found 😛
Try creating a Label with the text and a popup with an empty GUIContent
I mean the main issue is tha the rect they're getting starts too early
Guessing it's some issue with nested lists o something like that
I second what Navi is saying. Looks likea bug with nexted lists
var pos = EditorGUI.PrefixLabel(position, label);
index = EditorGUI.Popup(pos, GUIContent.none, index, stringList.ToArray());```
EditorGUILayout in PropertyDrawers is likely only going to cause more issues
small google copy/paste mistake
Fair
Worth a try but skeptical it'll fix it
Best guess is updating to the latest patch
Well, thanks
Did my suggestion present the same results?
This is why I hate IMGUI and love UIToolkit. In UIToolkit you still have issues, but you get away with creating custom elements that fix your issues and just reuse those custom elements everywhere. For example, making a custom inspector label correctly aligned with native editor labels.
I doubt this would be easier to fix in uitk since it's only this specific use case likely (which is hard to detect)
How do I make it so an editor script can do something once when an object is selected?
what I'm trying to do is cache a component
whenever I focus on an object, I want the editor script to initialize component references
so I can store them when I use them in onscenegui
Selection.selectionChanged
doesnt look like its an editor method
oh nvm
its a unityeditor class
this stuff is confusing
so i subscribe to it on enable in the editor script?
and unsubscribe on disable?
I'd subscribe in https://docs.unity3d.com/Manual/RunningEditorCodeOnLaunch.html
If you want it to always be active
How can I draw a gizmo in the world of the scene view from the mouse position when I have focus on a heirarchy object?
from inspector or editor window?
How would I go about dealing with PrefabUtility.GetPropertyModifications()? Docs say it's like SerializedProperty.propertyPath. That's quaint, but how would I go about examining the modification to know if it's referring to a child's property? For example, a nested child's enabled (m_enabled) property. Mainly asking since the docs don't say anything and I could potentially break my system if I try to print it the values and see.
I'll try anyway, I guess.
d'oh
Sorry, just thought asking would be easier than trying.
Version Control anyway.
Chances are you can just use FindProperty on the SO of the target with propertyPath as param
Good idea, thank you.
Never done this though but looks like the intended way
Intended
Unity
pick 1
/s
Also, for some reason PropertyModifications() can return null instead of being empty.
okay, so, yeah, it seems, these propertyPaths aren't ordererd/hierarchy'd in any way
I suppose it would make sense for that since they do provide an object reference (for once).
Thank you for the advice and rubber-ducking!
Is it possible to add custom List to AudioSource Editor?
A list of what?
Of audioClips
No, you would need to make a custom script that sets the audio clip on the audio source from the list accordingly
does unity has popup message like this, that just an info, so no button, that was using EditorUtility.DisplayDialog which return bool, which when we we press OK its true, Cancel its false....what i want simply just a message and close button only
Then just don't use the bool
Why do you want a message box with no button anyway. Just don't give it a cancel text and don't use the bool it returns.
The dialog disappears whether the user presses OK or the close button
Like this EditorUtility.DisplayDialog("Success", "Task successful.", "OK");
okay then, before i tried to empty the ok text, the button still show up, i just thought unity have something like info popup built in
ok and cancel are labels to be displayed on the dialog buttons. If cancel is empty (the default), then only one button is displayed. DisplayDialog returns true if ok button is pressed.
all right, thanks, now its looks more like info....anyway another question, so that's my Level Creator Editor Window, as you see the position of that window, not always at center on my screen, so if i want display something at the center of my Editor Window( with relative to its size and position) how can i achieve that?, what is math calculation behind it?, thanks
OnGUI is relative to the window
and Screen.Width/Height return the current editor window size
you can use ListView for this and make your own template for those audioClips with ObjectField
Ty
assuming what you asked was uitk that is 😂
Hi ! I'm playing with ui toolkit and i am trying to make a simple list of 3d models with their preview using AssetDatabase.GetAssetPreview. The issue is, some previews load correctly, but others don't. I understood that the preview isn't always available, so I check IsLoadingAssetPreviewFirst, but the result is still the same. I did a small method to fetch it, but i might be doing something wrong.
public async Task SetPreview(Object modelObject, CancellationToken cancellationToken)
{
do
{
if (!AssetPreview.IsLoadingAssetPreview(modelObject.GetInstanceID()))
{
_modelPreview.style.backgroundImage = AssetPreview.GetAssetPreview(modelObject);
}
await Task.Delay(10);
}
while (_modelPreview.style.backgroundImage == null && !_previewCancellationSource.IsCancellationRequested);
}
I know the use of task with Unity API isn't thread safe, I'll change it in the future, but I wanted to see if it would work better with and async approach.
I'm using Unity 2022.3.5f1 btw
📃 Large Code Blocks
Large code blocks should be posted as links to services like:
https://gdl.space/, https://paste.ofcode.org/, https://hatebin.com/
https://paste.myst.rs/, https://hastebin.com/
📃 Inline Code
Surround code with three backquotes. Not quotation marks.
To get C# formatting the first line should only contain cs or csharp.
Add a comment with a line number if there is an error message.
```cs
// Your code here
```
Do not share screenshots of code unless requested.
as long as you're not touching the threadPool, should be fine
I might have found what I was doing wrong: I assumed that the cache was kinda automated on the Unity side, but it appears it was too small to contains my previews. Increasing it with SetPreviewTextureCacheSize (https://docs.unity3d.com/ScriptReference/AssetPreview.SetPreviewTextureCacheSize.html) did the trick.
Does anyone have good ideas to profile an async method in the editor? I can't use GetAwaiter.GetResult since it'll deadlock, Just starting the profiler and ending it doesn't show all that much since it's a few minutes long 😬
did you try to await it, and make the calling code asynchronous?
There are reasons why this is happening, especially in Unity. Which for obvious reason
read this, a splendid write up by Stephen Cleary
This is a problem that is brought up repeatedly on the forums and Stack Overflow. I think it’s the most-asked question by async newcomers once they’ve learned the basics.
Yes I know how async works
But unity profiler doesn't like async so much
So to fix that you can block it and it'll provide useful data in the profiler
The operation runs over 5 minutes sometimes and thus you can't really save enough samples in the profiler to get meaningful data
I wasn't doubting your c# skills 🥹 just want to point out that what the article says apply to Unity as well
Yeah sorry, didn't mean to be offensive
Problem isn't really async or C#, but how to make the unity profiler provide useful data for editor async code
it should, we heavily rely on async/await in edit-mode for our tools here. What Unity version you're using?
tho we're using our own internal library for this
2021 something
can you show the snippet at least?
The code snippet?
yeah
That's a few thousands lines of code 😛
ffs 😂
It's also in probably 3 different projects
And a bunch of reflection, serialization, and downloading
just fyi, that async/await on runtime does not respect Unity's frame timing at all. To do so we need CustomYieldInstruction
As for edit-mode, I'm not too sure about this
Oh yeah we don't care about that
tho I can try and peek what we have here for the edit-mode 😂
It's completely separate from anything frame related
Hiiiii
Tbh, I feel like it's not being caught by the profiler at all
it's still important tho, to guarantee one process has higher priority than others OR order of execution etc
it's just I'm not really sure how it works while in edit-mode
Ok I think I figured out why it wasn't working very well
It's in a Task.StartNew somewhere
And Unity loses track of it somehow
Any reason why factory method ? just curious. You can set Unity SyncContext in your factory method incase you're doing something funky
No idea tbh
guessing it's something about doing things in the background more neatly
@peak bloom 😬
Not quite sure what your code is doing, sometimes they're make sense (depends on what you're doing) but... 😄
technically by default async/await will allocate more than coroutines. Which can be tackled pretty easily with custom AsyncMethodBuilder but this pretty much useless nowadays due for a fact we have Awaitable api now in 2023 🤩
speaking of awaitables, does it even work in edit-mode 🤔
Oh yeah not too worried about it just looks funny
before I go, just want to say, avoid factory methods
when you need to run some CPU-bound code asynchronously use Task.Run asynchronously instead
a good reading material regarding this https://jamiemagee.co.uk/blog/common-async-pitfalls-part-one/
The .NET Framework provides a great programming model that enables high performance code using an easy to understand syntax. However, this can often give developers a false sense of security, and the language and runtime aren’t without pitfalls. Ideally static analysers, like the Microsoft.VisualStudio.Threading.Analyzers Roslyn analysers, would...
aight, gtg
This new menu option is useless and obstructive. We already have a "Properties" option at the botttom of the menu and I end up clicking this one by mistake every time I want to click "Show in Explorer".
Does anyone have an idea if a built-in menu option in Unity can be hidden with a custom script? I am even open for Reflection suggestions.
I've got a question: I already managed to make my custom polimorphic data visualizer using UIToolkit, but now I want to apply it to lists.
SerializeReference attribute is directly applied in each element of a list, if applied in one. How can I do this? Or do I need to create a custom attribute for lists?
I've got my [PolimorphicField] attribute. When applied to a list, I'd like it to be applied into each element. A 'for' loop inside the propertydrawer would be appropriate?
The drawer will also be applied to list members
Is it possible to check through reflection what each type is supposed to be, if it is a list?
The script doesn't work because I'm using fieldInfo.FieldType, I'm currently making a checkMethod to get the element of the list if it is a list
I've written a serialized reference dropdown before, I forget how I did it https://github.com/vertxxyz/Vertx.SerializeReferenceDropdown
There's some internal Unity functions that can do it, also can write your own. It's a bit of a mess either way
Did you made it with IMGUI or UIToolkit?
I managed only with UIToolkit, with IMGUI was too painful for me
As for drawing the list elements, I'm still doing it
It supports both, IMGUI support is optional because it uses IL weaving
I'll take a look at it
Ok, it is working. I can change the type of the object in the list, but it is kinda weird and giving an error
How can I programatically open the Sprite Editor window for a specific sprite?
I see there is the "Data Provider API" but the examples are super vague, so I'm really unclear on what it does and why I should use it over calling the methods and extension methods on Sprite directly, and they don't shine a light on if I can display an editor for interactive use.
My use case is I'm writing a custom importer for a specific image format and the produced asset should be a Sprite. I got the basics of that working already, but I would hate having to re-implement the whole border and physics editor functionality myself.
[UI Toolkit]
Is it possible to set Flex Direction via code for a newly created Visual Element or do I have to create an asset preset and spawn it from the Resource folder?
Yup, same with any other style property element.style.flexDirection = FlexDirection.Row;
Thanks. 🙇
Might have to use reflection to open the SpriteEditor window. I would look at the source code to see how the inspector for the sprite handles opening it.
I don't know what you need exactly for your imported asset, but you could possibly just use the AssetDatabase.SetMainObject(..) method to set the sprite as the main asset and automatically get the ability to open the window.
The TextureImporter which does it is implemented in native code, so I'm not sure how to go about it.
What do you mean by the second part? Making the sprite the main object is not a problem, and in fact I am already doing that, but I don't see how it provides the ability to open the window?
So, someone has put me in their cloud project, how do i access it?
Can I use a propertyDrawer on a class declaration, to create a button to change the type of an instance of the class to a subtype?
It works perfectly on the instance of the object, but gets weird behaviour when adding/removing from lists
I found a solution using OnGUI, but I'm trying to use UIToolkit
Ok... If I wrap the classes on another class and put it in a list, it works without errors.
That's enough for me.
Is this using my drawer? What's the setup and version that causes this?
Actually, it was a different foldout git. I'm using Unity 2022.3.4f1. I'll share the scripts
Ah if it wasn't mine I'm not fussed to see it. I just was gonna fix it if it was that bugged!
Was yours made with UIToolkit or IMGUi?
If you dind't use UIToolkit it probably is working, I tested this one https://github.com/mackysoft/Unity-SerializeReferenceExtensions/tree/main and everything went fine. But he is not using UIToolkit.
As I said, both
Mine's complex because it supports nested property drawers
Did anytime you got this error?
I get this whenever I assign a new value to property.managedReference, if null
This happen only to lists
No I've never seen that one before
Fuck it. I give up. I'm gonna use someone else's code.
lmao, so angy 🤭
Also: the solution I made doesn't work with OdinInspector. The solutions I found on GitHub doesn't either. I basically need to rewrite it for Odin. It feels like UIToolkit is full of gremlins haters of polimorphism.
I need a way to expose Func<bool> in the inspector.
Something like this but for Func<bool>
It doesn't exist, you would have to find or make a custom implementation
Hi there, I have an Enemy which maintains a list of Vector3 positions called path, each Enemy maintains this list so it can use this positions as waypoints.
public class Enemy : MonoBehaviour
{
public List<Vector3> path = new();
public List<Vector3> tempWaypoints = new();
// draw the path and tempWaypoints
private void OnDrawGizmosSelected()
{
...
}
}
I wanted to automate this process so I used a editor script, I added tempWaypoints to Enemy for debugging and two buttons, one to add a waypoint and second to assign the waypoints
#if UNITY_EDITOR
namespace DEBUG
{
[CustomEditor(typeof(Enemy))]
public class PlaceWayPoint : Editor
{
private Enemy _enemy;
private void OnEnable()
{
_enemy = (Enemy)target;
}
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
if (GUILayout.Button("Add Waypoint"))
{
_enemy.tempWaypoints.Add(_enemy.transform.position);
}
if (GUILayout.Button("Assign Waypoints to Enemy"))
{
_enemy.path = new List<Vector3>(_enemy.tempWaypoints); //
_enemy.tempWaypoints.Clear();
}
}
}
}
#endif
I am using this script to add waypoints and assign it to an enemy to store it in path when I am not in play mode. When i enter the play mode I can see that it is there in path but as
I exit the play mode the enemy resets. Is this default behaviour? How can i make changed by editorscript be persistent? I know it's fairly basic so I am not sure if I shouldn't ask here. Do tell me if I need to move to other channel and i will do so.
Changes are always reset if they are made in playmode, however edit-mode changes can be persisted using one of the methods that are pinned to this channel
i made the changes in edit mode
oh okay, I'll look at the pinned message
ah so i just need to do ApplyModifiedProperties() on the SerializedFields
Figures. Maybe I'll start with the UnityEventDrawer source code.
