#↕️┃editor-extensions
1 messages · Page 33 of 1
Hello people. Do you guys happen to know how I could add an additional button here, in the view options list?
Only way is to use reflection unfortunately.
Ah damn, I was hoping it was extensible. Oh well, I'll create a separate EditorWindow instead
You can add your own overlays and toolbars, just hard to add them to existing ones
oh I can create my own toolbar? Do you have the documentation page for that? I can't seem to find it.
Sure, this is a good starting point with a lot of links https://docs.unity3d.com/6000.0/Documentation/Manual/overlays-custom.html
Thanks dude, I think I can work from this.
anyway to get the property type of a [SerializedReference]?
.type is just managed reference and so is .propertyType
.GetPropertyType() returns an actual type but it seems to return null when managed reference is null
is the only way to just make different propertydrawers
what are you doing? you want to find all users of this attribute and check the field type?
I want one property drawer to work on FloatGetter, VectorGetter, and BoolGetter. I want the drawer to be able to figure out which type it is.
I presume unless you can get FieldInfo for the field its gonna suck to figure out with a custom drawer
i dont know if you can for a serialized property but FieldInfo would provide Type so you could do this checking.
Ofc the easy way is to define a custom drawer for these 3 types
no thats the type of the reference itself, thanks for looking tho
oh but not the "defined" type? how confusing 😐
okay my only other idea is getting the type of the monobehaviour and getting field info with the field name via Type.GetField()
anyway am I dumb I thought a propertyfield was supposed to draw the label automatically?
[CustomPropertyDrawer(typeof(FloatGetter))]
public class FloatGetterDrawer: PropertyDrawer {
public override VisualElement CreatePropertyGUI(SerializedProperty property) {
VisualElement element = new VisualElement();
var dropdown = new DropdownField(new List<string> {"Hi","Hello","Goodbye"},0);
element.Add(dropdown);
return element;
}
}
public void RefreshAnimationProperties(VisualElement element,SerializedProperty property) {
element.Clear();
switch ((AnimationAction.AnimationSpeed)property.FindPropertyRelative("animationSpeed").enumValueIndex) {
case AnimationAction.AnimationSpeed.Length:
element.Add(new PropertyField(property.FindPropertyRelative("speedGetter"),"Length")); <--- should have this label
break;
case AnimationAction.AnimationSpeed.Multiplier:
element.Add(new PropertyField(property.FindPropertyRelative("speedGetter"),"Multiplier"));
break;
}
}
if not, how do I make the label show up? I could do it manually but then it wont be properly aligned
this is when you set a dropdowns label and is totally unacceptable, plus idk how to get the label out of the property itself
i only know the old editor gui way, using PrefixLabel 😦
also I finally see what u mean by getting the fieldInfo out of the propertyfield
hopefully that worked or got you closer
im still totally stumped on why propertyfields are so weird and bad
why they have different lengths for no reason
@wanton arrow just going to shotgun answer your questions.
Anyway to get the property type of a
[SerializedReference]?
Assuming you mean viaSerializedProperty, you can use.managedReferenceFieldTypeto get the defined type, akapublic MyBaseClass myField;.
And you can use.managedReferenceFullTypenameto get the type of the value assigned to the field, akapublic MyBaseClass myField = new MyDerivedClass();
I thought a propertyfield was supposed to draw the label automatically
Not dumb, but it is just like the IMGUI where all it gives you is a space to 'draw' stuff, and you get to decide what goes there. So you specify the label.
idk how to get the label out of the property itself
That would be.displayName
getting the fieldInfo out of the propertyfield
For reference, you should never do this because if you, or anyone else ever puts a field of that type inside another class/struct, it will break the drawer.
why they have different lengths for no reason
Labels in the inspector are a bit funky, both in IMGUI and UIToolkit. In this case, you need tomyField.AddToClassList(BaseField<string>.alignedFieldUssClassName));. That will tell the inspector it should control the width of the label instead of letting the layout engine control it.
ur a saint
However I should have been more clear in saying that I dont want the property label, I want the label assigned to the propertyfield
new PropertyField(property,"Speed") <- the custom one
seems like unity just doesn't let u do that in 2021 tho
theres no .preferredLabel
.label
There is literally this... no?https://docs.unity3d.com/2021.1/Documentation/ScriptReference/UIElements.PropertyField-ctor.html
yes there is, I want to get the custom label assigned there in the propertydrawer
there seems to be no way to access it
Huh? Can you show what you mean, I don't think I am understanding, sorry.
so I have to make my own class to have a custom label thats different than the one assigned to the property
do you see the label arguement thats being put into the constructor
Yeah
Yeah
a custom property drawer cannot (from my understanding) see what that label is in unity 2021
which means it can only have the default label
but I want custom labels to work
Oooh you mean a custom PropertyDrawer using UIToolkit can't use the passed in label?
yes
in unity 6 they have .preferredLabel but not in 2021
its a small thing but if you want that feature you literally cannot use PropertyField I have to make my own
so i think thats what im gonna stick with
-# because unity doesn't like finishing features before they are released
Huh yup looks like it isn't possible
Does anyone know of a way to somehow inherit SerializeField attribute? I have an attribute that works on serialized fields only and it's very annoying to do [SerializeField, MyAttribute] when I can just do [MyAttribute]. Apart from custom serialization callback shenanigans.
SerializeField is explicitly sealed so i think the answer is no, unity doesn't want you doing that 🥲
rude
propertyCopy = property.Copy();
Debug.Log("loading " + propertyCopy.displayName);
dropdown.RegisterValueChangedCallback((evt) => {
var constructor = evt.newValue.type.GetConstructor(new Type[0]);
if(constructor == null) {
Debug.Log("No Constructor without arguments exists for " + evt.newValue.type.Name);
return;
}
Debug.Log("setting " + propertyCopy.displayName);
propertyCopy.managedReferenceValue = constructor.Invoke(new object[0]);
//propertyCopy.serializedObject.Update();
RefreshDisplay(lowerDisplayElement,propertyCopy);
});
utterly confused. so I want to set the managedReferenceValue of a property but its saying the type is different. I double checked what property it was setting and it turns out it is setting the parent property? for no reason? I tried to copy the property and store it in the element but no dice.
when the element is loaded it prints "loading speedGetter" and when I change the dropdown it prints "setting Element 0" ??? why would this happen. why is the property a different one
var enumerator = property.GetEnumerator();
while (enumerator.MoveNext()) {
var prop = enumerator.Current as SerializedProperty;
if (prop == null) continue;
//Add your treatment to the current child property...
Add(new Label(prop.displayName));
}
my guess is it has something to do with this code, but idk why it would since i dont seem to be modifying the property AND im using a copy
so idk what im supposed to do instead
you can use a debugger with editor code btw
yea you may need to check it line by line and investigate the whole state of the serialized properties to figure out shit
Is there a standard or common place I should put my tool under the dropdown menu of the window? i.e., MenuItem("..."). What do people generally prefer? I've been doing "Custom/..." or "Tools/..."
i usually do Tools/ too
seems like
- the enumerator stuff does change the original property
- property.copy doesn't copy the property
which is weird as hell
yea the doc page says it meerly copies the enumeration state or somethin
I want it to do exactly what it says
but it doesn't?
"Returns a copy of the SerializedProperty iterator in its current state. This is useful if you want to keep a reference to the current property but continue with the iteration." ???
you probably need to get an object out of it to do a copy of the serialized prop val
is the serialized property an array/list/object?
when do you do this copy and why is it needed?
I'm doing the copy on the instantiation of a new visualelement and its bc the property gets enumerated afterwards
I need it for when the user interacts with the element
it works 
id rather it not have to be that way but it honestly might just be unity sucking ass
and the copy doesn't work in this special case that isn't documented
Oh right, so you enumerate over each one but make a copy for that particular "instance" to use?
no i enumerate afterwards to display all the properties it has
i bet its got something to do with using a managedreference
probably as usually you use the specific functions to interact with the object or array element
this whole property enumeration thing isn't my favorite
i feel like it made a lot more sense before uitk
or maybe i just dont understand it
but its certainly not SIMPLE
im totally lost
Never fear, for Mech is here! Can you share your enumeration code?
public class GetterDisplay : VisualElement {
public GetterDisplay(SerializedProperty property) {
var enumerator = property.GetEnumerator();
while (enumerator.MoveNext()) {
var prop = enumerator.Current as SerializedProperty;
if (prop == null) continue;
if(prop.propertyType == SerializedPropertyType.ManagedReference) {
if(prop.managedReferenceFieldTypename == "Assembly-CSharp FloatGetter") {
Add(new GetterView(prop,Variable.Type.Float,prop.displayName));
}
if(prop.managedReferenceFieldTypename == "Assembly-CSharp BoolGetter") {
Add(new GetterView(prop,Variable.Type.Bool,prop.displayName));
}
if(prop.managedReferenceFieldTypename == "Assembly-CSharp VectorGetter") { // i know this sucks but idk how else to do it lol, maybe nameof? idk
Add(new GetterView(prop,Variable.Type.Vector,prop.displayName));
}
} else {
Add(new PropertyField(prop));
}
}
}
}
ok so this is the getterdisplay (ik the names are confusing) which goes inside the getterview:
heres the getterview, I would trim it down but I might remove important parts
so as far as I can tell either
- a child getterview enumerates the whole property so only the first one shows
- I copy it, and then the normal enumeration displays the child properties as normal properties and theres duplication
this is when the property is not being copied
and this is a result (there should be a B Getter under it)
this is if I copy the property before it goes into the getterview
as u can see it just continues to the child thats already been loaded
I assume what I want it to do is each getterview only go through all of its properties so that when I get the property back it just goes to the next top-level property
its probably the nested enumeration
I tried .Next() but that doesn't stop it just keeps going
The issue is here
dropdown.RegisterValueChangedCallback((evt) => {
var propertyCopy = property.serializedObject.FindProperty(propertyPath);
});
Or
Add(new GetterView(prop,Variable.Type.Float,prop.displayName));```
The issue with the top one is that the delegate is capturing the property that is passed in, but you are then enumerating passed it in the outer scope.
You use property.GetEndProperty() to get the last property before you start iterating, and compare the 'current' property against it with SerializedProperty.EqualContents(current, endProperty)
Or you can do
// Important to not use 'var' as otherwise it will be 'object'
foreach (SerializedProperty childProp in property.GetEnumerator())
{
}
whats the issue with that? and how would I do it differently
thats why im only using it for the serializedObject
since copying outside didn't work
i just store the path
Ah sorry @wanton arrow I didn't finish reading what your issue was, I was going off of what I had read before about getting a mismatch type. That's my bad.
Where is the GetterView getting used, seems like that is where the issue would be
for now just here, and inside the GetterDisplay (because getters can contain getters)
And where is that getting used (trying to figure out where the property is coming from and iterated on)
inside AnimationStateView which is inside StateView which is inside StateMachine
while (property.Next(false)) {
if (property == null) continue;
if(property.propertyType == SerializedPropertyType.ManagedReference) {
if(property.managedReferenceFieldTypename == "Assembly-CSharp FloatGetter") {
Add(new GetterView(property.Copy(),Variable.Type.Float,property.displayName));
}
if(property.managedReferenceFieldTypename == "Assembly-CSharp BoolGetter") {
Add(new GetterView(property,Variable.Type.Bool,property.displayName));
}
if(property.managedReferenceFieldTypename == "Assembly-CSharp VectorGetter") {
Add(new GetterView(property,Variable.Type.Vector,property.displayName));
}
} else {
Add(new PropertyField(property));
}
if(property == endProp) break;
}```
I tried this, but it just goes off the edge over into siblings. Idk how its supposed to be used
do you need to "copy" for each getter view creation? im not sure how it works
Not what I was looking for, but does this code even work...?
heres the answer to your question
I could show all of that but it would be a lot and likely not relevant?
as I say above, I tried that but the enumerator just goes to the child and displays it twice, once inside and once outside
if(SerializedProperty.EqualContents(property, endProp)) break;
changed the comparison line, and now it shows absolutely nothing lol
at this point im just trying random shit and seeing what works which is not how one should program but with a lack of resources about how this all works in detail its all I can really do
you repeat yourself a lot which isn't good for finding mistakes. also try to use nameof() instead for prop names.
The docs for this part of the API is actually pretty decently documented with examples, so I would recommend taking a look at them.
But to try to summarize it. The SerializedObject is like a tree of all of the serialized data in an object. And each SerializedProperty is a reference to an item in that tree. Where things get confusing is that you can change what data item a SerializedProperty is referencing.
So lets say you have a simple example like this
public class MyComponent : MonoBehavior
{
public Foo myFoo;
public int myInt;
}
public class Foo {
public string bar;
}
And you get foo
var serializedObject = new SerializedObject(myComponentInstance);
var myProperty = serializedObject.FindProperty("myFoo");
That is all well and good, we have a SerializedProperty (myProperty) that references the data item myFoo.
Now we can either change the what data item is being referenced by myProperty by doing myProperty.Next(false);, which will not (false) enter the child of the data item, and instead go to the next sibling (myInt).
Or we can change the reference to be the first child data item of the property by doing myProperty.Next(true); which, as you might expect, will (true) enter the child of the data item.
So in this code, when you do while(property.Next(false)) you are telling it to just go to the sibling of the current property.
i realized that and changed it to true, which got much worse results
but maybe it was bc I had a copy in there hold on ugh
ctrl shift z
I assume what you want is to iterate the children of it?
In which case you would want to do
if (property.Next(true) // We want to enter the children.
{
// We use a Do-while loop because 'property' now references the first child already.
do
{
// the code here
} while (property.Next(false))
}
aha that makes sense why copy works as it does 🤔 Good explanation
I had an idea like that ill give it a go
that will still go to siblings it seems
InvalidOperationException: The operation is not possible when moved past all properties (Next returned false)
This will now iterate all the children. But wait, it will continue on to all of the siblings of the parent property after it has finished the children!
That is where .GetEndProperty() comes in.
// This will give us the last child of the property, that is why we need to do it before entering the children with .next(true)
var lastChild= property.GetEndProperty();
if (property.Next(true)
{
do
{
} while (property.Next(false) && !SerializedProperty.EqualContents(property, lastChild))
}
right
Yeah, it is basically just giving you a copy of the reference to the data item. Thanks 😄
public GetterDisplay(SerializedProperty property) {
//var enumerator = property.GetEnumerator();
var endProp = property.GetEndProperty();
if (property.Next(true))
{
do
{
if(property.propertyType == SerializedPropertyType.ManagedReference) {
if(property.managedReferenceFieldTypename == "Assembly-CSharp FloatGetter") {
Add(new GetterView(property,Variable.Type.Float,property.displayName));
}
if(property.managedReferenceFieldTypename == "Assembly-CSharp BoolGetter") {
Add(new GetterView(property,Variable.Type.Bool,property.displayName));
}
if(property.managedReferenceFieldTypename == "Assembly-CSharp VectorGetter") {
Add(new GetterView(property,Variable.Type.Vector,property.displayName));
}
} else {
Add(new PropertyField(property));
}
} while (property.Next(false) && !SerializedProperty.EqualContents(property, endProp));
}
}
this also does not work, sadly
its not only display only the first property of the getter
but also for some reason making all other getters render weird (seems like they are using default propertyfields?
it might be something to do with this code skipping too far ahead?
I think it does
getEndProperty is its next sibling or parent
I think I want the iteration to be only on the last child
imma try swapping the terms of the bool expression
You might need to put EqualContents before the Next in the while statement
I can't remember for sure
I tried that and I got this error
goddammit
well its an and
so it evaulated them both
so imma try a break inside the while
Yeah but property.Next(false) mutates property
I dont want it to run on the last time
in theory it should work tho, assuming it wouldn't run property.Next() if the first one returns false
and would move on
grrr
You can also just try doing a foreach since that is the same thing as what you are trying to do (iterate the direct children)
foreach(SerializedProperty prop in property.GetEnumerator())
{
}
i tried that first
not a foreach loop
i could try the foreach loop lol im out of other options
Ahh shoot nvm, it enters the children
Er sorry you just do the foreach on the property
why the hell is this so difficult
i dont even have a good grasp of why the other 80 tries didn't work so idk what else to do but try everything
I really thought this would work
I would try simplifying it a bit, at least from what I have seen, it feels a bit over-engineered (I am guilty of this sometimes) which is making it more complex to debug because there are so many potential points of failure.
it should do
I dont even know how id start doing that
trying debugging
ugh I almost have something
it doesn't exit property tho
oh
huh
nvmd im still as confused
Sorry I don't have good recommendations for how to simplify, that would take a larger understand of the system than what I have.
I notice some things like Variable.Type which seems like it might be redundant if since there is the System.Type. Looks like you also have FloatConstantGetter and FloatGetter.
Not sure if that is helpful or not (you don't need to explain it if that isn't the case)
For the editor side, it is minor, but you can look at TypeCache to simplify some of your type searching.
this issue is its exiting early for reasons I can't really figure out, and the debugger just stops debugging earlier than I would expect it to
how do you mean stops?
Variable.Type is an enum, FloatConstantGetter is a subclass of FloatGetter
Right, what I mean is that Variable.Type.Float means it is FloatGetter (or a subclass of it).
I think in this instance ur right that I dont need to pass that in
if I instead looked at the fieldtypename
like I do here

i dont really see a big difference tho
both suck in their own way
But anyway, I gotta get back to work, sorry I couldn't help more.
its ok, thank you so much for all the help you did give
i THINK
my problem is
I want to exit out of the loop one before the end property
but idk how to do that
i was right I did it!
lovely
except
oh no the others are just not implemented right
what glee
Hello guys 🙂
I'm trying to modify the global volume profile from script (before play). Following the documentation (tried other stuff but let's come back to this) :
if (!GlobalVolume.sharedProfile.TryGet<GlobalIllumination>(out var rtgi))
{
rtgi = GlobalVolume.sharedProfile.Add<GlobalIllumination>(false);
}
rtgi.enable.Override(true);
rtgi.enable.value = true;
I click on a button in the inspector to do it, and it works fine.
But when I start the game, the changes are removed. I guess I'm missing some serialization stuff ?
set as dirty / register prefab modifications
EditorUtility.SetDirty() on the mono so the changes can be saved to the scene/asset
See the second pinned message in this channel
Damn, I almost tried this one too x) Thanks 😄
That one didn't work, probably because it's a volume profile
You gotta se the volume profile dirty, not the volume iself
Yeah I tried both, or maybe I missed ?
I guess I'll try again ^^
This totally lost me.. can anyone explain whats going on here? I just want to know if this field has the focus or not- but just drawing the control seems to change that (well, not really, just the return value of that GetNameOfFocusedControl function): ``
Debug.Log("Before TextField: " + GUI.GetNameOfFocusedControl());
GUI.SetNextControlName("GlurthsTextField");
string newFilter = EditorGUI.TextField(filterRect, label, currentFilterText);
Debug.Log("After TextField: " + GUI.GetNameOfFocusedControl());
``
Try logging the Event.current.Type in both Before and After
I did try that, but couldn't make much sense of the result: what should I look for? thought perhaps I should be ignoring repaint or working only on layout, but those tests failed too.
The UI is rendered with multiple passes, so the focus may be inaccurate in some passes. Just look to see if there is a pass that it is always accurate in.
best I got is to check only when (Event.current.type != EventType.Repaint && Event.current.type != EventType.Used) any idea where they got this stuff documented? no luck in my searches so far
I'm looking for a way to avoid two-way binding (UI Toolkit <=> SerializedProperty). What I actually want is one-way binding (SerializedProperty => UI Toolkit).
I'm working on an editor for my custom settings on the Project Settings window. As in the screenshot bellow, the left hand side is a ListView whose items are populated using a property DatabaseSettings[] databases inside my ScriptableObject. Each item of that ListView is just a Label bound to the DatabaseSettings.name property.
As you can see here, whenever we perform searching on the Project Settings window, matching texts will be highlighted. The original plain texts will be replaced with rich texts each includes some <color> and <mark> tags.
However this causes a problem: the value of Label is changed by search function, thus its "value change event" is invoked, results in my name property is updated with the rich text value of that Label.
This is the function assigned to bindItem callback on the ListView.
static void BindItem(VisualElement root, int index, SerializedProperty dbListProperty)
{
var nameProperty = dbListProperty.GetArrayElementAtIndex(index)
.FindPropertyRelative(nameof(DatabaseSettings.name));
var label = root.Q<Label>(className: Constants.NAME);
label.BindProperty(nameProperty);
}
var listView = new ListView {
makeItem = MakeItem,
bindItem = (root, index) => BindItem(root, index, dbListProperty),
};
If I comment out the line label.BindProperty(nameProperty); then this problem won't happen anymore.
However I need to bind Label to the "name" property so that whenever I changed the selected database through the Dropdown on the right panel, the value of this Label can also update.
I want to stop the Label from applying its value back to the "name" property.
Does anyone know how to achieve that?
There is no nice way to do one-way bindings with serialized properties sadly. What I normally is instead of using the binding system, I use the scheduler to do the binding.
label.scheduler.Execute(() => label.value = nameProperty.stringValue).Every(100);
Your case is a bit trickier with the search changing the value of the label. I would either A) From the scheduler delegate, cache the previous nameProperty value, and only update the label when it changes. Or B) don't bind it at al and just set it once, would only pose a visual issue if a user kept the settings window open and on your settings page and renamed the asset.
This is the solution 🥳
https://discussions.unity.com/t/how-stop-label-value-changed-from-being-applied-back-to-bound-serializedproperty/1599851/6
static void BindItem(VisualElement root, int index, SerializedProperty dbListProperty)
{
var nameProperty = dbListProperty.GetArrayElementAtIndex(index)
.FindPropertyRelative(nameof(DatabaseSettings.name));
var label = root.Q<Label>(className: Constants.NAME);
var labelNotifier = (INotifyValueChanged<string>)label;
labelNotifier.SetValueWithoutNotify(nameProperty.stringValue);
label.Unbind();
label.TrackPropertyValue(nameProperty, prop => {
labelNotifier.SetValueWithoutNotify(prop.stringValue);
});
}
Ooh yeah, I always forget about TackPropertyValue, sorry about that. Good find!
Hello, I've been kicking this around for ages, I want a function key to collapse all the component editors in the Inspector tab. I can list them, I can list their properties, but can't see how to expand and collapse the individual component editors. Any suggestions? Thanks in advance!
[MenuItem("Tools/Toggle Component Expansion v2 _F4")]
public static void ToggleComponentExpansionV2()
{
// Ideally, we want this to Expand/Collapse all items in the Inspector, just like the menu items
// feels like there's something here... can't pin it down
// https://docs.unity3d.com/ScriptReference/SerializedProperty-isExpanded.html
var tracker = ActiveEditorTracker.sharedTracker;
foreach (var editor in tracker.activeEditors)
{
Debug.Log($"editor: {editor.name}, " +
$"{editor.GetType().Name}, " +
$"{editor.GetType().GetMethod("m_IsExpanded")}, " +
$"{editor.GetType().FullName}");
foreach (var field in editor.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance))
{
Debug.Log($"<B><COLOR=#AAAAFF>{editor.GetType().FullName}</COLOR> " +
$"<COLOR=#FF3333>{field.Name}</COLOR></B>: {field.GetValue(editor)}");
}
FieldInfo isExpandedField = editor.GetType().GetField("m_IsExpanded",
BindingFlags.NonPublic | BindingFlags.Instance);
if (isExpandedField != null)
{
bool isExpanded = (bool)isExpandedField.GetValue(editor);
Debug.Log($"{editor.target.name} is {(isExpanded ? "expanded" : "collapsed")}");
}
else
{
// yeah, no, still doesn't work
Debug.LogWarning($"Could not access 'm_IsExpanded' for {editor.target.name}");
}
}
}
IIRC I did something in the past by creating an SO of the GO, going into m_Components (or whatever it is called) and changing isExpanded for those
Also you want to ue serializedObjects and not reflection there
Thanks for the suggestions
Hey guys
So question about editor menu. Even made a beautiful paint description to show end goal. Orange box is the one I want. I don't know what object type to use in C# or how to control events on whatever object it is.
Reference photo
So you want a window to appear when you ware hovering over a specific menu item in a context menu? It isn't possible, at least not without a load of hackery and probably use of Harmony, and even then I'm not sure it is possible...
The reason is that the context menu is an system menu (or at least it is drawn with QT in C++ at a low level), and not really a Unity window/menu.
Yea just found that out
I'm trying to create a config for a package I'm working on. It seams there's multiple frameworks built into Unity for this, which is the best to use? I've found the Settings Manager package and SettingsProvider class, there may be more.
Honestly never seen the Settings Manager package, which is surprising since I do a lot of editor tooling. But looks like it is just a thin wrapper around existing systems and I don't see it adding much. SettingsProvider class is the way to go, you can use inherit from the ScriptableSingleton class to create persistent settings. (Both have decent docs so if you are unsure, you can read them)
Hey, I inherited the Image component and added a few extra fields.
I need a custom inspector in order to display those(simply making them public didn't work).
What I have draws my first 2 properties, throws a ton of errors when it gets to drawing the actual image properties and doesn't draw anything else.
What am I doing wrong?
Code
None of those are the names of the serialized properties of the image component. Those are the names of the C# properties. Also, generally it is a bad idea to inherit from Unity's 'core' components as a lot of them are directly tied to a C++ class.
hey, thanks for the tip, however, I managed to make it work by doing m_Color etc.
and also, how bad is it really to inherit to add a few properties on top w 2 functions, I highly doubt it's any worse than keeping it a separate component w image property that adds an additional image component to the object
Anyone know why: {
Selection.selectionChanged += ShowWindow;
}
wouldn't trigger every time I click a new object in hierarchy ? It's like every other one
Here is issue
Does the window close automatically if you click somewhere outside of the window? I'm just wondering whether that could have something to do with it. Try to add simple debug within ShowWindow to confirm whether the method is actually called every time but something closes every second window
It isn't a gradient, it is a per-component basis and is black and white 9for the most part), either it will break /won't let you or it will work. It isn't a 'bad practice' thing, it is a 'literally breaks the component's functionality' thing. So that is why it is generally better to just not do it, because some break, some won't let you, and some work okay. Just a suggestion/warning 🙂
What is the logic in ShowWindow and where are you calling Selection.selectionChanged += ShowWindow;?
It is being called. Issue is it's not poping/repopulating window
Did a check to make sure ShowWindow is triggering lol
That didn't answer either of my questions 😛
was quicktype on phone sorry lol. cuddling da baby
private static void ShowWindow()
{
Debug.Log("----------------------------------------------------------");
Debug.Log("ShowWindow");
canRun = true;
var focusedWindow = EditorWindow.focusedWindow;
Rect popupRect;
if (focusedWindow == null)
{
Debug.Log("focusedWindow is null");
// Fallback to a default position if no window is focused
var mainWindowPos = EditorGUIUtility.GetMainWindowPosition();
popupRect = new Rect(mainWindowPos.x + 400, mainWindowPos.y + 200, 0, 0);
_currentPopup = new MeshInfoPopupContent();
PopupWindow.Show(popupRect,_currentPopup);
return;
}
Vector2 mousePos = focusedWindow.position.position;
mousePos += new Vector2(400, 200); // Offset from window corner
_currentPopup = new MeshInfoPopupContent();
MeshInfoPopupContent.windowContent = _currentPopup;
popupRect = new Rect(mousePos.x, mousePos.y, 0, 0);
Debug.Log("Showing PopupWindow");
PopupWindow.Show(popupRect, _currentPopup);
}
@gloomy chasm
Literally just wanting a floating data box that shows up when you select items in hierarchy lol. Shouldn't be this annoying. Don't want to make a "window" or tool window
PopupWindows close when they lose focus (iirc). So what might be happening is when you select an object it causes the popup to lose focus, but before it closes it tries to open it, but it is already open so does nothing, then it closes because it loses focus because of the selection.
Or something like that
Any ideas on a way to circumvent it?
It doesn't have a close method either. Looked into that
Will have to make a custom Editor window instead. And use window.ShowPopup() and set the windows position. You will have to close it as well.
im making a custom graph using graphview for my editor, and i struggle with 1 issue due to serialized property bindings.
OnGraphUpdated has 3 possible iterations that can be invoked many times in the same cycle.
If i change nodes (dragging an edge) from a node, it will call first delete on it then add.
The logic is sound but at the same time serialized properties seem to struggle when i move and re-add an item in the same frame with how graph view works.
how should i tackle this?
I'll look into that. Thanks @gloomy chasm
Hi! I am trying to understand how to make a vertical only scrollbar for my editor window. It seems that whenever the vertical scrollbar shows, the horizontal one also shows, and clutter things for me even if everything fits in the width... I set a minimum width of 400 to this window to make sure everything always fits horizontally.
I could work around it by removing the right side margin. It is still drawn because of the window being wider than the layout...
I think if anything you draw has a some fixed/min width then it will then eventually make the horizontal scroll bar appear.
I think i countered it before by making min width or width 0 for basically everything.
Thanks, I managed for now to adjust my approach for a few layouts by not adding the last margin/spacer in the direction I want avoid scrolling in. I suppose that makes it think that I still have 20px to go, and that makes it all fit without a scrollbar.
Why you no want to load every click lol
@gloomy chasm switched to editor. It works.
How can I force a redraw for a ToolbarOverlay? I have an EditorToolbarButton that is tied to a monobehavior value, but the button does not update when the value changes.
Kind of a broad question, but I have no idea how Undo.RecordObject actually works. I tend to always get an out of range exception with my lists whenever I use it. What is and isn't recorded with this?
From what I know, you should call it before you do manual changes to an UnityEngine.Object or any of its members
Manual changes = not using property drawers or default inspector
For ScriptableObjects you also need to call SetDirty after you have done the changes
why the foldout is goinng out of the box. the property field is a serializable custom class drawn in custom editor using property field inside a vertical layout group with box style but the foldout icon goes outside of the bound
or is there any way to show fiels of a serializeable class with out explicitly finding its property per class rather make something simmilar to EditorGUI property field but without the foldout?
The "best" way to make changes to scene or prefab data is to create a SerializedObject, change properties on that object, and then apply modified properties
that way, you're directly editing serialized data
If you instead edit the C# data (e.g. someThing.transform.position = Vector3.zero;), Unity doesn't know that anything has changed
You need to explicitly tell it to record a copy of the object's data, so that it can later check what has changed
@safe sorrel @real spindle Thank you for the answers, much appreciated!
I realized after fiddling with it some more that it seems to mainly just record serialized data. The fields that were giving me trouble were non-serialized privates. My fix was to attach [SerializedField, HideInInspector] attributes to it, which does work from what I can tell, but I don't think this is the "proper" way to handle this, right?
Dont expect Undo to work with non serialized fields. however marking a field to be serialized just for undo to work seems wasteful
Definitely. But I'm unsure how else I can get undo to work if it's not serialized.
maybe your own undo state? https://docs.unity3d.com/6000.0/Documentation/ScriptReference/Undo-undoRedoEvent.html
shame you cant register some non unity based undo event
I should also note
Since I'm only using these fields for Editor stuff, they are wrapped in #if UNITY_EDITOR directive. So doesn't really affect final builds.
Wouldn't I need to keep a copy of my fields in this case?
Yea, you can record the data that changed or enough data for you to revert the change later
guys why my grass fade out too quickly i want to fade out with far more distace in viewport
Does anybody know how can I expose an AudioMixerGroup's volume with an editorscript?
some one coul help me ??
I'm very confused by undo groups right now. For example:
https://docs.unity3d.com/6000.0/Documentation/ScriptReference/Undo.RevertAllInCurrentGroup.html
Performs the last undo operation but does not record a redo operation.
This is useful when you want to simply revert the last performed action. In Unity the escape is commonly used to execute this function.
I can't tell if this is supposed to throw out everything we've done since the undo group was last incremented, or if it's supposed to redo everything that was thrown out by the most recent undo operation
I'm getting random errors about overflowing the undo stack while placing a bunch of objects via script. Part of the cause is that I'm instantiating a prefab, doing some tests, then destroying it because it failed those tests
It'd be nice if I could just tell Unity to completely forget it ever instantiated the object
rather than having to record a destruction
I'm also unclear if calling CollapseUndoOperations actually does anything to simplify the undo stack, or if it just combines multiple actions into one visible undo step
wait, duh: I just wait to register the object's creation until after I decide I want to keep it
yep, that fixed it!
I was still using the Undo destroy method, which was spamming the undo stack
after fixing that, it's all happy
a fair bit faster, too!
Is it really intended behaviour that PropertyFields don't actually render anything in the UI Builder?
Yeah, it has no way to know what it should show until a property is bound to it.
https://youtu.be/DU7cgVsU2rM?si=3O4_-yU60B8ZMHbo
This guy used audiomixer groups and parameters
Show your Support & Get Exclusive Benefits on Patreon (Including Access to this project's Source Files + Code) - https://www.patreon.com/sasquatchbgames
Join our Discord Community! - https://discord.com/invite/aHjTSBz3jH
In this tutorial I'll show you how to add sound effects properly into your game in Unity.
We'll start by making an awesome ...
Hi all, I am trying to make a custom scriptable object UI for the editor. However I can't seem to get the ListView to work, I am able to display the inspector and the view but trying to add anything to it just throws this error:
NullReferenceException: Object reference not set to an instance of an object
UnityEngine.UIElements.BaseListView.AddItems (System.Int32 itemCount) (at <9e479aa738ca4829b0b686484913de34>:0)
UnityEngine.UIElements.BaseListView.OnAddClicked () (at <9e479aa738ca4829b0b686484913de34>:0)
The code in question is below, this sits inside the scriptable object. I have checked just before the both the source list and the element for null and both are good, so I am unsure on where this null error is coming from. Does anything stand out to anyone?
From your description and the error message, it looks like the ListView is not properly initialized or bound before trying to add items. A NullReferenceException in BaseListView.Additems typically means that either:
- The ListView's itemsSource is not set correctly.
- The makeltem or binditem functions are missing or not properly implemented.
- The ListView is being accessed before it is fully initialized.
This could be a cause, but im not really focused on editor stuff, so maybe have a copy of the original code before altering it, yw :)
Thank you for the response, but I don't understand how this video could be a solution. I'm trying to make an editor script to automatically expose an AudioMixerGroup's volume parameter, but in this video the person doing it does it manually (See 9:26 in video). https://youtu.be/DU7cgVsU2rM?si=7BoijDa6JnfdCTL1&t=566
Show your Support & Get Exclusive Benefits on Patreon (Including Access to this project's Source Files + Code) - https://www.patreon.com/sasquatchbgames
Join our Discord Community! - https://discord.com/invite/aHjTSBz3jH
In this tutorial I'll show you how to add sound effects properly into your game in Unity.
We'll start by making an awesome ...
You might need to look into the code on github to see if it is even possible.
Thank you! With this I managed to expose my parameters (With reflection). However, I want to set a specific name to my exposed parameters. Do you know by any chance which method can solve that?
Are their any specific examples then of how to do UXML with scriptable objects with list views then?
https://docs.unity3d.com/6000.0/Documentation/Manual/UIE-HowTo-CreateCustomInspector.html
I was following this part of the docs to set up the scriptable objects UI given the greation and querying of the UXML is done within the CreateInspectorGUI.
https://docs.unity3d.com/6000.0/Documentation/Manual/UIE-uxml-element-ListView.html
And in this one it shows the binding, of the listView, setting of the source and such can all be done immediately after it is queried.
I have even tried setting using a new list from within the custom editor itself rather then the scriptable objects list to see if the data source list was the trouble itself and this still causes the error.
If no examples exist, is thier a way to enable better debugging options with UIToolkit, so I can actually see what lines are throwing null, rather then just a blank null error?
No, I do not. Sorry.
One thing to note is I'm not sure if the binding system works in editor.
Oh... That may be it then xD
Is their a different approach for using UXML with scriptable objects / editors then? Should I just use a scroll view and control everything manually?
Normally you would use SerializedObject and SerializedProperty and the bindingPath property. You can't bind to arbitrary values with it sadly.
Ah okay, I havn't used the serialised object stuff directly for a while, so I'll need to look back into that. Thank you though I'll see about giving that a try!
Do you know of any docs that specifically go over the use of serialised properties and the binding path?
Hiya, so I have _surfaceCellLayoutList.bindingPath = "surfaceCellGenerationData"; working now, and it is showing the list. I can add and remove from it which is great!
However I now want to access the properties inside the binds, how does this binding work? I assume I will need to rebind and unbind in the ListViews Bind and Unbind calls but my question is where is the binding path considered to be for this?
Will I need to use something like intField.bindingPath = "surfaceCellGenerationData[index].depth"; or would just intField.bindingPath = "depth surfice?
I've managed to get this to work! https://discussions.unity.com/t/need-help-getting-nested-listview-bindings-working-correctly/904577 It seems I had to also call .Bind() when setting up the items, just for peice of mind is this going to cause any issues. Should I be calling .Bind on every one of my fields (like the _surfaceHeightRangeSlider for example). Right now it works without, but I also know serialization can be a bit finicky.
_surfaceHeightRangeSlider.bindingPath = "surfaceHeightRange";
_surfaceSmoothnessRadiiRangeSlider.bindingPath = "surfaceSmoothnessRadiiRange";
_surfaceCellLayoutList.bindingPath = "surfaceCellGenerationData";
_surfaceCellLayoutList.makeItem = MakeItem;
_surfaceCellLayoutList.bindItem = BindItem;
_surfaceCellLayoutList.Bind(serializedObject);
return;
VisualElement MakeItem()
{
AsyncOperationHandle<VisualTreeAsset> operationHandle = Addressables.LoadAssetAsync<VisualTreeAsset>("Visual Element: Surface Biome Cell Layout Element");
VisualTreeAsset visualTreeAsset = operationHandle.WaitForCompletion();
VisualElement visualElement = visualTreeAsset.CloneTree();
operationHandle.Release();
return visualElement;
}
void BindItem(VisualElement element, int index)
{
IntegerField depthField = element.Q<IntegerField>("DepthIntField");
depthField.bindingPath = $"surfaceCellGenerationData.Array.data[{index}].depth";
depthField.Bind(serializedObject);
EnumField cellTypeField = element.Q<EnumField>("CellTypeField");
cellTypeField.bindingPath = $"surfaceCellGenerationData.Array.data[{index}].cell";
cellTypeField.Bind(serializedObject);
}
Bind is like setting the dataContext to be the scriptable object.
So normally you want to do it from the root element
Having it applied only to the root object seems to break the list items again, or do you mean to just call it on element? (like root of the specific element)
Sorry I thought you meant root of the whole UI xD
No no, I did mean root of the whole UI haha
Oh, in that case it still doesn't work for some reason
Just tried aswell on just the element and that also doesn't work
Hmm, yeah it seems the .Bind only fixes the issues once its applied to the IntField and EnumField, which I assume isn't meant to be the case xD
Unless, binding the root element changes the bindingPath of the list elements
Would that be the case?
Hi everyone, I'm trying to set up an editor that would let me design templates for 3D patterns of cells.
The idea would be that I can define the width / height of a 3D grid and then select which cells I am intrested in and give them properties.
Excuse the bad example, but this is the closest thing I could find for what I mean:
The idea would be that I could create a property drawer that would allow me to edit this in a simular way to moving around the scene.
How would I best go about doing this? A while ago I did some stuff with Scene like behaviour in the hierachy so I know it is possible, though I don't know if in the years since I did do this UIToolkit or the EditorGUILayout stuff has any other specifics on how to go about managing 3D logic?
To render 3D stuff in the UI the easiest way is to use the PreviewRenderUtility and then just draw the resulting texture (via UITK or IMGUI)
Is something like this what you want?
I.e. I have 3 points selected(in orange) and then I assign properties to them
This is how I create structures in my procedural world
I want to have my own ways of interacting with the inspector, for example i already have a class which allows me to drag and drop monobehaviours, and it will set itself to null or error if the monobehaviour does not inherit a given interface. I would like to make it so that It simply wont accept objects which dont implement the given interface, is there a way to do this?
Yeah, thats pretty much exactly what I need:
Right now I am using a system like this, x and z for each block of 9, and the 3 blocks are the y levels.
That is then used to do the pattern matching for the meshes like this
I am also going to use this system to spawn prefabs, did you also use the PreviewRenderUtility MechWarrior99 mentioned above?
No I didn't, using PreviewRenderUtility like how you're doing above is probably a nice way to isolate the editor, because I currently have it kind in its own seperate scene currently.
I built a editor extension that uses a custom grid shader, custom mesh generation compute shader, custom compute SDF extractor, and a lot of quality-of-life features, to recreate the mesh and visualize it all in the editor.
It's more tailored for my needs but it requires more groundwork(as you can probably tell). My implementation is very much tied down to my game system, but I can give a top-level rundown of how it works.
Overview
Underneath, I have a buffer that represents the information for each point along the grid. When you select a point and change its information, this buffer gets copied to the GPU, where the mesh is regenerated in a compute shader. The grid shader also looks at this buffer to determine what points are selected(to color orange). To determine, from what vertex your mouse is clicking, I get the screenspace position of every vertex.
SDF Extractor
You can import an fbx and specify the address of it within your root directory, then I find it, using AssetDatabase.LoadAssetAtPath to load it and extract the mesh. Then I have a compute shader that extracts a SDF from it and then returns the SDF as the map information to transfer my models to ingame representation. (You don't have to be too optimal about this, just check the distance from every entry to every triangle in the mesh is fine, compute shaders are fast).
Grid Shader
I basically have a mesh(you can make one dynamically in a compute shader) made up of a bunch of cubes, and each cube face has UV from 0,0->1,1. Then I have a transparent shader where if the uv of a pixel is close to a corner of the UV draw white(point), and if it's close to the edges, draw gray(an edge), otherwise you can clip it(alpha = 0). You should also have backface culling turned off and zwrite off(ztest on), for the grid as well.
Since you're probably doing voxel-based generation, instantiating a prefab for every entry is probably a lot easier and the way to go, but that wasn't an option for me(using marching cubes).
Is there a way to force EditorPrefs to save to disk without exiting the Unity Editor?
Is there any way to make a custom editor for files with a specific file extension (which is not handled by Unity) without doing [CustomEditor(typeof(DefaultAsset))] and checking the extension?
When I'm inside of prefab view (double click prefab), how can I get AssetPath of current prefab via code?
i think PrefabStageUtility.GetCurrentPrefabStage().assetPath is what you need?
Yeah, first you will want to make a ScriptedImporter for it and have it import as a custom ScriptableObject (You can have it import as other things, so long as the object set as the MainAsset is the custom ScriptableObject).
Then you just make a custom editor for it like normal for the most part
Awesome, thanks
(You can have it import as other things, so long as the object set as the MainAsset is the custom ScriptableObject)
Or GameObject! Or any other existing native asset type.
Oh, I can see what you mean, if you want to have a custom editor for the file.
That editor will be read only, though. Only serialized fields in the ScriptedImporter can be changed to modify the imported asset. Or the contents of the file itself.
I'm using the Graphics.DrawMeshNow and instancings batches of matrix4x4 for the different meshes, instantianting gameobjects is a bit to slow overall, but the end result is the same. Thank you for the help btw! I'm gonna try the previewrenderutility for a bit, but if it doesn't work I may just do it using a seperate scene too ^-^
Shift-space will toggle a window in and out of fullscreen, but not during Play. This has always bugged me, is there a way to do that during play?
I really want to be able to move in and out of fullscreen for the game tab without stopping play
well unity were smart to not let keyboard input for your game also do editor shortcuts
i think you have to click out of the window or change fullscreen manually on the game window
Untested, but if you toggle the keyboard-looking button at the top of the view I would expect all editor shortcuts to function
somewhat new to editor extensions. but, how difficult would it be to make something like shadergraph but for other stuff, like dialogue trees.
nvm, found an asset on the asset store that does pretty much exactly this
can some one explain how to use handle utility controls in editor... im adding controls and choosing the nearest from mouse position, it correctly selects the one i want, then i have a PositionHandle at the handle position i chose, but as soon as i click to drag the position handle the control i had selected changes because i have clicked again so it breaks
I have no experience when it comes to extending the editor, but I've come across this asset that has some very useful looking elements, I'm wondering how do I go about making something like the image where I can better display certain properties in the inspector
the alternative has been using OnGUI and a Canvas, which honestly feels incredibly sluggish to do development with
Do you mean using IMGUI or UIToolkit? And in editor or at runtime?
Changing the fullscreen toggle manually has no affect while in play mode
doesn't work sadly
Er no you can surely change the game window full screen state mid play
"full screen on play" won't do anything but the lil dots menu option works
oh yeah that works, thanks. I guess that would do for now
I've used both of them, ImGUI by far the better choice when I need to get something quick and dirty, but it ends up being a big wall of text inside OnGUI
I figure if I could better display properties in the inspector so its laid out nicely, thats all I really need
Tell me, previously in Editor graph Node it was possible to specify the style of the visual element's maintainer mainContainer.AddToClassList, how did this change in version 2022?
How to Control and Change Node Styles in 2022?
I can't find any video or information on how this works in Unity 2022, it looks like Node class was reworked and now it's done differently, Give a link to any source with this information pls
ok this is bad using fo Node using UnityEditor.Graphs;
this is try using for Node using UnityEditor.Experimental.GraphView;
Hi everyone, I'm trying to get a renderpreview to move the camera based on mouse movement in the same way as the main editor, though I'm a bit stuck on how exactly I'm meant to get the inputs hooked up.
I can use PointerMoveEvent and PointerDownEvents to get mouse movement and buttons, but these stop working once the mouse moves outside the scope of the visual element they are registered too.
What is the intended way to get Mouse / key inputs for editor extensions?
And if it is the former, is their a way to lock mouse positioning inside the visual element (without it then messing with the delta of the PointerMoveEvent) in the same way as how you can lock the cursor in runtime?
I found this: CapturePointer
It holds onto the pointer which is good, though it still allows for the pointer to leave the bounds and the mouse is still visible so if anyone has any ideas on that I would be greatful ^-^
I think you can use the static Cursor class in editor but I don't remember for sure. You can also look in to the cursor styled property of VisualElements style. I can't remember what options are availabe for it.
Neat! Did you replace the GUIStyle for the editor along with doing some injection to change the base colors or something else?
oh my god it's round
I gave the Cursor class a go but it still didn't seem to hide or lock the cursor. It's not the end of the world at the moment though
popupField = new PopupField<string>(label,choices,-1,(e) => property.stringValue != string.Empty ? property.stringValue : "none",(e) => e);
popupField.RegisterValueChangedCallback((evt) => {
if(evt.newValue.Contains('/')) {
int lastIndex = evt.newValue.LastIndexOf('/');
property.stringValue = evt.newValue.Substring(lastIndex+1);
} else {
property.stringValue = evt.newValue;
}
valueChangedCallback?.Invoke();
property.serializedObject.ApplyModifiedProperties();
//popupField.index = -1;
});
hey yall, so it seems like my popupfield is not properly updating its display.
it seems to evaluate the formatSelectedItem before the valueChangedEventand there for wont display the actual stored value. I could remedy this by using the selected value it gets passed in and doing the same operation but id rather just have it update to show the real displayed value, since that has other issues (namely when you reload)
is there any way to just set the text of the popupfield directly? or make it refresh?
Any way to start a program through editor code and read its standard output without losing it on a domain reload? Like if the program outputs stuff while the domain reload is occurring, I want to be able to display what the output was after the reload occurred.
Use SetValueWithoutNotify
yes, i injected custom stylings into the IMGUI elements using uss
...What? You can't change the stlye of IMGUI via uss...?
yeah, i've also created a tool to help auto-generate the uss code using a scriptable object.
That is not uss... no? That is generating a GUIStyle is it not?
it is uss
/----------
[ Theme: Light-Penelope ]
----------/
/<Animation.Background>/
.AnimItemBackground {
background-color: rgb(255, 180, 193);
border-color: rgb(220, 114, 151);
}
.TimeRulerBackground {
background-color: rgb(255, 235, 211);
border-bottom-color: rgb(220, 114, 151);
border-width: 0 0 2px 0;
}
.AnimationEventBackground {
background-color: rgba(239, 169, 209, 0.5);
border-color: rgb(220, 114, 151);
border-width: 0 0 1px 0;
}
/<Animation.Row>/
.AnimationRowEven {
background-color: rgba(255, 180, 193, 0.15);
}
.AnimationRowOdd {
background-color: rgba(255, 180, 193, 0.3);
}
/<Animation.Toolbar>/
.AnimPlayToolbar,
.AnimClipToolbar {
background-color: rgb(255, 242, 242);
border-color: rgb(220, 114, 151);
}
.AnimClipToolbar {
border-width: 0 0 0 0;
}
.AnimLeftPaneSeparator {
background-color: rgb(220, 114, 151);
}
/<Animation.Toolbar.Button>/
.AnimClipToolbarPopup,
.AnimClipToolbarButton {
background-color: rgb(255, 180, 193);
border-color: rgb(255, 242, 242);
border-radius: 10% 10% 10% 10%;
border-width: 1px 1px 1px 1px;
}
.AnimClipToolbarPopup:hover,
.AnimClipToolbarButton:hover {
background-color: rgb(255, 199, 198);
}
.AnimClipToolbarPopup:active,
.AnimClipToolbarButton:active {
background-color: rgb(255, 208, 156);
}
/<Animation.Toolbar.Button.TS>/
.TimeScrubberButton {
background-color: rgb(255, 178, 177);
border-radius: 0 10px 10px 0;
border-width: 0 0 0 0;
}
.TimeScrubberButton:hover {
background-color: rgb(255, 180, 193);
}
.TimeScrubberButton:active,
.TimeScrubberButton:checked {
background-color: rgb(255, 199, 198);
border-width: 0 0 0 0;
}
a small snippet of what "Apply Theme" generates.
How do you apply them? You cannot edit IMGUI with style sheets.
https://github.com/Marmik-Emp37/Emp37.Editor-Theme
if you wanna have a closer look
no, but you can override them before they're rendered ig. It's very limited as to what can be changed on these IMGUI styles but i've explored & tried to create a tool around what seems possible.
although i'm trying to learn if there is a way to freeze a panel or the editor so i can inspect the IMGUI styles on this selection window.
if i open this & i try to click anywhere outside of this window, it collapses. IMGUI being a different panel i don't understand on how i would inspect the names of these elements in gray so i can override them too in order to make my theme more consistent.
if anyone can help, i'd be grateful
You would look at the source code
& how would i do that for this specific case?
the editor for materials has a function called TexturePropertyBody, it uses DoObjectField, on MouseDown that calls ObjectSelector.get.Show, which has an OnGUI method, which calls SearchArea, which has an area commented as // TAB BAR
you can then see the styles they use for that area.
@slim bramble
Just follow the code down to where the thing you want is, OnGUI makes this easy as it's all linear
thank you, i will look into this.
My eyes would have a tough time with that light mode, but that is cool nonetheless!
thanks, i also have a dark theme which currently looks like:
hi all, I am working on an editor window for cusomising patterns using PreviewRenderUtility, the idea is that different parts of my project will need to use this pattern so I wanted to have it separate from the each scriptable objects editor code.
This is what I currently have:
I'm going to set the second window up to render the patterns and allow for editing, however since this is now a seperate editor window how would I be serialising the changes?
SpawnRequirementEditorWindow window = EditorWindow.GetWindow<SpawnRequirementEditorWindow>();
window.titleContent = new GUIContent("Spawn Requirements Editor");
window.Data = _targetScript.spawningRequirementPattern;
This is currently how I am retreiving the "spawnReqiurementsPattern" struct that I will be serialising from within the different scriptable objects, I know I can get the serialisedProperty from the SO's SerailisedObject however will I then not also need the SerialisedObject to get the property to save?
(The TL;DR is that I want this EditorWindow to behave in the same way as the Color editor does in Vanilla Unity)
Any help would be appreciated
Just create a SerializedObject for the ScriptableObject and save changes by doing serializedObject.ApplyModifiedProperties();
Thank you!
Ill do that, I'll pass in the SerialisedObject and the property itself and then once its changed ill call the Apply function
thanks!
wait
I think this does the opposite of what I want it to do, how would I use this to get what I want?
Hiya, How would I go about getting handles to work with a UIToolkit UI using PreviewRenderUtility?
private void OnGUI()
{
if (_previewVisualElement == null) return;
if (_renderPreview == null) return;
Rect rect = new Rect(0, 0, _previewVisualElement.resolvedStyle.width, _previewVisualElement.resolvedStyle.height);
_renderPreview.BeginPreview(rect, previewBackground: GUIStyle.none);
_renderPreview.Render();
ProcessHandles();
Texture texture = _renderPreview.EndPreview();
_previewVisualElement.style.backgroundImage = ConvertTextureToTexture2D(texture);
}
private void ProcessHandles()
{
using (new Handles.DrawingScope())
{
Handles.SetCamera(_previewCamera);
Handles.color = Color.black;
Handles.DrawWireCube(Vector3.zero, Vector3.one * 1.5f);
}
}
This is currently my rendering code, right now I can see the game object (pink cube) and move the camera perfectly fine but I cannot see anything from the handles. I've been looking how others have been doing it using https://discussions.unity.com/t/previewrenderutility-and-handles/783621/5 from this link and others and it does not seem to work still.
Sorry ignore my previous post, I think it was the recontextulising the scope that caused it not to draw. I've removed this now and it works.
This method will update the GUI without sending changed event, so in your changed callback you should be able to call it
oh ok, ty
Hi again, sorry. I've got handles appearing and the Button handle appearing too, but for some reason I cannot click it. hovering is registered (the white box is showing this in the image). Could something be eating the mouse input and if so how would I detect this and stop it. This is the code I am using for the clicking:
if (Handles.Button(buttonPosition, buttonRotation, 0.125f, 0.125f, Handles.RectangleHandleCap))
{
Debug.Log($"Cells in pattern: {coordinateListProperty.arraySize}");
};
I've tried checking the adding the following line to check what events are currently being show (the if is to get rid of either the repains and layouts as they spammed the log).
if (Event.current.type != EventType.Repaint && Event.current.type != EventType.Layout) Debug.Log("Event Type: " + Event.current.type);
However, now no longs are appearing, my guess is that the OnGUI isn't firing on any events, clicks or otherwise:
Which is strange as I have registered callbacks on the creation of the UI for the panel itself with this code:
_previewVisualElement.RegisterCallback<PointerDownEvent>(OnMouseDownEvent);
_previewVisualElement.RegisterCallback<PointerUpEvent>(OnMouseUpEvent);
_previewVisualElement.RegisterCallback<PointerMoveEvent>(OnMouseMoveEvent);
Which does work, does Registering callbacks maybe block future OnGUI calls with mouse events?
I just checked my code and I don't do anything special to have the IMGUIContainer receive input events. I would try to re-create the simplist scenario and then work your way back to your current setup until it breaks.
I'm not sure this would matter, but this is for a UIToolkit based system not IMGUI though I wouldn't have thought that would change much
So I checked the event debugger and it seems that the UI is reading the events. Its just the OnGUI event doesn't get called.
private void OnGUI()
{
Debug.Log("Event Type: " + Event.current.type);
}
Do you have any example code that showcases handles usage within PreviewRenderUtility UIToolkit visual element?
(The keydown event in the logs is me Alt-Tabbing out the editor to not fill it with mouse move events - not the mouse down)
Are their any other methods for allowing on Click functionality with PreviewRenderUtility then Handles?
I have tried manually calling the OnGUI event with the registered events from the visual elements, but that still does not trigger the handles to recognise the click.
I've been reading different posts across google on topics remotly related to this and each seem to be using slightly different setups (e.g not using UIToolkit, or Handles in the Scene view etc.) So potentially they just don't work without IMGUI.
Just updating the chat incase anyone else has the same issue. The problem seems to be that UIToolkit is designed not to call the OnGUI update method unnecisarilly, which apparently includes any mouse inputs, this basically locks Handles from ever working correctly with user Input with UIToolkit. That said, using the IMGUI container as a event generator and calling the OnGUI event of the window ith its callback seems to fix all these issues:
I'm running some tests now, but the code below seems to be working now.
IMGUIContainer container = new IMGUIContainer();
container.style.flexGrow = 1;
container.style.width = new StyleLength(new Length(100, LengthUnit.Percent));
container.style.height = new StyleLength(new Length(100, LengthUnit.Percent));
container.style.backgroundColor = Color.red; // <-- Just so I could see it before I hid it.
container.style.opacity = 0;
container.onGUIHandler += OnGUI;
preview.Add(container);
When updating to Unity 6, it started to fail for some of those work around. I suggest you test on it if you are not there yet.
I'm using Unity 6000.0.21f1 at the moment, but I will keep that in mind if I update ot a later version then this.
So far this seems to be working, though I am getting some errors in the log from calling begin on the render preview most likely because the event logic for the mouse click is happening between the repainting of the window. Should be a simple fix but again worth noting that the above code isn't without its faults.
Hi everyone, I was wondering what the correct way of cleaning up a preview render utility was. (or secondly the correct way of closing a UI).
The UI I am working on I want to have simular functionality to something like the Color UI, where as it closes on focus being lost. Previously manually closing the window worked fine and gave no errors, however once I added the forced close with OnFocusLost it seems to now cause an error about deleting game objects twice. Most likely caused by the OnDisable and Close cleaning up the PreviewRenderUtility and its gameobjects together.
private void OnLostFocus()
{
Close();
}
``````c#
private void OnDisable()
{
if (_renderPreview != null) _renderPreview.Cleanup();
}
I have tried checking if either function is entered and exiting the other early to stop this, however this causes two issues, the first is that if the window looses focus I get the error: A PreviewRenderUtility was not clean up properly before assembly reloading which lead to leaking this scene in the Editor..
While if I close it manually using the close button (which invokes OnDisabled first) I get: Destroying object multiple times. Don't use DestroyImmediate on the same object in OnDisable or OnDestroy. still.
My guess is that I am holding on to a list of the active objects in the scene inside the editorwindow class so I can move them and such, and since the window is closing down their is some sort of automatic process to clean these up, which happens before the OnDisable event occurs.
Seems like odd behaviour but I assume I'm just doing somethign wrong, if anyone could help with this I would apperciate it.
Your null check does nothing to prevent duplicate calls since you never set it to null if that was what you were trying to handle
The null check is mainly their to make sure the UI didn't fail to initialise.
Its more of a precaution (not that its needed)
Would I need to set it to null to stop Close from attempting to also call Cleanup on it?
yup
I've updated the code to set the preview to null after the cleanup, aswell as added in the returns for it the cleanup has already occured.
I also figured maybe the extra list was holding onto the gameobjects so I've cleared that aswell, and yet I am still getting the error:
Destroying object multiple times. Don't use DestroyImmediate on the same object in OnDisable or OnDestroy.
UnityEditor.EditorWindow:Close ()
private void OnLostFocus() => Close();
private void OnDisable() => CleanUp();
private void CleanUp()
{
if (_renderPreview == null) return;
if (_previewRenderUtilityCleanedUp) return;
_renderPreview.Cleanup();
_renderPreview = null;
_emptyCellNeighbourPositions.Clear();
_cellsInPattern.Clear();
_gameObjects.Clear();
_previewRenderUtilityCleanedUp = true;
}
Am I just not meant to be using Close to force close the UI?
_previewRenderUtilityCleanedUp is set to true on creating the renderPreview;
Oh
Actually
This seems to only happen now if I close the UI manually
Close is actually happening before the CleanUp, and the error is nothing to do with OnDisable
private void OnLostFocus()
{
Debug.Log("Close");
Close();
}
private void OnDisable()
{
Debug.Log("OnDisable");
CleanUp();
}
private void CleanUp()
{
if (_renderPreview == null) return;
if (_previewRenderUtilityCleanedUp) return;
Debug.Log("Clean Up");
_renderPreview.Cleanup();
_renderPreview = null;
_emptyCellNeighbourPositions.Clear();
_cellsInPattern.Clear();
_gameObjects.Clear();
_previewRenderUtilityCleanedUp = true;
}```
Does manually closing a UI call anything else first? As my best guess is that thats basically calling Close twice and causing it to attempt to delete everything twice before the cleanup even happens.
Is their a way to check if the window is already closing?
I move the Close() call from OnLostFocus to OnGUI, and got it to be called by just using a bool, (I set the bool to true on OnFocusLost), this no longer throws the error. However, this seems wrong to me but it works for now so it'll do :/
My debug gizmos stopped drawing in the game view
Does anyone know why and how to enable them back?
When I switch to the scene view, they get drawn
They were getting drawn in the game view a few days ago
Now even on the commits from a week and 2 weeks ago on which I'm sure the gizmos were drawn in the game view, they don't get drawn.
void OnDrawGizmos() {
RenderSteeringForce();
}
void RenderSteeringForce() {
Gizmos.color = Color.green;
Gizmos.DrawLine(transform.position, transform.position + Steering.Force.ToVector3());
}
Oh I needed to press on the Gizmos button
Is it possible to change the skybox of a PreviewRenderUtility? everythign I do seems to just change the skybox of the main scene and leaves the preview with a default.
Iirc you have to change it between begin and end render
Ahhh
Thats where I went wrong
Thanks! Its all working now, I was doing it before Begin thinking it would need to be established before I start doing any sort of rendering
Hey guys, is there a way to disable rendering gizmos from overlay cameras in the scene?
Currently I have a couple setup and they totally just break my gizmo functionality sinec it draws them from both perspectives.
If I wanted to create a editor script that generated a bunch of collisions inside of a subscene what would be the best way to do that?
You mean colliders?
Even still, you need to be more specific
I can create the gameobjects and attach them to another game object but I really just want to dump them into a subscene and that's where I'm running into problem.
so i have a custom editor that is in an editor folder it inherits from Editor i have the attribute custom editor of the type (which is a scriptable object), yet not a single function in the script runs when i select my scriptable object asset, ive made plenty custom editors before but suddenly now nothing, i dont know how to debug this problem
Restart Unity if you haven't yet
got it working now, turns out i had a second script using the CustomEditor attribute somehow. was a difficult one to find 😄
is it possible to know which element in an array is selected with the gui api
not the visual element stuff
Hi guys, I'm developping games for mobile and when working on UI I like to open 4 game views, each with a different device (Device Simulator Package) so I can, well, view it on different devices.
I'm trying(and failing miserably) to build a tool where at the click of a button it immediately opens 4 Game Views side by side on a dettached window, each occupying 25% of said window.
In an ideal world, it already sets the correct devices, and I might eventually try to get there using reflections, but for now I don't mind chosing the devices every time, but I would like the button to open the 4 side by side views.
Anyone got any ideas on how I can achieve this?
When using editor extnesion via ui toolkit do I have to unregister the callbacks of a propertyfield value change somewhere? I'm currently registering callbacks in the CreateInspectorGUI like this:
public override VisualElement CreateInspectorGUI()
{
VisualElement root = new();
visualTree.CloneTree(root);
_timePanel = root.Q<VisualElement>("TimeToComplete");
_directionType = root.Q<PropertyField>("DirectionType");
_directionType.RegisterCallback<ChangeEvent<DirectionType>>(OnDirectionTypeChanged);
}
Hi everyone, I'm working on an analysis editor in which is gets and processes data from runtime. This editor and its subsequent scripts have been put in the Editor folder, however because of that the classes that the classes in these editor files are no longer visible in the runtime code.
I am blocking runtime access using #if UNITY_EDITOR so that it doesn't cause issues when I do builds, but not because of the location of the files (now in the Editor folders).
What is the right way to handle this?
Nope
Kinda hard to answer this as the approach changes depending on the exact API and usage, etc.
which is more performant foreach(var child in inputContainer.Children()) var port = child as Port; or inputContainer.Query<Port>().ForEach();
implementation details matter more than API, you need to specify what all the things are you are mentioning in that code and how/when/how-often they are called.
could it be possible to have a custom editor element (I'm not sure what the right word is for adding a button to the editor UI) that is able to change settings in Unity's Project Settings/Preferences window? I'd imagine the answer would be no
its possible
nice!
wanted to see which is faster, inputContainer and Port are just visual elements from UnityEditor.Experimental.GraphView, but i took a different approach
specifically what I have in mind, is a feature in Houdini allows you to alter how the program updates. Each time you add certain nodes, those need to be initialised, so it can be useful to pause updating if you want to quickly add a lot of things that you only need to be initialised after youre done.
similarly in Unity, if I want to make 10 scripts in succession before I'm ready to start writing code in each one, it is a little tedious to make a script, wait for the domain to reload, make the second script, wait, and so on
ideally I could change the setting to never reload, create what files I need, then change it back to the original setting
that should be easy enough via UnityEditor.EditorApplication.LockReloadAssemblies (); https://docs.unity3d.com/ScriptReference/EditorApplication.LockReloadAssemblies.html
How could I add a dropdown menu for it in the editor?
This is a side of unity I havent touched before
https://github.com/marijnz/unity-toolbar-extender I found this a couple days ago, and it made me think that I could recreate the auto/manual update menu that houdini has
actually, I could just do it as a toggle switch. Auto/Manual is all I need, On Mouse Up is more of a special case in Houdini
weird case here. the above structures all resolve the "ShowWhen" attribute completely fine.
these are not hitting the property drawer however
i must be overlooking something really dumb.
nothing happening in the attribute at all when i mess with the values. and here's the attribute, just a very basic propertydrawer show/hide on enum values
figured it out, apparently the attribute has to be defined very specifically
apparently can't have Min attribute and my custom one together
oh, or mine has to come first it seems.
this ok
not ok
You just add a static method with the MenuItem attribute
[MenuItem("Edit/Lock Assembly Reloading")]
public static void LockReloading()
{
EditorApplication.LockReloadAssemblies();
}
It is because is Min is a PropertyAttribute which takes over how the field is drawn. And you can only have a single one at a time on a field.
it definitely respects the minimum i define when i put ShowWhen first.
order of operations? 
Hello,
I created a Monobehaviour holding a unique id (using System.Guid).
I also created an editor script for this component that sets this property value during the OnEnable() hook.
The goal is to have this property value persisted by the serialization. I want its value to stay consistent between editor mode and play mode/runtime and also keep its value when unloading/reloading the scene holding it.
My issue here is when I add this MonoBehaviour to a prefab, the value is set at the prefab level and all instances of the prefab in a scene then share the same id which is not okay for my need.
This is illustrated by the two screenshots I added.
How can I know within the editor script if the targeted gameobject is in a real scene or in the prefab edition scene please ?
Below is the code of the MonoBehaviour and related editor script.
using System;
using UnityEditor;
using UnityEngine;
public class MonoBehaviourID : MonoBehaviour
{
[SerializeField]
private string _uniqueID;
public string UniqueID => _uniqueID;
public void Generate()
{
_uniqueID = System.Guid.NewGuid().ToString();
}
public void Clear()
{
_uniqueID = string.Empty;
}
}
[CustomEditor(typeof(MonoBehaviourID))]
class MonoBehaviourIDEditor : Editor
{
void OnEnable()
{
MonoBehaviourID id = (MonoBehaviourID)target;
if (!id.gameObject.scene.IsValid() || PrefabUtility.IsPartOfPrefabAsset(id)) // this test does not work to distinguish between the object being in a real scene versus the prefab edition scene
{
id.Clear();
EditorUtility.SetDirty(target);
return;
}
if (string.IsNullOrEmpty(id.UniqueID))
{
id.Generate();
EditorUtility.SetDirty(target);
}
}
public override void OnInspectorGUI()
{
MonoBehaviourID id = (MonoBehaviourID)target;
EditorGUILayout.SelectableLabel(id.UniqueID);
}
}
Thank you
Hi everyone, I have a quesiton about serialised objects, I have written an editor window that modiefies serialised properties, this editor is opened by clicking a "modify" button on a scripatable object. However, once I retarget the inspector while the window is open (to look at something else) I then get errors saying the serialised objects and properties are disposed.
Is their a way to keep these objects in memory? Like a counter I can add to to say they are in use?
I presume you need to make your own serialized object for the asset to avoid it being disposed of early
What would the best way to this be?
I have tried:
newObject = new SerializedObject(oldObject);
However this is a type mismatch, is this the correct way of doings this?
_serialisedObject = new SerializedObject(_serialisedObject.targetObject);
This does seem to work, so I'll stick with it for now! Thank you :D
great. hopefully if they apply properties in the correct order then it will work without conflicts
I've created a system, which requires me to create 3 separate classes to add a new function. Is there an easy way to create a tool, that will create those 3 classes for me, from a template? Or do I have to write something from scratch
it's not a particularly complicated template, literally just copy/paste a bunch of text, and substitute the class name in a few places
you can use T4 templates for that, VS & Rider have integrations for that so you can easily generate c# sourcecode
are these stored in the project somewhere, so they can be shared via git repo? never heard of these
works similarly to any template language you'd use in webdev
yes
its just a markup text file, that gets inhected with some data and it can generate any text file format from that, you need to run that generator offline in your IDE or from the commandline
its not a source generator that runs at compile time
My ideal solution would be an option in the asset create menu, kinda like [CreateAssetMenu], is it possible to plug those two together?
like inside the editor
as mentioned, Rider&Vs should recognize T4 files and allow you to "build" them right away
you can call the T4 processor from a button in unity ofc. its also not hard to generate a text file yourself without a template language
okay, cool, that's my ideal usage, do you have a link to a documentation or guide regarding that type of integration? I already have my own EditorWindow for this purpose I just need to plug it into the actual file creation and fill it with those files with content
specific to rider: https://blog.jetbrains.com/dotnet/2019/12/17/introducing-t4-text-template-support/
thanks! I'll take a look
how do I run it from within unity though? Rather than IDE
it seems all integrated into IDEs but ideally it'd be inside a unity tool
do I need to implement a whole T4 processor in my tool...?
You use the commandline tool for T4: https://learn.microsoft.com/en-us/visualstudio/modeling/generating-files-with-the-texttransform-utility?view=vs-2022
and you can invoke that with via Progess.Start(), either directly or by launching the platform's CLI and invoking shell commands there: https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.process.start?view=netstandard-2.1
Hi all, is their a way to render the wireframe of the mesh using PreviewRenderUtility, Handles doesn't seem to have a function for it, and Gizmos don't seem to render, even when adding a mono behaviour to game objects in the previewed scene.
GL has a setting for it iirc
are the GL settings global?
You set and then unset them
Ah, would I need to use this then with Graphics.DrawMeshNow?
You do
GL.wireframe = true;
// render mesh here...
GL.wiretframe = false;
What i mean is, when I render the mesh. Since I'm using
renderPreview.Render(true); // this being the PreviewRenderUtility
Would how would I seperate out just a single game object to render in wireframe, and if I can't would I need to use a different rendering function and render the mesh manually?
You would it yourself yeah. Iirc you do renderPreview.Begin() (or beginStatic), then you can do Graphics.DrawMesh surrounded by the GL call. And then do rednerPreview.Render() and then end.
Actually.. might have to call Render before manually drawing the mesh
Gotcha, thanks! I'll give it a go!
Works perfectly! Thank you
So, this is my first time using UI Builder. I'm working on property drawers for dozens of classes in my project.
I understand that I can add a field like container.Add(new PropertyField(property.FindPropertyRelative("sourceName"))); and changing it will change sourceName directly just like if I did it on the inspector. But what do I do if, instead of changing sourceName directly, I want it to call my static class SourceHelper and use the method SetName(Source source, string name)?
[CustomPropertyDrawer(typeof(Source))]
public class SourceDrawer : PropertyDrawer
{
public override VisualElement CreatePropertyGUI(SerializedProperty property)
{
// Create property container element.
var container = new VisualElement();
container.Add(new Label("Source Editors"));
container.Add(new PropertyField(property.FindPropertyRelative("sourceName")));
container.Add(new PropertyField(property.FindPropertyRelative("sourceID")));
container.Add(new PropertyField(property.FindPropertyRelative("author")));
container.Add(new PropertyField(property.FindPropertyRelative("convertedBy")));
return container;
}
}```
(PS: Is everything else ok? Am I doing it right?)
Everything looks right. You'd just need to call EditorUtility.SetDirty(source); after changing the value of any of the serialized properties, if you want them to be updated in the inspector.
You would register an event on value change, and change the newValue property of the event.
aaaaaaaaaahhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh there I go learning how events work
Been using Unity for a solid while and I've been avoiding events because they look complicated. 😔 I guess it's time I stop beating around the bush
var field = new PropertyField(property.FindPropertyRelative("sourceName"));
field.RegisterValueChangeCallback(evt => {
evt.changedProperty.stringValue = myStaticMethod(evt.changedProperty.stringValue);
});
You could try something like this. I am not sure if the change event is for changing of binding or change of the value... one way to find out.
Thank you! But I do think it's time I go and learn the event system by myself. I'll come back to this to cross reference it with yours tho 🫡
ohh you wanted to call the METHOD instead of actually changing the field.
What I understood was you wanted to change the FIELD from a METHOD.
my bad.. in this case yes what MechWarrior suggested is the way. I'm cutting back on coffee and seems I'm missing a lot of important details lately 🙄
Is it possible to render 3d texture preview (like the one when you doubleclick Texture3D field) in custom editor window? I was trying to use EditorGUI.DrawPreviewTexture(textureRect, texture3D, null, ScaleMode.ScaleToFit); but it results in Unsupported D3D format 0x1 errors. (not counting there will not be enough control - I would prefer it to be able to rotate it and so)
_Being able to display selected slice would be probably enough but 3d is 3d 🙂 _
If unity can show it already then you probably need to get the unity asset preview as a texture first, then draw this.
https://docs.unity3d.com/6000.0/Documentation/ScriptReference/AssetPreview.GetAssetPreview.html
I'm getting a "Failed to find entry points" error with a c# DLL I'm using (Harmony). It seems to be due to the DLL being analyzed by Burst/Jobs. Every call I make to functions with the DLL work fine, so I think it's just an issue with burst. But I'd rather not distribute a plugin throwing errors like this. Any suggestions?
The error is
Failed to find entry-points:
System.Exception: Error while loading assembly references for Assembly-CSharp-Editor ---> System.Exception: Error while hashing assembly
System.Exception: Error while hashing type reference '10000D0' in assembly '0Harmony.dll' ---> System.BadImageFormatException: Read out of bounds
When I disable Burst via the project settings, I still get the error, but I don't get the error on projects without burst included.
EditorGUI.PropertyField only draws the plainest inspector for a given property - how do I draw my custom inspector for a given property instead, from within a different property drawer?
I have a drawer for my class, and it draws the class and all its children using the typical
var enumerator = property.Copy();
EditorGUI.indentLevel++;
EditorGUIUtility.labelWidth += 17;
if (enumerator.NextVisible(enterChildren: true))
{
do
{
if (enumerator.depth <= property.depth)
{
break;
}
rowRect.y += rowRect.height + EditorGUIUtility.standardVerticalSpacing;
rowRect.height = EditorGUI.GetPropertyHeight(enumerator);
EditorGUI.PropertyField(rowRect, enumerator, true);
} while (enumerator.NextVisible(false));
}
EditorGUIUtility.labelWidth -= 17;
EditorGUI.indentLevel--;
but if it encounters for example a float with a [Range] or something with a custom inspector, it just draws the default inspector for them instead rather than the [Range] inspector
Weird, I am using very similiar code and it draws the children normally
Also why do we need to make a Copy of the property first?
not my code and the person who wrote it left the company, so not 100% sure why
The code i snatched also uses .Copy, I got rid of it just to see what happens and I didn't notice anything
the issue was that my variables were properties, and I forgot to make it field:Range() instead of just [Range()]
fixed now
Ah alright
Hi everyone, I was wondering is their a way to change the view of a Editor.RenderStaticPreview?
https://paste.ofcode.org/6FZQB6i9Lgaza4u864KSGg
My enum selector for ScriptableObjects works, but I have to select a ScriptableObject twice in order to actually select it - why?
Unity recycles propertydrawers so I don't think using member variables is a great idea. It might be related to the issue too
Is there a way to pre select search items when opening up a search window or picker via SearchService in Unity 6.
I was trying to add the SearchItemOptions.Highlight or .FuzzyHighlight to achieve this in the Provider.FetchItems callback, but it seems to have no effect. The SearchContext.Selection is readonly. Not sure how else I could achieve this.
custom provider code
internal static SearchProvider CreateProvider()
{
return new SearchProvider("idAsset", "UniqueAssetSearch")
{
filterId = "me:",
fetchItems = FetchItems,
};
}
static IEnumerator FetchItems(SearchContext ctx, List<SearchItem> synchronousItemResults, SearchProvider provider) {
var types = TypeCache.GetTypesDerivedFrom<UnityEngine.Object>();
int index = 0;
foreach (var type in types) {
var item = provider.CreateItem(ctx, $"Search Item Type ID {index}");
item.label = type.Name;
item.score = index;
item.description = $"{type.FullName}";
item.data = type;
item.options |= SearchItemOptions.Highlight | SearchItemOptions.FuzzyHighlight;
index++;
yield return item;
}
}
opening search window code, which uses above provider
var providers = new List<SearchProvider> { SearchService.GetProvider("idAsset") };
var searchView = new SearchViewState(new SearchContext(providers));
searchView.trackingHandler += OnAssetQueryChanged;
SearchService.ShowPicker(searchView);
Reflection to the rescue https://github.com/Unity-Technologies/UnityCsReference/blob/master/Modules/QuickSearch/Editor/UI/SearchViewState.cs#L113C24-L113C35
(the latter is probably better)
thanks!
The fact that SetSelection, which feels like a basic feature, is on an internal class is unfortunately a red flag for me that indicates I should just use my own UI instead of trying to get the built in ShowWindow/ShowPicker to do what I need.
Maybe you're just looking on the wrong object for the public API https://docs.unity3d.com/6000.0/Documentation/ScriptReference/Search.ISearchView.SetSelection.html
Is it possible to edit multiple sub object of a given SerializeObject at the same time ? The idea would be whenever we select two object that are of the same time, we would show a property field for both.
We have a Graph Tool and we are currently seeking to see if we can change our ScriptableObject into SerializedReference. Supposedly it would reduce the loading time of the graph, removing the need to instantiate each node individually when creating a new instance. (Not really sure though)
One of the work around we are currently using is to use a temporary scriptable object that we instantiate for each element we select and then use a serialized property field. Is it the only/best way of doing it ?
A SerializedObject cannot have sub objects. But you can edit multiple of the same object easy enough. Just pass multiple objects in to the constructor of a SerializedObject
There is only serialized object, the graph.
But there would be multiple element that we want to edit at the same time, such as the node of the graph
You either just manually drop them and loop over them, or you add a temp ScriptableObject with a single field that you assign and use to draw the SerializedProperties for all of them like you were sayin
Also, is it possible to clone a serialize property the same we can with instantiate for a given ScriptableObject ?
Just getting the boxed value for it will 'clone' it because unity serializes by value. (Not 100% about fields serialized by reference though)
Yeah, we would be working with SerializeReference.
But you can't clone it like you are thinking because a SerializedProperty is just a pointer to some data.
As far as I nkow, it is possible to have two object point to the same SerializeReference, I believe it would not work correctly.
It is not possible for two UnityEngine.Objects to point to the same SerializedReference object if that is what you mean
Obviously not, but it is possible in a given serializeobject.
Of course
How would you clone a serializereference then ^
var cloned = JsonUtlity.Deserialize(JsonUtility.Serialize(serializedProp.managedReferenceValue));
Thanks, I will look into it.
It is just a normal C# class so you can clone it how you would any normal C# class. This is just the easiest way since it uses Unity's serialization system.
Is there any easy way to retrive the serialize property given an instance of an object ?
Like, finding where it is in the SerializedObject?
Yes
Nope, just would have to iterate through every serialized property and check to see.
I mean, I kinda have to rework the whole system, it would be easier if I could simply do something like SerializeObject.GiveMeThePropertyOf(node)
The issue is you are mixing serialized data access with direct access
That is almost always a bad idea and makes things more complex
@gloomy chasm, thanks for your help. I finally used a CloneWrapper ScriptableObject because the whole system is not using SerializeObject/SerializeProperty and it might take too much effort to refactor at that point.
public class CloneWrapper: ScriptableObject
{
[SerializeReference] private object data;
public object Data { get => data; set => data = value; }
}
Trying to get inspector grid to work. It works fine it seems, but its spewing some errors that are difficult to trace for me.
https://paste.ofcode.org/WbrbkVxemzCq3jenDrNBu9
Any ideas what it could be ?
first time doing a custom inspector.
didn't see the ISearch interface, nor that it gets returned from SearchService.ShowPicker/Window/Context 🤦♂️
That some funky stuffs that should not be happening and are not related to the code you just posted as far as I can tell. Try restarting Unity if you haven't yet.
Oh okay, I restarted and didn't show up this time even after a recompile of script. Weird.
Maybe something was badly written before ? not sure lol
hopefully stays okay.
thanks !
Looked like something internally in Unity got in to a weird state, maybe on the C++ side. Glad it fixed it!
great minds think alike
We upgraded from 2021 to Unity 6 recently, since the build system in Unity leaves a lot to be desired we've been rolling with our own for a long while now. Essentially it sets up the build by interacting with PlayeSettings & EditorUserBuildSettings to execute a build matrix. As a part of this we use PlayerSettings.SetScriptingDefineSymbols(), which is probably pretty common because using scripting defines is almost mandatory. The problem is that doing so kicks off a recompilation of scripts, which is understandable, but this causes BuildPipeline.BuildPlayer to fail. In at least 2021 & earlier versions of Unity this did not happen, I guess it's because the script recompilation now happens on another thread. One would think the way around this is to use EditorApplication.update & EditorApplication.isCompiling to wait out the script recompilation, but this also doesn't work because EditorApplication.update gets cleared as part of the script recompilation, there's no way to get the other side of it, at least it would seem to me. I've posted on the forums about this a few days ago, but there's almost no-one there. I thought I'd ask here since I presume we're not the only ones using our own build setup, and if so it would seem inevitable that others has run into the same issue. Would love some input on it & how others have solved this problem if so.
A recompilation will cause the current managed code state to be lost as assemblies get removed and reloaded so your code execution cannot survive past this reload.
projects i work on are on 2022 and we also have an custom system to apply build settings. We also set symbols but this seems to work just fine. We use PlayerSettings.SetScriptingDefineSymbolsForGroup()
perhaps unity 6 changed something
That's fair & makes sense, but there has to be some way to get to the end of the recompilation to run BuildPlayer
Or that BuildPlayer waits out any recompilation internally instead of failing
I'll try that version & see if it makes a difference
im not sure. i can only presume the fact that we set these and then trigger a build after makes it work as it did not yet recompile anything
Yeah I think this is a new thing, it worked for us in 2021 just as it does for you guys in 2022
How I handled something similar before was to write to a file which i then check on platform change (can be done also for script reload i think) to see if something should be done
SetScriptingDefineSymbolsForGroup exhibits the same problem & has been made obsolete in Unity 6 it seems. Yeah I might have to do some trickery & pokery to get to the other side of recompilation, it's a PITA though with how we have stuff setup at the moment.
as soon as you set symbols does code execution end or does the rest complete before recompilation?
It still survives for a while, we use "EditorCoroutines" by leveraging EditorApplication.update, so we can see that EditorApplication.isCompiling is true for a couple of yields before it gets cleared, probably as part of assembly reload as you stated
Ah yea well that won't work because it probably goes to recompile next editor update so you want to do everything synchronously after setting symbols.
Hmm, yeah, perhaps if I stuff it around a bit & make sure that there's no yield between the set symbols & buildplayer it might work. We enable / disable packages a part of the build in between currently, and that requires us to wait for that action to complete, but we could probably do that before we get to set symbols instead.
that would cause a recompile too and then you get the same problem, unless you can do everything in one batch before a recomp
Any Idea how I can properly configure a new Texture and its sprite from an adjacent ScriptedImporter.
I always have: 'some.png' and 'some.custom_type' next to each other. custom_type has details on how to import the texture (also other data producing a ScriptableObject). Meaning both resolution and sprite configuration.
Currently Im loading the textures "TextureImporter", edit it and call "SetDirty" and "SaveAndReimport". The weird part is this only works if the sprite file has been manually touched by the user. Otherwise it will just ignore the changes....
It seems like
EditorUtility.SetDirty(importer);
importer.SaveAndReimport();
Don't work until I selected the texture in unity once (no save just select in "project")
If you got TextureImporterSettings then try texImporter.SetTextureSettings() and then texImporter.SaveAndReimport();
also try setting the asset itself as dirty. i had similar issues with importers not saving before
I tried both:
EditorUtility.SetDirty(importer);
EditorUtility.SetDirty(AssetDatabase.LoadAssetAtPath<Texture2D>(texturePath));
importer.SaveAndReimport();
and:
var factories = new SpriteDataProviderFactories();
factories.Init();
var provider = factories.GetSpriteEditorDataProviderFromObject(importer);
provider.InitSpriteEditorDataProvider();
provider.Apply();
EditorUtility.SetDirty(importer);
EditorUtility.SetDirty(AssetDatabase.LoadAssetAtPath<Texture2D>(texturePath));
importer.SaveAndReimport();
it doesn't work until I touch the texture for the very first time....
I cancel the import and configure/reimport the texture until it has the settings I want from the beginning:
aka:
1. detect texture settings and configure
2. depend on texture
3. if texture was required to change, return and wait for reimport
4. do more data import and use configured texture/sprites
I did a work around at some point by using a bat file to essentially launch Unity, change the Scripting Definition, and relaunch it to build. Also, for most platform, the "extraScriptingDefines" parameters of the BuildPipeline.BuildPlayer work correctly. I'm currently looking to change the whole setup to use build profile though. (Using .bat for most of the afterwork)
is there a way to expose/draw fields in here?
iirc this is the source https://github.com/Unity-Technologies/UnityCsReference/blob/master/Editor/Mono/Inspector/MonoScriptInspector.cs
You can probably replace it quite easily, not sure if you can easily add fields
I am thinking of exposing static fields
then creating a connection to change them in the editor
think that's doable?
Again, adding fields is probably hard without replacing the whole thing
Updating static fields is easy but remember that they'll be reset when the domain reloads
You'll need some other mechanism to store that state (and even then ti won't persist into builds etc)
How do I pass a scriptableobject to my UI in a custom editor
As CreateGUI is called before I can set my window.target = preset
Use CreateWindow instead. GetWindow gets an existing instance of the type of window if there is one, and if not it creates on and .Show() it before returning.
unfortunately CreateWindow also seems to show before returning the window
Ahh it is CreateInstance then I guess
Weird, I thought I remembered using CreateWindow but guess I was just thinking of CreateInstance
does anyone know if this is bug in unity 6 or am I doing something wrong? I used to maximize game window or starting play mode in previous versions but in unity 6 I'm getting nullreferenceexception when I try to do view.maximized = true on load (but it works fine later)
this is what happens in unity 6
for now I just fixed it with
EditorApplication.delayCall += () =>
{
if (GetGameView(out var view) view.maximized = true;
};
and it seems to work
Hey guys,
I'm having some issues with our editor menu created with [MenuItem("MyMenu/Builds/Config/Do Something Useful")]
What is happening that on mac (Apple Silicon) the menu kind of makes the editor freeze.
This happens when opening the menu, it will be drawn as completely blank. We are using 2022.3.24f Has anyone encountered this?
You need to show your code.
Does anyone know or have suggestions of a better method for a running an AsssetPostProcessor on specific models/fbx WITHOUT falling back to using convoluted naming on the fbx files?
I have some ModelProcessors that need to run on specific models. Currently I do this via prepending tags to the end of the file name e.g. '[LM]' for lightmapped asset. But its not ideal.
I think I investigated using actual tags in the past but they aren't available at this point in the pre/postprocess.
A slightly cleaner method might be to filter the fbx based on folder names, but then I have multiple different tags for different models/fbx, so that doesn't work.
userData field doesn't work for you?
I'm looking into this again, but feel like I must have done so when I originally wrote the code i'm looking to update back in 2021. I have seen a few threads about how people were unable to get the userdata to save to meta files and the solutions found - so maybe that was an issue.
However that still leaves the issue of how to generate the userdata.
I could add it in the editor, but then i'm back to tagging the file name (unless I can find a way to extended default model importer).
I could add it to the fbx, which works for my own files, but not so useful for thirdparty models.
For reference I am looking into solutions such as;
https://discussions.unity.com/t/how-to-add-custom-fields-into-any-assetimporter-inspector-solution/1527490
https://discussions.unity.com/t/how-to-add-custom-editor-to-assetpostprocessor/853286
But without a native Unity solution i'm not keen to invest into these solutions as they might be too 'brittle' especially long term. So it might be better for me to look into alternative solutions than embedding this data at import.
Maybe I just don't use the original fbx, and generate new meshes during import or in the editor - though I want to try and avoid having convoluted instructions to achieve this too.
This is the most frustrating aspect, that there is no clean way to do this. If the modelImporter was extendable it would be so much simpler.
you can make your own importer and swap an asset to that but im not sure if you could easily use the existing model importer as well and then do your custom stuff 🤔
I think newer unity versions show a dropdown to change importers when more than 1 exists (e.g. when using the unity psd importer)
a lot of things would be way easier if they were extendable, it's 2025 and unity still doesn't have a way to add codecs to videoplayer or even open videos from streams
unity is frustrating
so many times I want to do something and realize that something is not extendable and the only way to add a simple function is to just reimplement it from scratch
Just remembered a potential issue with userData is if another plugin/script uses it. The problem being they can overwrite each other, unless both are written in such a way to respect the existing data. There was talk about Unity trying to address this, but it doesn't look like they bothered.
typical, I'm seeing a lot of talk about different things and instead of implementing things that people ask for or opening them for extension they overhaul their rendering API for 100th time making it more limited than before
is it possible to use a folder as an object and assign it like a script? (drag into a field) im looking for an alternative to typing out the path
unless someone has a better alternative, im open to new ideas ofc
Could be wrong but I don’t think there’s anything prebuilt for that, you could probably do something simple with a little scriptableobject though
Yuup, sure is, though nothing built-in for it. I did it somewhere I can dig it up if you want
turns out you can open up the file explorer and have it selected that way, but id love to know your method as well!
Here you are, this was implemented to mirror the implementation of the ObjectField. So if it is a bit funky looking, that is why haha.
could you point to which bit im meant to look at, im very very new to editor scripting so this is a bit overwhelming lol
Yeah sorry it isn't the easiest one to look at. Basically it is line 111
private void OnDragPerform(EventBase evt)
{
string validatedPath = ValidateDnD();
if (!string.IsNullOrEmpty(validatedPath))
{
DragAndDrop.visualMode = DragAndDropVisualMode.Generic;
_folderField.value = AssetDatabase.AssetPathToGUID(validatedPath);
DragAndDrop.AcceptDrag();
evt.StopPropagation();
}
}
oh so its similar to how youd do drag/drop in a game kinda
Yeah. UITookit has some events specific for DragAndDrop, like DragPerformEvent and also a static class DragAndDrop which is used in the editor for all drag and drop operations.
So you just listen for the even, check to see if it is dragging a folder, and if so, accept the drag and store the path
does anyone know how to fix this? i made the repository via the github website which is likely why it has no meta file
also getting this error when appending a file with my editor script
it gets spammed 999+ times
Is there a method that gets called when a unity package is first time installed/ added to a project?
if i have this function to create an instance of a so, i have to set it dirty and assetdatabase.saveAssets() after i modify it?
public static T CreateScriptableObject<T>(string relativePath)
where T : ScriptableObject
{
var instance = CreateInstance<T>();
AssetDatabase.CreateAsset(instance, relativePath);
AssetDatabase.SaveAssets();
return instance;
}```
heya, im currently creating a custom window and am encountering a really annoying issue where some of my variables are reset whenever i adjust my code. Here is the simplest way i found to reproduce my bug
public class Tool {
public int x = 2;
}
public class ToolMenu : EditorWindow
{
int y = 1;
Tool z;
void OnEnable() {
Debug.Log(y);
y = 3;
if(z == null) {
z = new Tool();
Debug.Log(z.x);
}
}
}
this prints
1
2
-- Reload --
3
2
and not
1
2
-- Reload --
3
someone pointed out [SerializeReference] to me
that fixed it ;-;
Has anyone tried adding custom controls to the UI Builder window? I'm looking to add more functionality to it specific to my project.
I want to make a menu item that will launch the apk build with an automatically generated apk name. PLease, tell me how to do this?
The core is triggering a build with the desired options. You may need to modify some build settings and/or adjust the build profile before you start the build.
https://docs.unity3d.com/ScriptReference/BuildPipeline.BuildPlayer.html
Thanks! Will try
Not sure if this is the right place to ask but is there any way to stop the heiarchy from hiding the scene upon loading? I searched for the solution but couldn't find anything
You meant collapsed ? You could probably use Reflection to call a function to expand it.
A post that seem to be attempting to do it this way.
https://discussions.unity.com/t/how-to-collapse-hierarchy-scene-nodes-via-script/726741/8
Hi everyone, I was wondering, is their a way to change the Icon of a material based on the its using shader?
I know I can just have a different name for the material to show its shader too, but I was wondering if their was a way of changing the materials icon based on the shader as I am having to assign a lot of materials in the editor, ones that specifically have to use a custom shader for them to be rendered at all.
Giving this a go,thanks
Without knowing if you can change the icon of a material dymically, I know you can easily modify the rendering of the whole line. You could add an additionnal icon at the right most of the line.
Unfortunately, it doesnt work. Here's the code:
{
foreach (var window in Resources.FindObjectsOfTypeAll<SearchableEditorWindow>())
{
if (window.GetType().Name != "SceneHierarchyWindow")
continue;
var method = window.GetType().GetMethod("SetExpandedRecursive",
System.Reflection.BindingFlags.Public |
System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Instance, null,
new[] { typeof(int), typeof(bool) }, null);
if (method == null)
{
Debug.LogError(
"Could not find method 'UnityEditor.SceneHierarchyWindow.SetExpandedRecursive(int, bool)'.");
return;
}
var field = scene.GetType().GetField("m_Handle",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
if (field == null)
{
Debug.LogError("Could not find field 'int UnityEngine.SceneManagement.Scene.m_Handle'.");
return;
}
var sceneHandle = field.GetValue(scene);
method.Invoke(window, new[] { sceneHandle, expand });
}
}```
{
SceneManager.LoadSceneAsync(nextSceneIndex, LoadSceneMode.Single);
while (SceneManager.GetActiveScene() != SceneManager.GetSceneByBuildIndex(nextSceneIndex))
{
yield return null;
}
SceneManager.UnloadSceneAsync(previousScene);
SetExpanded(SceneManager.GetSceneByBuildIndex(nextSceneIndex),true);
}```
I'm using 2019 LTS and according to the replies it should work for that version
I cannot help you with that. I would not invest more time than I am ready/having a project with the exact version, etc.
You could always print the error
But, if you arent able to understand the error, maybe it is to advance of a subject for you and you should live with the limitation.
Adding an additional icon would work, how would I go about doing this?
EditorApplication.projectWindowItemOnGUI
Also, you might want to look into EditorGUIUtility.SetIconForObject to change the icon itself.
Thanks, I'm suprised that there aren't many people with the same issue is mine. Like they're okay with the heiarchy collapsing everytime they switch scenes. It makes it a bit annoying when testing.
Hiya, another question, I'm using render preview utility to do some custom modifications to 3D data in scriptable objects. Part of this has the data replicated visually to a gameobject inside the preview, (just sets the matieral of the object based on specific input fields so its visually clear what the data is representing).
Since this is a monobehaviour it currently sits in the main project folder, I would like to move this to an editor folder though as it isn't needed in runtime, and for organisational purposes to keep things to do with that editor together.
When I move this to the editor folder I get errors as its trying to reference build mode scripts in the editor, which yes does make sense.
But I was wondering, is their a "editor" equivelent of monobehaviours, that I can use with the PreviewRenderUtility that can be put in the editor folder?
Hi, I am creating a wrapper class for variables that should be togglable.
I just can't figure out how to display the property name as a label next to the toggle.
I am using the value type now but that doesn't seem like the best solution.
Is this even possible and, if yes, how would I go about it?
using System;
using Sirenix.OdinInspector;
namespace TimelineMaker {
[Serializable] [InlineProperty] [HideLabel]
public class Optional<T> {
[HorizontalGroup("Toggle", width: 20)] [HideLabel]
public bool UseValue;
[HorizontalGroup("Toggle")] [LabelText("$PropertyName")] [EnableIf("UseValue")]
public T Value;
private string PropertyName => Value.GetType().Name;
public Optional(T value, bool useValue = false) {
UseValue = useValue;
Value = value;
}
}
}
Please @ me if you are able to help.
You just have to have it in a runtime folder, no way around it. But you can wrap it in a #if UNITY_EDITOR so it is not included in builds. If you just need rendering, you can use the Graphics API and GL API with the render preview utility.
This is more of a Odin question no?
I am not sure if that's doable with odin, that's why I asked for a regular c# solution.
You would have to make a custom property drawer for the Optional class
I see, just to make sure, that's regular solution, nothing to do w odin, right?
Ah damn, nw's then. I am using the defines to block it from runtime code, but was thinking it would be more "organised" to keep it with the other parts of the editor tool I was making. Thanks anyway though ^-^
How can I create a simple "blank" asset? I just want to create an empty file that has an associated GUID. I'm planning on creating a bunch of assets at once and they need cross references, so ideally I can create blank assets first to get their corresponding GUIDs, which I can then use to populate them
Create a ScriptableObject ?
ScriptableObjects are not empty though, they have a header but I suppose I could overwrite it afterwards
Also, really not sure why you are doing this though. It seem to not be a really good solution, but I do not know the context.
Context is batch creating a "templated" assembly definition setup. So I would create N amount of assembly definitions, some of them might have "references" to each other, but I would need to import each one to get their corresponding GUIDs. Since there's gonna be a bunch I'd like to do it in two batch steps instead of one by one
Could you not create them, then assign the reference ?
You can also use AssetDatabase.StartAssetEditing to prevent reimport each time.
I can but I would need to do two passes which is what I'd like to avoid by batching it. I can't reference one that's not been created yet, so I'd have to create each one first and then do a 2nd pass with referencing the ones I created
You would need to do the same with a temporary asset.
Yeah, problem with specifically Asmdefs is that importing them also triggers a script recompile, depending on the project that can be very slow
30s maximum. It's not like you are doing it a lot don't you ?
You import your 10 asmdefs, then you reimport.
50 seconds for a single recompile in my case
Also, you can manually modified the guid of an asset if you really wants. Not sure with asmdef, but with prefab, etc. you can do it pretty easily.
Hence you could always set your own id instead of using a temporary asset.
That might be a good idea actually. I've got some ideas to try out now cheers!
I genuinely cannot comprehend why this code isn't working, especially as it was working just fine when I used a custom scale vector instead of the transform local scale... is this just some weird transform editor bs?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
[CustomEditor(typeof(BoxGizmo), true)]
public class BoxGizmoEditor : Editor
{
protected virtual void OnSceneGUI()
{
BoxGizmo box = (BoxGizmo)target;
Transform t = box.transform;
Vector3[] faceNormals =
{
Vector3.right, Vector3.left,
Vector3.up, Vector3.down,
Vector3.forward, Vector3.back
};
for (int i = 0; i < faceNormals.Length; ++i)
{
Vector3 normal = faceNormals[i];
Vector3 worldNormal = t.TransformDirection(normal);
Vector3 localOffset = Vector3.Scale(normal, t.localScale * 0.5f);
Vector3 handlePos = t.TransformPoint(localOffset);
EditorGUI.BeginChangeCheck();
Vector3 newHandlePos = Handles.FreeMoveHandle(handlePos, Quaternion.identity, HandleUtility.GetHandleSize(handlePos) * 0.1f, Vector3.zero, Handles.RectangleHandleCap);
if (EditorGUI.EndChangeCheck())
{
Undo.RecordObject(box, "Resize Box");
float delta = Vector3.Dot(newHandlePos - handlePos, worldNormal);
t.localScale += normal.Abs() * delta;
t.position += 0.5f * delta * worldNormal;
}
}
}
}
oh I just saw the pins actually, this might be a serialised thing (or not, idk, I'm very confused)
I'm not even going to pretend to understand what's happening, here's my behaviour and updated code...
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[ExecuteInEditMode]
public class BoxGizmo : MonoBehaviour
{
private void OnDrawGizmos()
{
Gizmos.color = Color.yellow;
Gizmos.matrix = transform.localToWorldMatrix;
Gizmos.DrawWireCube(Vector3.zero, transform.localScale);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
[CustomEditor(typeof(BoxGizmo), true)]
public class BoxGizmoEditor : Editor
{
protected virtual void OnSceneGUI()
{
BoxGizmo box = (BoxGizmo)target;
Transform t = box.transform;
Vector3[] faceNormals =
{
Vector3.right, Vector3.left,
Vector3.up, Vector3.down,
Vector3.forward, Vector3.back
};
for (int i = 0; i < faceNormals.Length; ++i)
{
Vector3 normal = faceNormals[i];
Vector3 worldNormal = t.TransformDirection(normal);
Vector3 localOffset = Vector3.Scale(normal, t.localScale * 0.5f);
Vector3 handlePos = t.TransformPoint(localOffset);
EditorGUI.BeginChangeCheck();
Vector3 newHandlePos = Handles.Slider(handlePos, normal, 0.05f, Handles.CubeHandleCap, 0.0001f);
if (EditorGUI.EndChangeCheck())
{
float delta = Vector3.Dot(newHandlePos - handlePos, worldNormal);
if (Mathf.Approximately(delta, 0f)) continue;
Vector3 newScale = t.localScale + normal.Abs() * delta;
newScale = Vector3.Max(newScale, Vector3.one * 0.0001f);
t.localScale = newScale;
t.position += 0.5f * delta * worldNormal;
}
}
}
}
^this cube shit helped me fix it actually and I'm not cruel enough to leave this unanswered. Basically, because I moved from a custom vector3 to the transform scale the gizmo and handles used that transform scale for position changes, but I was also accounting for the scale in my maths. By using Vector3.one for the gizmo scale and normal*0.5f for the offset, it then multiplied that by the scale anyways and boom it works
Hey folks!
Trying to use a Generic List Type to reduce repeated work when adding a List to a Custom Inspector using the following:
I'm getting an error because I'm not supplying a correct Type for a Generic List, I've tried supplying the Type using IncomingList.GetType() / newList.GetType()/typeof(T) as well as creating local Type variables for the purpose of referencing but no dice there either. Is there any way to supply T as a Generic type to satisfy 'typeof' and 'as' arguments here?
static void ListVariable<T>(List<T> IncomingList, bool BoolToRef, string ListDisplayName)
{
BoolToRef = EditorGUILayout.Foldout(BoolToRef, ListDisplayName, true);
if (BoolToRef)
{
EditorGUI.indentLevel++;
//List Creation
List<T> newList = IncomingList;
int size = Mathf.Max(0, EditorGUILayout.IntField("Size", newList.Count));
while (size > newList.Count)
{
newList.Add(default);
}
while (size < newList.Count)
{
newList.RemoveAt(newList.Count - 1);
}
for (int i = 0; i < newList.Count; i++)
{
newList[i] = EditorGUILayout.ObjectField("Element " + i, newList[i], typeof(newList), true) as newList;
}
EditorGUI.indentLevel--;
}
}
you need to cast with a real type. typeof() produces a Type instance from a real type.
show where you create newList too
(T)EditorGUILayout.ObjectField("Element " + i, newList[i], typeof(T), true);
do not use as to cast if you want it to work 😠
mb just corrected the example, see if it works
Gotcha - thanks for the quick reponse!
Calling like this:
ListVariable(_StaffStats.lucinaStats.UnlockedHunts, _StaffStats.lucinaStats.ShowUnlockedHunts, "Hunts");
References created List here
[Serializable] public class LucinaStats
{
//NOTES
//This Class will handle Lucinas current stat information
//A - Hunts Unlocked - Where Lucina can go
//B - Progress per Time Unit - If set to 2, each time unit spent would result in 2 progress
//C - Hunt Yield
[Header("Lucina Passive Slots")]
public List<LucinaHuntScriptable> UnlockedHunts = new List<LucinaHuntScriptable>();
Tried the above and screenshot attached for that - looks like the parameters auto update to expect something else here
check the doc page and use a version that is not deprecated: https://docs.unity3d.com/6000.0/Documentation/ScriptReference/EditorGUILayout.ObjectField.html
if there is another error then check what that is
Nice, will do, thanks!
Looking for free tools or add-on like simple mesh combine to reduce set pass calls and make level more optimized
Which EditorWindow method should I use to wait populating my window until it's actually visible? Say I have a window that's expensive to populate and it's docked somewhere but not visible since another tab is the one that's focused
Hey, I'm trying to make a custom property drawer for a simple class I made.
I saw UI Builder let's you configure binding, so I tried to have my custom Property Drawer in a uxml file that I could edit from the UI Builder. I tried to bind an integer field to a value,. I'm not sure how to use it properly, I think I'm missing something.
public class Entity
{
int life;
}
[CustomPropertyDrawer(typeof(Entity))]
public class Entity_Inspector : PropertyDrawer
{
public override VisualElement CreatePropertyGUI(SerializedProperty property)
{
// Load the UXML file.
VisualTreeAsset xml= AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/Scripts/Editor/EntityEditorUI.uxml");
// Instantiate the UXML.
VisualElement propertyDrawer = xml.Instantiate();
propertyDrawer.dataSource = property;
// Return the finished Property UI.
return propertyDrawer;
}
This is probably a kinda misunderstanding I have but when things like BeginHorizontal, BeginVertical etc. return their rects, How does that work? I was under the impression those rects are determined by the content that ends up in them but those are executed after the rect gets returned so like
Either they aren't returning what I'm assuming they are returning or there's some sort of foresight I'm missing?
I want to use Gizmos.DrawIcon, but with an icon that's not located in Assets/Gizmos, do you guys think that's possible?
Because I want to package my script with all of it's references in a specific folder, and placing the icon in the Assets/Gizmos folder complicates that
okay well I found a janky solution, you can escape the path with ../ and just put you your own
I forget but does that api take a path or a texture?
If its a texture, I'd load it using a guid instead of a path, which gets rid of all the file path shenanigans
It takes a path, and it assumes it begins with Assets/Gizmos, which is where my problem stems from
You can use UnityEditor.Handles.Label() and draw a texture but when I last tried to use it i had weird behaviour with the position
To answer this if you didn't already figure it out. Your uxml is using the runtime binding system while the editor uses its own binding system that uses the bindingPath property. I think in UIBuilder it is now called Editor Binding Path or something.
Thanks for responding 😇 Yes indeed I found that I was confusing two different things. In the end, I gave up UIBuilder and did my Property Drawer only by script
I am playing around with ways to upgrade components when I make breaking changes.
Here's the code I have right now
[CustomPropertyDrawer(typeof(ModelV1))]
public class UpgradeTime : PropertyDrawer
{
public override VisualElement CreatePropertyGUI(SerializedProperty property)
{
var button = new Button();
button.text = "Upgrade me!";
button.clicked += () =>
{
property.managedReferenceValue = (property.managedReferenceValue as ModelBase).Upgrade();
property.serializedObject.ApplyModifiedProperties();
};
return button;
}
}
[CustomPropertyDrawer(typeof(ModelV2))]
public class Property : PropertyDrawer
{
public override VisualElement CreatePropertyGUI(SerializedProperty property)
{
return new Label("I am the latest version! How cool!");
}
}
It's very rudimentary, of course, but it does work -- with one issue.
The inspector doesn't update immediately, so you still see the property drawer for V1. Can I tell Unity that it needs to competely recreate the property drawer (or editor (or inspector window))?
ModelV1.Upgrade() returns a ModelV2
The field has [SerializeReference] on it, and it stores a ModelBase
(The actual details of the upgrade system aren't really relevant here)
Does forcing a redraw not work?
How would I do that?
this would be from inside of a property drawer, not an editor, which complicates things
Yeah that's true, but you still can with some magic tricks
Trying to find the right incantation for you
Huh, haven't seen this before but works a try
EditorUtility.SetDirty(EditorWindow.focusedWindow);
EditorWindow.focusedWindow.Repaint() could also work
Repaint doesn't do it, which makes some sense -- you're just asking it to re-draw the retained UI
Shame, I was hoping it would
i did check that focusedWindow is the inspector window
I guess your next option is to try to find the actual Editor that is drawing it
I guess I could have the property drawer destroy itself and clone in a new UI 🤔
that sounds scary
(well, not "itself" -- destroy the UI it created)
There is also an internal InspectorWindow that you might be able to force to recreate (maybe there's something on editorwindow too?)
var whoops = Selection.objects.ToArray();
var huh = Selection.activeObject;
Selection.objects = null;
Selection.activeObject = null;
EditorApplication.delayCall += () =>
{
Selection.objects = whoops;
Selection.activeObject = huh;
};
...I mean, it works...
lmao
This should be an infrequent operation
for some context...
I'm working on packages to be used in VRChat projects
I mean it's fine 😛 it's on manual button press right?
I know I'm going to be making breaking changes (let he who is without sin cast the first stone...), so I want to have a way to deal with them
There's an even larger problem that this doesn't address...
If a user overrides a property on a prefab instance, that override is going to get lost
I was considering suggesting to manually destroy the ui elements then asking unity for an instance of the property drawer and adding that as a child of your current instance
I think I'm going to deal with that by forbidding overrides, and instead having the user attach an extra "Override" component. It'll be a bit like the Volume framework
that way, there are zero prefab property overrides involved
My editor code will have to look for the "leaf" component -- either a Foo or a FooOverride with nothing else trying to override it
there could be several layers of overrides due to prefab variants and nested prefabs
and yeah, it's going to be an infrequent operation
yooo this works
lmao
var replacement = new Property().CreatePropertyGUI(property);
var parent = button.parent;
parent.Remove(button);
parent.Add(replacement);
i'll have to check if it actually binds anything correctly
Probably not like that
You can also try adding a new PropertyField instead of doing what you're doing there
That should fix the binding
It appears to be working. I create and bind PropertyField controls in Property.CreatePropertyGUI
(i am going to rename that class now)
Ah yeah, that should work then
I'll be loading a UXML document later on
in theory, I should be able to keep every old property drawer, and then just insert an "upgrade" button into anything that's out of date
or just put a frowny face if I did something so dramatic that migration isn't possible
):
i'm going to forbid the upgrade if you're looking at a prefab instance
This exactly matches what I did for a procedural generation system
I realized that overriding a list's elements goes haywire if you change the original prefab's list contents
you aren't adding stuff to the original prefab's list; you're just overriding individual elements
the solution was to add a new component for each "prefab layer"
oh no, i also have to do migrations on the override components 
the word "override" no longer looks real
Has anyone ever successfully managed to set a custom icon to a scriptable object through code?
Im trying to get it working but it seems that only when I select it once and reimport i can get the icon to update, but it should show it as soon as I open unity
you can trigger the reimport when you assign it in code
The problem is that the code of assigning it only gets called when I select the asset once. Plus, if i call reimport after assigning it, since it's selected it will reimport again and again, etc.
then trigger it differently
using UnityEngine;
using UnityEditor;
using System.Linq;
[CustomEditor(typeof(TextureAsset), true)]
[CanEditMultipleObjects]
public class TextureAssetEditor : UnityEditor.Editor
{
public override Texture2D RenderStaticPreview(string assetPath, Object[] subAssets, int width, int height)
{
TextureAsset example = (TextureAsset)target;
if(example == null)
return null;
var albedo = TextureDataExtensions.ExtractTextureWithType(example, TextureType.Albedo);
if(albedo == null)
return null;
Texture2D previewTexture = null;
int attempts = 0;
while (previewTexture == null && attempts <= 10)
{
previewTexture = AssetPreview.GetAssetPreview(albedo);
attempts++;
}
if(previewTexture == null)
return null;
Texture2D tex = new Texture2D (width, height);
EditorUtility.CopySerialized(previewTexture, tex);
return tex;
}
}
here's the code btw
im all ears
Hi everyone,
is there a straightforward way to override/modify the function that handles copying the previous element whenever an element is added to the list?
Specifically I have a List of the class below, but when I add another element to the list in the inspector both elements share the reference to the same ConfiguratuionCommand object for the behaviour field, which I dont want. If I reassign the behaviour field in the inspector it works great and both elements have a seperate ConfigurationCommand object.
I would love to make this happen automatically, so the new element immedieatly has a new object as well, or at least null.
Thanks!
Dont know if theres a better (or UITK) way, but ReorderableList lets you customize this kinda stuff
Which would require a custom propertydrawer for OptionReactive
Or a custom editor for its owner class
~~Hi, everyone. Is there an extension or any other way that I can change the color that unity gives to inactive prefab objects in the hierarchy? Active game objects and inactive children of prefabs are the same color, and it's really annoying. I checked in Preferences/Colors but there's no color options for the hierarchy unless I missed something. Thanks!
I've discovered prettyHierarchy, but I don't believe that's what I'm looking for. I want to change the color of the text itself. Annoyingly, objects that are not prefab children get a very obvious dark gray when they are inactive, but for some reason prefab children are set to the same color as regular active objects.~~
Nevermind, apparently this is a bug, since restarting unity changed inactive prefab children to dark blue as they should be.
Try #💻┃unity-talk
thanks
tldr; Editor's Inspector populates all my null array elements into object instances.
Hello, I might be posting in the wrong channel, but thought people with editor experience might know whats happening.
I have a simple array of (serializable, non MonoBehaviour) objects, which I populate with X null fields (think of an inventory system with empty slots).
When I select the inventory object in the editor while the game is running, unity populates all my null fields with instances of new objects. This ONLY happens when I run the game, and have the script selected/visible in the inspector window.
Can I stop the editor from filling my array with data that I didn't create myself? Is this a bug, or is this a unity feature persay?
I have a couple lists. Both are basic classes which use polymorphism. Am trying to make a property drawer for them, but it's been the bane of my existence. Nothing I try seems to work and both StackOverflow and GPT don't seem to help.
I have tried writing these in several differeny ways - serialize field, serialize reference, with or without auto-properties:
[Serializable]
public class GrowthStage
{
[SerializeReference] private List<ComponentData> componentData = new();
[SerializeReference] private List<GrowthCondition> conditions = new();
public List<ComponentData> ComponentData { get => componentData; private set => componentData = value; }
public List<GrowthCondition> Conditions { get => conditions; private set => conditions = value; }
}```
Basically, it looks like this when I try, or sometimes it'll just show the base element with no subfields or subproperties serialized.
I'm not so worried about being able to generated the dropdown using Reflection, so much as I am figuring out the proper syntax for actually drawing it:
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
this.property = property;
// Begin drawing the property
EditorGUI.BeginProperty(position, label, property);
DrawComponents();
DrawConditions();
// End drawing the property
EditorGUI.EndProperty();
}
private void DrawComponents()
{
componentDataList = property.FindPropertyRelative("componentData");
EditorGUILayout.LabelField("Components", EditorStyles.boldLabel);
//// Ensure that we draw each element in the ComponentData list
//for (int i = 0; i < componentDataList.arraySize; i++)
//{
// SerializedProperty componentElement = componentDataList.GetArrayElementAtIndex(i);
// EditorGUILayout.PropertyField(componentElement, new GUIContent("Component " + i));
//}
// You can optionally add an "Add" button here later
EditorGUILayout.BeginHorizontal();
string[] componentNames = componentTypes.Select(t => t.Name).ToArray();
componentSelectionIndex = EditorGUILayout.Popup("Component", componentSelectionIndex, componentNames);
if (GUILayout.Button("+"))
{
Type selectedType = componentTypes[componentSelectionIndex];
ComponentData newComponent = (ComponentData)Activator.CreateInstance(selectedType);
Debug.Log($"{selectedType.Name} added to stage.");
}
EditorGUILayout.EndHorizontal();
}
Basically, I want each stage to show a list of components, their drop down / button, then a list of conditions with dropdown / button. Such that the button adds to that stage's list.
anyone know if theres a simple call for drawing the transform gizmo?
i want to modify an array of vector 3 positions using the transform gizmo
Yes! Thank you brotha
Hello, I want to apply a CustomEditor to multiple classes. Ideally, I would have it appear for every class that implements an interface, but as far as I know that's not possible. I would be okay with the editor targeting a parent class, but I don't want others to accidentally use the parent class rather than one of its children. What should I do in this situation?
Make the parent class abstract?
ohh I completely forgot about the existence of abstract classes haha
are there any extensions that would let unity build connect to your steam account?
wdym
You use the steamworks sdk, there are a few c# wrappers for it
https://partner.steamgames.com/doc/sdk
https://github.com/rlabrecque/Steamworks.NET ⭐
Steamworks wrapper for Unity / C#. Contribute to rlabrecque/Steamworks.NET development by creating an account on GitHub.
this requires your game to be on steam though
No it only requires the build to be on steam if ichi.io will have it I can just make build without iz
er i dont understand but if you think its gonna work go ahead. If you want to simply do a steam login then thats different to this.
There is another web api for general steam user data querying: https://steamcommunity.com/dev
Don't trust the steam api docs though, it's lying, different data types, missing fields in both requests and responses
I'm trying to create an extension that visualizes the stencil buffer. To do this, I need to draw a mesh in front of the scene view camera.
I'm currently using Graphics.RenderMesh. It looks like it winds up stacking all of the meshes up until something makes it "refresh" -- like clicking on the scene view.
This is not a hall-of-mirrors effect; there are many spheres being rendered all at once!
How should I draw exactly one mesh in front of the scene camera?
(this is for the BiRP)
and I am currently drawing in response to EditorApplication.update
I get the same results by responding to Camera.onPreCull
Graphics.DrawMeshNow appears to do nothing.
I guess I can just put an object with a MeshRenderer in the scene, but it'd be nice to avoid that
Ah. It looks like I needed to set the camera that the mesh should render in
RenderParams rp = new RenderParams(material);
Matrix4x4 mat =
Matrix4x4.TRS(camera.transform.position + camera.transform.forward * 25f,
camera.transform.rotation, camera.transform.lossyScale);
rp.camera = camera;
Graphics.RenderMesh(rp, mesh, 0, mat);
Ooooh, I get it
They were all stacking up on the main camera in my scene
I guess the "render mesh" command only clears once every camera gets a chance to draw it
This call creates internal resources while the Mesh is in the render queue. The allocation happens immediately and exists until the end of frame if the object is in the render queue for all cameras. Otherwise, the allocation exists until the specified Camera finishes rendering.
yeag
I"m making a custom build window is it possible to show the currently connected device like it is shown in the actuall build menu( oppened by ctrl shift tab)
you mean like an android device? You can use adb devices for that.
I'd check the reference source, there's probably some API that exists
I mean the run device option from the build settings
but what is "device"
the device to run the build on depending on the target platform
Yea for other platforms I have no idea. I suspect most wont be exposed to c# and api documentation for closed platforms isnt public 🤷♂️
Hmmm the implementation leads to some internal stuff. Or I am not finding it
Is this the intended output ?
public class Spell : ScriptableObject{}
In the custom PropertyDrawer of another class
var spellSelect = new ObjectField
{
objectType = typeof(Spell),
allowSceneObjects = false
};
The object field let me select anything, both scene wise and asset wise 🤔
Are you sure that's the component being rendered?
Yes of course, I don't have any other Object field on this property drawer.
* Looks below *
//root.Add(spellSelect);
root.Add(new ObjectField());
Mb, feel dumb 😂
Haha, happens
How do I fix this overlapping?
I'm using:
TreeView treeView = new()
{
makeItem = static () =>
{
VisualElement slot = new();
ObjectField field = new("Game Object");
field.objectType = typeof(GameObject);
field.SetEnabled(false);
slot.Add(field);
IMGUIContainer container = new();
container.onGUIHandler = () => ((Editor)container.userData).OnInspectorGUI();
slot.Add(container);
return slot;
},
virtualizationMethod = CollectionVirtualizationMethod.DynamicHeight,
// ...
};
How much are you guys willing to pay for a addon that lets you easily bake texture in blender and map those texture automatically in unity for any material?
I find no usage for such addon.
You use blender?
Not directly, but I work with artist that does and I never seen them complain that issue.
Well u see baking texture in blender and importing them to unity is easy (depends) but very redundant
And not to mention unity doesn't automatically map metallic map to materials
If you had experience with blender and imported assets to unity from blender then you would understand the issue I am talking about
It's very redundant and it's very easy to make mistakes when baking texture
i want to make drawer or defaut reference setter like this for script that are not part of mono script
Use ScriptableObject or EditorWindow
any example?
You set the variable you want there, and whenever a script is created (not sure how you detect), you use those variables.
thanks
I am creating an Overlay. This is not a Unity Object, so I can't use SerializedObject/SerializedProperty to bind its fields to my UI.
Should I just create a new ScriptableObject type that'll hold all of the data, and create an instance of that when the Overlay is created?
(and then bind the UI to it)
oh, I should just use a ScriptableSingleton! That'll let its state survive assembly reloads
I ran into a very annoying issue while working on the same overlay
On first import, the overlay can get created before non-code assets finish importing
which made several things break
Is there a good way to deal with that beyond trying over and over until the assets are present? I don't want to have to guard every single place that needs to use AssetDatabase.LoadAssetAtPath
Are you talking about for loading UI assets?
That sounds vaguely familiar, let me take a look and see if it is and what I did if so
I'm surprised I haven't run into this before while working on a pretty complicated editor window
Yuup I did have to deal with this. In CreatePanelContent I have it try to load the uxml file, and if it fails, it adds a callback to EditorApplication.delayCall which tries again, repeat until it works.
So it's specifically an issue you've had with Overlays
I was beginning to worry I'd need to do this everywhere I loaded a UXML file
Yeah it is specifically with overlays
it seems like overlays get created sooner
(soon enough that throwing an exception completely explodes my scene view)
oops
actually, that might have been a rendering error
The other half of this issue caused me to try to create Materials out of shaders that hadn't imported yet
and then draw those all over the scene view
It is because the scripts compile before the assets import. And the overlays are created via reflection by finding all the types on domain reload.
Is there a quick way to un-collapse all of the children of an object in the Hierarchy?
Alt-click the arrow
thanks!
Not sure where to post this, I feel people might have a hint here :
My editor hangs regularly when I select things in the Inspector (quite at random). Tried disabling stuff, don't know what would make a search something freeze like this.
Hi ! I'm using the SearchWindow api (https://docs.unity3d.com/6000.0/Documentation/ScriptReference/Experimental.GraphView.SearchWindow.html) and I can't figure if it is possible to open the window at a desired position in the search tree.
using UnityEngine;
using UnityEditor;
using UnityEngine.UIElements;
namespace PrimePixel.EZVN.VisualScripting
{
[CustomEditor(typeof(Dialogue))]
public class DialogueProperties : UnityEditor.Editor
{
const string ASSET_PATH = "Assets/Editor/VisualScriptEditor/Documents/Functional/DialogueProperties.uxml";
#region Properties
private Dialogue dialogue;
private VisualTreeAsset rootAsset;
private VisualElement root;
#endregion
void OnEnable()
{
dialogue = target as Dialogue;
GetElements();
ConnectElements();
}
public override VisualElement CreateInspectorGUI()
{
root = new VisualElement();
rootAsset = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(ASSET_PATH);
if (rootAsset != null)
{
rootAsset.CloneTree(root);
ConnectElements();
}
else
{
Debug.LogError("Visual Tree Asset not found at: " + ASSET_PATH);
}
return root;
}
private void GetElements()
{
// Implement logic to get necessary elements if needed
}
private void ConnectElements()
{
// Implement logic to connect UI elements with the script properties
}
}
}
Can anyone spot where I'm going wrong with this? It's still drawing the default inspector
It's driving me mad... and I want to get to bed!
Try re-starting Unity
I'm using an internal method to add MenuItems, everything works except the shortcuts. They get displayed correctly but nothing happens when you press them. Anybody got an idea on why that is?
Would there be a way to implement my own hotkey system? I can't seem to find a way to listen to key inputs in the editor.
You'd use the Shortcut attribute
unfortunately the MenuItems are generated dynamically
I imagine ShortcutManager allows you to register your own stuff
having an issue with this GUI breadcrumb drilldown button. Nothing I do is changing the hover cursor when theuser hovers over one of the buttons in the top left.
code:
does the editor window have any connection to the scene at all?
like can I see if I'm in a prefab context or not?
sick, thank you 😁 I'm looking to write a moveset editor and I'm looking to make it only work within a prefab context so I can grab the root object and augment it a bit. this is what I needed
I originally had it as a script to attach to the character, but I want to avoid that annoying stuff when I export so I'm going to change it to it's an editor window
is it annoying to make a good layout in an editor window? is there a lot I have to learn or
Depends on what you are used to, I would look at UIToolkit and the UIBuilder, makes it drag and drop to create the layout.
I'll have a look at that then, thank you 😸 does that have a way to make a timeline? essentially all I want is like a timeline for an animation, and a couple of fields that reference existing objects to be modified.
No Unity doesn't have any built in support for timeline type controls.
a slider is fine
if they have that?
okay, I'll have a look at those then, thank you! to confirm, this is for an editor window and not actually for the game right? I've heard about UI toolkit for in game stuff, or something similarly named
UIToolkit can be used for the editor or game stuff. If you are using anything newer than like 2022.1 then the inspector is using UIToolkit, as well as the scene view window.
I see. well drag and drop will Def save me a lot of time 😁 I assume it works similarly to IMGUI stuff where there's like a c# script actually making it interactive and stuff?
In a way yeah, it is retained mode, so it is all based around events, but yeah you have to do interactivity in C#. But you can do basic data binding in the uxml/UIBuilder
can I easily make a field for a scriptable object that I've made, for example? where it displays all the properties that I can modify as if it was in the inspector?
Yes, but I think you have to add the field via c#
It would be the InspectorElement element (maybe it is called EditorElement I don't remember which)
It is what the inspector actually uses to show the properties, including custom editors
okay awesome, I'll have a read of this when I'm back on my computer in a week. do you have any resources for getting started with stuff like this?
The Unity docs/manual for Editor is good, and Unity Learn has some guides on creating editor extensions using UIElements/UIToolkit. Don't have links on me, but should be really easy to find on google
awesome, thank you for your time ☺️ I have a direction to get started now
Is there any way I can make a selectable gizmos? I am making a nodemap class and I want to be able to select each individual node in the scene without changing the selected gameObject. I'll explain in detail what I want to do.
I want to create a node map game object. Each node is its own serializable class, and when the nodemap's game object is selected, all its nodes and connections are drawn on gizmos as a sphere of an arbitrary color, I put green because why not. What I want is for me to be able to click a sphere in that object, have the object not be deselected, and perform an action on the node that sphere belongs to. Like somehow getting the node from the sphere and performing an action with it
using UnityEngine;
using System.Collections.Generic;
[System.Serializable]
public class Node
{
public Vector3 position;
public List<Node> connectedNodes = new List<Node>();
public Node(Vector3 pos)
{
position = pos;
}
} ```
This is the node class and this
```cs
public class NodeMap : MonoBehaviour
{
public List<Node> nodes = new List<Node>();
[Header("Editor Tools")]
public Node selectedNode = null;
public Node AddNode(Vector3 position)
{
Node newNode = new Node(position);
nodes.Add(newNode);
return newNode;
}
public void AddNodeFromSelected()
{
Vector3 pos = selectedNode != null ? selectedNode.position : transform.position;
AddNode(pos);
}
public void DisconnectNodes(Node a, Node b)
{
if (a != null && b != null)
{
a.Disconnect(b);
}
}
public void RemoveNode(Node node)
{
if (node != null && nodes.Contains(node))
{
node.Isolate(true);
nodes.Remove(node);
}
}
}```
Is the NodeMap class. what I basically want is for the selectedNode to become the clicked node when what I said in the message above happens, and to become null again when clicked off (but still in the scene, not somewhere else in another window). How could I do that?
What you probably want is a EditorToolContext. It basically lets you go in to a special mode where you can change how the default tools work and how selection works. It is what Unity's Spline package uses to let you edit splines.
I'm trying something with a Handles Button, but something makes it turn into a transparentish beige color, why is that?
private void OnSceneGUI()
{
NodeMap nodeMap = (NodeMap)target;
Handles.color = nodeMap.gizmoColor;
if (Handles.Button(nodeMap.transform.position, Quaternion.identity, 0.5f, 0.5f, Handles.SphereHandleCap))
{
PerformAction();
}
}```
This is how it's supposed to be like, a green color
This is what it turns into
Can editor windows draw gizmos to the scene?
how do I wait for layout computation to finish in edit mode in editor? I want to make a bunch of changes to scene in editor script and use layouts to properly align everything but layout computations are expensive and the layout is static so I want to disable all layout components after it laid out all elements correctly but I don't know how to wait for it
Yes
subscribe to the OnSceneGUI event and draw your handles in there
void OnEnable () { SceneView.duringSceneGui+= this.OnSceneGUI; }
void OnDisable () { SceneView.duringSceneGui -= this.OnSceneGUI; }
void OnSceneGUI ( SceneView sceneView )
{
Handles.BeginGUI();
// GUI Code here
Handles.EndGUI();
}
awesome, appreciate you 😁
do I have to use the handles API or will gizmos work too?
but you can't use Gizmos.drawSphere for example. you'll need to use the Handles