#↕️┃editor-extensions
1 messages · Page 109 of 1
It must be possible, cause the debug mode does it succesfully
Going to be needing to see the code
Uhh yeah... Currently it is not public so let me get some of the relevant stuff
You can look in #854851968446365696 for sites where you can put temporary bits of longer code
Ohh right forgot about gist sites
The important part is the end of the GuidReferenceDrawer
DoBasicPreview
Still reading, but letting you know that EditorGUI.showMixedValue can be set. No need to mess with GUIContent
Er, I guess for the button you do
Where and what is the problem? I don't see where your original problem was
well in the picture you can see that i have multiple objects selected
and in my custom editor the scene indicator does not show the "mixed values" while in the debug inspector it does show it
Is the 'issue' that EditorGUI.showMixedValue is false?
yeah.
That is because you haven't set it to be so
and the prop.hasMultipleDifferentValues is false as weel
Where
Any luck?
I did try to find the code that unity uses for the debug drawing but Rider's limited assembly exploring made it really hard
Not sure and not at a place where I can do testing on my own. I would try creating a minimal reproducible example. A simple class/struct with like a single float field or something. Make a drawer for that and see if the hasMultipleDifVal is true or false
Found the issue
Wasn't using the begin check changed
So it was writing the scene to both but not saving it somehow.
Also this was adapted from official unity code sooo I blame them XD.. (It is an adaption of what they did for GUID based references, for cross scene stuff)
@visual stag how would I do the thing you said to do?
If you use SerializedProperty, and PropertyFields then when you draw a field it will draw it like it would normally without you having to specify any specific UI
https://help.vertx.xyz/programming/editor-issues/serialisation/serializedobject-how-to
The "SerializedObject in Editors" section is how I would usually go about drawing fields in most circumstances
Only when I don't have a serialized value or I want to customise how it looks would I not use a PropertyField
I put the tag on the event but it didnt show in the inspector? And I did compile and there is no errors
huh? Tag?
[SerializedField]
So you don't have a custom editor or property drawer, you're just trying to get it to draw?
I do have a custome editor
then how are you drawing it there
why would it if you're not telling it to draw
OHHHH
oh wait
I thought you meant that if I just put that tag, then it will show just like how floats and text fields do
@visual stag so when I use EditorGUILayout.PropertyField() and I put the event in the input, it give my an error:
The event 'event' can only appear on the left hand side of += or -=
How do I convert an event to a serializedproperty?
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
var button = (SMButton)target;
EditorGUILayout.PropertyField(button.OnClick);
}
}
This is not easy to explain. You have to use the serialized object to find the relevant serialized property, and then draw it with the PropertyField.
My link explains how to do that with an example structure.
oh i think I get it. I have seen that concept before. Ill try that out
https://help.vertx.xyz/programming/editor-issues/serialisation/serializedobject-how-to#serializedobject-in-editors being the relevant part just to handle the simple case of drawing a field or two
So I added this but its giving me a nullref error:
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
var button = (SMButton)target;
var onClick = serializedObject.FindProperty("OnClick");
EditorGUILayout.PropertyField(onClick);
}
}
if it's not being drawn already with base.OnInspectorGUI(); then it doesn't sound like it's serialized
This is what I am referencing in my script that the editor is editing:
[SerializeField] public event System.Action OnClick;
uh
they how do they do it and what a UnityEvent?
is that like a wrapper?
A UnityEvent is what you were talking about earlier, the OnClick used by Button or other events you configure via the inspector
oh I thought OnClick was an event
so I assume by the name, that UnityEvents are events with other stuff?
They are Unity's serializable event
it behaves similarly to C# events but you can assign them in the inspector and they have a very slight overhead
So should I swap mine out for something like this?
[SerializeField] public UnityEvent OnClick;
also, [SerializeField] is redundant on public fields. If it's public, Unity will try to serialize it
Oh ok, wow everything is clicking in my head now, thanks as always!
When I call the event, can I just call is like this:
OnClick();
or do I still need to do it like this:
OnClick?.Invoke();
UnityEvents only support Invoke
i see thanks
degree = GetAngleInDeg(0, 0, cube.transform.position.z, cube.transform.position.y);
Handles.Label(Vector3.zero - (3 * Vector3.one), "angle : " + degree);
Handles.color = Color.red;
var center = Vector3.zero;
var start = Vector3.forward;
var normal = Vector3.down;
var radius = 1;
var angle = degree;
Handles.DrawWireArc(center, normal, start, angle, radius, 1);
Handles.DrawLine(Vector3.zero, 3* Vector3.forward);
``` i am trying to make arc , but i don't able to understand normal parameter , the arc is drawing in xz axis not in yz axis
okay fixed
my arc should move in -1 that is anti clock
how can i rotate the handle label
Hi, I am trying to import a new asset package from quixel megascans that I just downloaded but I am getting this error:
Hi!
So i'm having a small problem when trying to make a custom object picker. The goal is to be able to pick an object inside the scene view.
The default object picker communicates the chosen object back by sending an event to that window. This is something i would like to do as well..... but not sure how to get the window from a property drawer.
The thing is complicated by the fact that I serialize a GUID so i need to make sure that my property drawer does the actual assigning of the property
Shouldn't the normal in
Handles.DrawWireArc(center, normal, start, angle, radius, 1);
be cross product of the two vertor forming the angle ?
Hi,
I'm working on a EditorWindow where I want to set shared project settings. These project settings are stored in a ScriptableObject. The asset of this ScribtableObject is stored in Assets/Editor/ProjectEditorStorage.asset
This DevTool also needs to reference GameObjects in a scene.
Within a session, saving and loading works fine. But after closing Unity and starting it again, the references to the GameObjects are all wrong. Does someone know how to do it the right way?
public class DevTools : EditorWindow
{
public ProjectEditorStorage projectEditorStorage;
[SerializeField] private GameObject go1;
[SerializeField] private GameObject go2;
protected void OnEnable()
{
var devToolsProperties = projectEditorStorage.devToolsProperties;
JsonUtility.FromJsonOverwrite(devToolsProperties != null ? devToolsProperties : JsonUtility.ToJson(this, false), this);
}
protected void OnDisable()
{
projectEditorStorage.devToolsProperties = JsonUtility.ToJson(this, false);
EditorUtility.SetDirty(projectEditorStorage);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
private void OnGUI()
{
projectEditorStorage = (ProjectEditorStorage)EditorGUILayout.ObjectField("Project Editor Storage", projectEditorStorage, typeof(ProjectEditorStorage), true);
go1 = (GameObject)EditorGUILayout.ObjectField("GO 1", go1, typeof(GameObject), true);
go2 = (GameObject)EditorGUILayout.ObjectField("GO 2", go2, typeof(GameObject), true);
if (GUILayout.Button("Load Dev Tool Settings")) OnEnable();
if (GUILayout.Button("Save Dev Tool Settings")) OnDisable();
}
}
the session id's of the gameobject will be different. that's why it's failing. also: you should NEVER call any unity magic methods like Start, OnEnable, OnDisable, etc...... manually
How are the references within the scene are managed then? How do they keep consistent then? Are they using different ids? Didn't know the handling would be different. Regarding the Unity methods, I'm not doing that in the actual script, I just tried to simplify it as much as possible for this question and thought I could get away with it 🙂
maybe this helps: https://www.gamedeveloper.com/programming/building-a-simple-system-for-persistence-with-unity
Okay, well I get what this is doing, but I don't understand why this 'workaround' is needed. I'm scratching my head here... I mean, unity itself somehow needs to keep his GameObject-relations persistent between sessions. How do they do it? And why shouldn't I be able do reuse their handling?
Sorry if I'm missing the obvious here...
And thanks for trying to help me!
no , i am asking how can i rotate the handle label
like changing the text orientation
Righto, so for project settings I recommend using ScriptableSingleton, that way it is stored outside of the assets folder and makes things a lot cleaner
https://docs.unity3d.com/ScriptReference/ScriptableSingleton_1.html
As for referencing scene GameObjects, you can use GlobalObjectId to store references to them.
https://docs.unity3d.com/ScriptReference/GlobalObjectId.html
#🎥┃cinemachine would be the right channel for this question 🙂
guys onSceneGui get trigger when i move and hover my mouse on it , how can i make it trigger with script
Repaint the scene view window
how
thanks
i added SceneView.repaint() in onsceneGui method
is it good ?
Hi,
I have a question about why my object field is not staying set when I press the play button and I would love some help please thanks!
Here is editor
[CustomEditor(typeof(SMUI))]
public class SMUIEditor : Editor
{
public SMUI ui;
public override void OnInspectorGUI()
{
ui = (SMUI)target;
SMUI parent = (SMUI)EditorGUILayout.ObjectField("Parent", ui.Parent, typeof(SMUI));
if(parent != ui.Parent)
{
ui.Parent = parent; // THIS IS WHAT I AM SETTING BUT AFTER PLAY IT IS SET TO NULL
}
SerializedProperty children = serializedObject.FindProperty("children");
EditorGUILayout.PropertyField(children);
}
}
And this is what the .Parent property is doing since that is a property:
public SMUI Parent
{
get
{
return parent;
}
set
{
if(parent != null)
{
parent.RemoveChild(this);
}
parent = value; /// HERE IS WHERE THE VALUE ACTUALLY GETS SET
if(value != null)
{
parent.AddChild(this);
}
}
}
So just to reiterate: The value "parent" gets set from the property "Parent" when I add an object to the objectfield in the inspector. But when I press play the "parent" goes to null with no errors in console
got it
there is update and applied modify function for serialized property
Sorry for the late answer. Thanks for the response. That looks interesting. I'll try that. However, I see this could get pretty complicated to apply this for a List of UnityEvents, if that's even possible.
#archived-code-general would be the right channel for this.
This channel is discussion around creating your own editor extensions 🙂
ok thank you very much 🙂
(You can simply copy the message and paste it in #archived-code-general and then delete the one here as there is a rule against posting the same thing in multiple channels)
there you go 🙂 thanks for the help!
guys my gameobject reference get lost when i reselect the gameobject
Is there a way to get multi object editing to work with custom property attribute drawers?
As soon as i select multiple objects with the same script, the property with a custom drawer gets set to the same value on all selected objects
Ah. I didn't realize what might have meant by 'extensions' until just now...
So is this for writing custom extensions specifically, or in writingyour code to extend unity editor functions for developing your game?
this channel is for anything that extends the default functionality of Unity, doesn't matter what
The default functionality of the Unity editor
Thanks @visual stag I should have probably come here from the beginning <_>
rebuilt a jam game in unity. very hierarchy/class based. I wrote a level saver/loader that works fine... but only now discovering that I have to do a huge amount of work in order to leverage the unity editor to actually load that content out-of-game-play.
For the moment, a basic q - does the Singleton pattern work well with the Unity Editor? I occasionally find the
static Instance" reference on it empty...
It can, but you need to have a good understanding of script lifecycles in the editor
I used to be the same way, I've slowly adapted my development style to make it much more unity friendly
it has made life much easier
while not sacrificing everything to the monobehaviour gods
LOL
That's what I'm trying to do right now, before I attempt anything larger. A game I easily made in a weekend seemed like a good start >_>
I'll have to look into script lifecycles then. and work on more of the level data - the actors themselves hold references to gameobjects and other scripts, the level data has dictionaries... I'm not sure how I can reliably compensate for these traits.
any suggestions?
(dictionaries aren't the real headache. it seems references are?)
@crude forge hold references as in assets? or scene objects?
You can serialize dictionaries if you create a custom class that implements ISerializationCallbackReceiver
yeh. There's a few ways I can do dictionaries.
Good q. I do some asset caching, but in this case it's scene objects and scripts.
wait so what exactly are you trying to do with the editor if everything's already in-scene
I'm loading the data in and out through jsons. So the scenes are empty until the levels are loaded.
For the moment, I'm digging up more on script lifecycles.
Right now, in the Unity Editor I'm finding references between objects 'disappearing', becoming null when they weren't before.
This happens when I'm trying to load in new objects via code. Adjusting the 'level loader' to work in Unity Editor and not just the game.
you may be running into serialization issues, where you're not marking objects dirty so that changes get flushed properly
I've never run into that happening in the scene, but the symptoms sound familiar
Interesting. Okay, that's very helpful. Been banging on this for a while blind, but I'll look into that.
So marking objects as dirty is important as well?
it is
but I've never had to do that for scene objects..
just for scene saving purposes
when do these things become null?
after a script reload?
I'm having a hard time telling, since it doesn't happen every time. Sometimes on refresh I -think-, but there may be something else. It doesn't happen every time.
yeah that sounds like serialization sync problems
In terms of the scenes, was avoiding doing a level-per-scene (this is a puzzle game, it could have a lot of levels), so I just have a primary scene that I'm using to load in the level data.
sounds familiar 😄
rofl
protobuf? interesting
yeah don't go down that rabbit hole if you don't have to lol
don't get me wrong, protobuf is great
right now I convert the level to a 'levelsaveddata' class that properly serializes and is saved as a json file, and then I use a 'levelloaddata' class for reversing it
but you'll be integrating your own unity-inside-unity if you go too deep down that path lol
I save levels as scriptableobjects now
I heard about SOs, don't know much about them...
right now the levels serialize via that pipeline
I seem to recall SOs were really useful for classes with lots of variants?
so I never investigated them for this - I just don't have a lot of actual elements
they're useful in many situations
this is what I have now -- Asset refers to the scriptableobject asset that is basically the same thing as your json file
when it has an asset, it will serialize to that asset directly from the scene
That's almost exactly what I'm trying to figure out what to do 😉
the level functionally exists within the scene
Basically working on trying to get levels to load, then save.
ooh! that looks so nice!
thanks
what I was trying to do before was to make the saved level data the single source of truth about the level
but this created complications wrt architecture, because now unity objects were subservient to my own data structures
meant I was grinding against unity the whole way
what I did is to invert the single source of truth so that now levels exist as-is in the scene, and I just have a way to convert that scene level into an SO
Makes sense. and you save the SO?
(so the SO is used as the saving object, but not holding the scene functionality itself?)
I think I essentially did that with the levelsavedata and levelloaddata classes
I've been developing this "engine" for years as a hobby
I don't claim to be an expert but tbh it's pretty mature lol
I had been doing something like that in raw JS, but it got to the point when I wanted to migrate out of it. This is my first attempt to change one of my JS games over to Unity
fun
It's gone well until I started to try and really leverage the Unity Editor itself
takes a bit to wrap your mind around it
then it just went batnuts crazy
Yeah
I'm trying to re-engineer some of the code now too that I understand more - like that Prefabs can contain multiple gameobjects
basically, what I have in my SO is a list of "object descriptions" with a serialized dictionary of properties on them. Every serialized game object then has this pair of methods on it
so there's a bit of manual work for whatever data you want to save but it adheres to the KISS principle lol
I also have this interface SerializedComponent so that I can serialize properties for sub-components of the primary object
I like how clean that is
hopefully something here will give you a stroke of inspiration 😄
some!
one thing I discovered is I tend to keep a lot of references to other scripts on the same gameobject. I probably felt that was faster than doing GetComponent all the time
there's nothing wrong with that
those aren't going to cause a serialization sync issue?
I'll have to dig more into that
I created a struct for serializing references to other entities
this is used to track copies of entities across history states, but they can also be used to restore cross-object references
you are tracking entities across history states?
yes, for undo
you can deserialize cross-references a couple of ways
you can either do a two-phase system in which you load everything first, and then run through all of the objects and restore any references
this is simpler to implement and I recommend it, personally
the other thing you can do is have a dynamic resolver that, if the object you want hasn't been loaded yet, registers the reference with some central controller
then, when the object finally gets loaded, it runs through all the unresolved references and restores them
I did this using delegates
that's an incredible effort. I haven't touched delegates at all, but I might peek into it. I have an actorsavedata/actorloaddata class for all the actor types - the general refs are automatically generated (its obvious what it's pointing to), and the others are saved by id.
but ordering has been a pain there, I might not mind canning the two-phase approach. (I had to do it by saving all the actors in the puzzle grid to a list, and then later linking all the tiles to the actors and vice versa after the actors were loaded)
references to and from grids and tiles and the actors is probably the ugliest part of this to fix
dynamic reference restoration is uglier imo
Elegant solutions, especially ones transferrable to other projects, are absolutely interesting
two phase is pretty straightforward if implemented well
oh yeah. I haven't had to do that yet.
nothing selects targets or that type of behavior, yet
gameObjects have their own entityId string? huh
guess I didn't need to make that myself
Ahh
Is it possible to see the source of some of Unity custom inspectors? For example I wanted to check out "UnityEditor.Rendering.Universal.ShaderGUI.LitShader" to learn how they did some things
I'm looking through the c# source that's pinned hopefully I can find it, if someone has a link let me know please
The URP source is in the URP package, which would be in your project
Thank you
Hey guys, how can i create an editor for a class like this
thanks <3
np
Am I allowed to use GameObject methods in editor extensions, like GameObject.Find()
I’m pretty sure you’re but note that Find will found only objects on active scenes, not from project window
You can, yes
Hey, Can anyone help me. I am setting a sprite object field using a custom editor but the fields reset to null when I press play. "Up" and "Down" are the focus here:
[CustomEditor(typeof(SMUIButton))]
public class SMUIButtonEditor : SMUIEditor
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
var ui = (SMUIButton)this.ui;
//FOCUS ON AFTER THIS POINT SINCE ABOVE ISN'T WHERE THE PROBLEM IS EVEN THOUGH IT MIGHT LOOK WEIRD THAT I AM SAYING this.ui
Sprite up = (Sprite)EditorGUILayout.ObjectField("Up", ui.Up, typeof(Sprite));
if (up != ui.Up)
{
ui.Up = up;
}
Sprite down = (Sprite)EditorGUILayout.ObjectField("Down", ui.Down, typeof(Sprite));
if (down != ui.Down)
{
ui.Down = down;
}
EditorUtility.SetDirty(ui); //I AM SETTING IT DIRTY BECAUSE I THOUGHT THAT WOULD FIX IT. TURNS OUT IT ISN'T DOING ANYTHING NOTICABLE WHEN ITS HERE OR NOT
}
}
When working with custom editors, it is highly recommended to use SerializedProperty to get and set values instead of doing it directly so you get undo/redo support, values save when changed, and so fields support prefab variants. More info about them can be found in the pinned messages.
yeah but I need to do it this way so that I can update other things. As you can see by the ui.Up and ui.Down, those are properties not variables
the setters are doing things aswell behind the scenes
so any suggestions on how I might keep it from changing to null on play?
Are you perhaps setting the value in OnEnable/Awake/Start?
I thought about that but no. I actually thought that maybe unity was doing something like that behind the scenes but I thought that would be outragous
I am only setting the values in this spot
How do I add a button that executes a function when I click it?
ok I got it
Hello there! I want to make a custom float range attribute so that when i change the value of it from the inspector the slider increments by 0.25 or 0.5 for example instead of 0.01. I have very little knowledge of editor scripting. Does anyone know how i could approach this?
not in editor script, not bug free, but here is an approach.
thnx i ll give it a try and see how it works and maybe then i ll try to make it into an extension for the Range attribute
It seems to work nicely thank you very much
by some chance, does anyone happen to know, how I could make a simple visual scripting graph
like shader graph
thanks
There's also a video pinned about it
hi hmm anyone know, how in PropertyDrawer to get a values from List, example for int i can do property.FindPropertyRelative("MagicNumber").intValue;
if i try property.FindPropertyRelative("MagicList"). there is no ListValue, there is only objectReferenceValue i tryed to cast that to List but it did not work 😦
property.FindPropertyRelative("MagicList").GetArrayElementAtIndex(index)
Hello gamers, I have been trying to get an array to appear in a custom inspector, however I just can not seem to understand any of the tips/tutorials online, can someone please help me?
I think I hit the limit of my ability to code around this. Looks like I'm going to have to either start from scratch or learn a lot quick.
lots of objects that 'disappear' during the process of a script loading in data. I'm assuming all new objects have to be marked 'dirty'?
Do I do this as soon as the object is created? what about any subsequent changes?
(since I'm loading in data and writing a lot of properties, that implies a whole lot of repeated 'marks')
So, i want a class that always stores reference to its owner, which always inherits a specific interface
[System.Serializable]
public class Synced<T>
{
public ISyncInterface owner;
}
public class MyClass : Monobehaviour, ISyncInterface
{
Synced<int> integer;
}```and i *think* i could use property drawers to assign this variable for me without needing to pass `this` in the constructor, is this feasible, and/or is this taboo
Is Synced<T> a serializable class in this scenario?
It's feasible but not really recommended as there's no guarantee that it's been serialized
is there a specific scenario when it would not be serialized, or is that just a general, sometimes it might not be
Every script containing a Synced variable would need to be viewed in the inspector at least once for your PropertyDrawer to run and assign the owner. This means scripts added at runtime with AddComponent will not have owners assigned.
And any other scenario where a script might be added without immediately being viewed in the inspector
ISyncInterface would have other problems with being added at runtime, so that atleast is not a concern
@dense arch a property drawer is not how to go about this
you could do this with an editor script that loads on startup and collects all applicable classes
with reflection
but I would question the architecture here
So, realistically what i want is an easy way to tell variables to use a custom getter/setter, that calls a function from ISyncInterface
so the behavior im replicating is
public class MyClass : Monobehaviour, ISyncInterface
{
private int _x;
public int x
{
get => _x;
set
{
SyncSetValue(value);
_x = value;
}
}
}```but if i have a half dozen or more variables with this same set up, it becomes tedious to copy paste and rename to implement this same thing
so i could instead move this to a custom class, `Synced<T>`, and put this there, and store reference to the interface
but the `this` keyword is not accessible outside of function calls, and i want to serialize the object, so i need to have that set, or else in OnEnable assign the variable
might be a good use case for IL weaving lol
but that might be overkill
this is basically exactly what Unity did for its syncvars for their networking implementation
is it possible for you to create an abstract base class for ISyncInterface
side note, unity can't serialize raw generics so you'll still need to create definite classes for whatever value T you care about
can't it serialize the variable when i do Synced<int>?
no
when I was faced with a similar issue wrt serialization I tried to automate a bunch of stuff and eventually just landed on biting the bullet and making explicitly defined serialization functions. Yah it's a pain in the moment, but you make up for it with clarity and simplicity
you could write a snippet for vs to make it less painful
would probably be less work than automating it 😄
(or since 2019, in fact)
yes, I know about SerializeReference
🤨
Yeah don't even need SerializeReference for generics
In fact SerializeReference does not
https://docs.unity3d.com/ScriptReference/SerializeReference.html
The field type cannot be a specific specialization of a generic type(inflated type).
It's available in 2020.3 LTS
No more inheriting UnityEvent<T>, you can serialize it directly now
yah I use 2019 LTS
well thanks for learning me that info, that's an awesome addition to unity's scripting
I know that [Header("")] is a thing but is there an attribute like header that allows you to group variables like this
There is not, but there are several repos on github that add attributes like that
there's also the odin inspector, which has everything under the sun
Will check it out
or just switch to ui elements. highly recommend
That won't fix their issue 😛
(but I do agree UITK is great)
you can mock this up in literal seconds with UITK
Right, but they were asking about attributes
well.....they were asking how to group such values together
Does anyone know how to make a custom list without the add button? Or even override the default functionality of the add button?
think you need a custom inspector for that
my information on this may be out of date, but what you used to need to do was create a subclass of ReorderableList
perff
Yeah right now im making a custom inspector that has a button that adds items to that list from a filtered searchwindow
and I dont want to allow adding items normally anymore
but I cant find anywhere how to change that specific button
Yeah you use the UnityEditorInternal.ReorderableList to draw the list, it has a bool property for the add button (and or constructor param, I can't remember)
I'll look into it ty... although I couldn't find anything about it in the documentation so far 😦
Mad >> have you loaded in data (such as from a serialized file) into the editor before? Do you generally mark each object as dirty after filling it with data? Or after each data item is entered? // I also need to take a look at your reference-serializing code for my Master Singleton. It's self-referenced instance keeps on dropping :/
(hopefully I will get a chance to do the latter tonight -_-
ah thank you it is UnityEditorInternal, not UnityEditor.Experimental
@sweet compass like I said it's undocumented
welcome to editor scripting
you build your own map
pain
here's a simple one
started editor scripting 2 days ago thinking I'll just get it over with quickly to add a few required features but nah this shit is painful af lmao
ty man rly appreciate it
also I guess my main question is how do you make a normal list to use that reordable list subclass instead?
you create a custom editor and use the reorderable list in it
or a custom property drawer
I've only done the former, I don't use attributes very often
Btw, it is not required to make a subclass of RL
if you want to do any custom UI then you do
but you are correct
you can use it as is by passing in the serializedobject
Can't make custom property drawers of Lists or arrays. Would need to be a class that contains one
You can do it via an attribute, I think
What do you mean?
if you want to override the list item GUI
Nope, attributes are applied to the elements in the list 😦
really?
Ah, actually if you add to the drawElementCallback it uses that instead of the default
Yup
Haha, it is undocumented, and editor knowledge and scripting has come a long way and a lot more common now. So I can imagine a lot of misinformation and such used to go around
like I said -- dinosaur
I'm kind of at a loss for how to deal with this
Deal with what now?
Hm. So I am trying to load in level data - I have that working 'in game', but in the editor there are lots of references, data, gameobjects disappearing. I think I need to do two things, but it might require disabling a huge amount of functionality to get there.
I was talking with Mad a tiny bit on it
and I really should 'reply'
part of me wants to start over in a fresh project, but that'll be the sixth time. But I could test the Master Singleton and all that nonsense.
LOL. Well if you describe the problem I might be able to make some suggestions.
Sometimes it can also help to test things from scratch in an empty project and build up so you don't have so many interconnected systems right from the start
Just during the process of 'loading in' from the level file, I'll have data not appearing. Can I assume "Awake" isn't normally called in Unity Editor?
Figure out how to do it then go back to your main project and implement it sort of thing
Do you use anything like Singletons or Master Singletons with Editor resources?
Sort of, on components (MonoBehaviours) Awake is not called unless the class has a ExecuteInEditMode attribute. However it is called for ScriptableObjects regardless
Yeah, I use Singletons in editor
How do you go about maintaining the Instance reference to iself for the Unity Editor?
I wonder if I need to learn how to properly partition code in Unity. I'm not sure there's anything that describes how to do that - I've been focused on a class based approach of monobehaviors.
then I keep on running into people talking about SOs, but I have no use for them like this?
Resources.FindObjectsOfType
I'm scratching my head. It means your Singleton.Instance reference would either have to be remade every interface click or...
No, but I can't give you proper advice since I don't know what class type your singleton is (SO, Mono, or normal C# class) and I don't know if you are talking about it being editor only, runtime only, or both
I'm thinking I need to start completely over.
so the Singleton is Mono
and references over Mono classes on its gameobject. the gameobject is in an initialization scene
my goal was to code the core 'loading in/creating level' features, as well as the actor initialization features, to be able to function in both Editor and Runtime
the actual 'actor behavior'/updates wouldn't run. just enough to drop actors in, then some basic code to save and load the level
but that's not so simple
(as it turns out)
I'm struggling with trying to "Save" a prefab manually after making some changes to it via editor scripts. The prefab is open when this logic is executed, so I'm not sure what I'm doing wrong.
PrefabStage prefabStage = PrefabStageUtility.GetCurrentPrefabStage();
GameObject prefabInstance = prefabStage.prefabContentsRoot;
PrefabUtility.ApplyPrefabInstance(prefabInstance, InteractionMode.AutomatedAction);
I get the following error:
ArgumentException: Calling apply or revert methods on an object which is not part of a Prefab instance is not supported.
Does anyone have any ideas on how to accomplish this? I'm basically wanting to simulate clicking the "Save" button in Unity's prefab editor window.
Let's say I throw out everything and start over.
My intention for organizing this -
- make a singleton holding some subclasses/things so actors can call music, get sprites, other behavior
- save and load level data to jsons instead of using scenes. this is because there are lots of little levels
- make prefabs for the various in-game actors.
- make it so that I can push buttons in Unity Editor for load/save/new levels, and thus use the Unity Editor to actually edit levels?
How would I make this? Should I use SOs for singletons? saved level data? actors?
Sorry if I'm too aggressive. at the end of my rope here.
I'm basically seeing how I should be creating the elements of my code so it will actually work the way Unity seems to want it to. Which I have no idea where to begin.
I think the architecture might be the easiest. So I'll try to focus on that, I suppose.
@gloomy chasm sorry about rambling. Here's a direct question - how do you script actors for your game? ie- is it a category-of-actor monobehavior inheriting the basic actor stuff?
Not really sure what you mean by "actor" but basically everything is just inherited from MonoBehaviour and like 99% of your components will inherit directly from it
So you don't use SO's much? Actor is... well, a gameobject. Presumably with some scripted behavior. Item, player, enemy classes in a traditional coding environment
Oh, so you mean in relation to SOs. SO are used to stare data. For example I have a Item SO for storing info about an item in my game. Then in say an inventory. SOs are generally used when you want to store data independent of a scene.
Think of a GameObject as a simple class that contains a list of classes (MonoBehaviours), and MonoBehaviours can be thought of as normal C# classes that have a Update/Start/etc. methods that the GO will call.
This is all getting a bit off topic though (it happens) so this should be continued in #archived-code-general
The SO stuff can hold then. Okay - so I don't need to think about SOs. It sounds like I have multiple separate problems... to focus on references, it sounds like Unity Editor will 'forget' any refs to things like game objects or unity classes?
It will lose references to any non-persistent UnityEngine.Objects (SO, GO, Mono, etc.) on domain reload
However they are still there and can be found by using Resources.FindAllOfType
just tricky to sneak that into my source code. I need either to eschew most references... or have a parallel script for 'editor' behavior where I can include those "Find Alls" instead of refs. I know there's a specific behavior for folders called "Editor"?
noted on "domain reload". That's a name I can look up.
Uhh, you shouldn't need to. Would need to see code though to tell.
Domain reloading is when Unity basically clears all C# instances and states and recreates them from C++. This happens when a script changes or you enter playmode (unless the option is toggled off)
Got it. Part of what I'm experiencing might be different, but I'll have to track that down separately. Hm, [InitializeOnLoadMethod] triggers when a script changes but not when I -return- from playmode. Is there a trigger I can set somewhere for the Unity Editor for that?
It doesn't trigger when exiting playmode because that does not trigger a domain reload (script recompile)
I believe there is something like EditorApplication.playModeStateChanged
of course, editor only
Saving all this to my notes. Definitely will look for that.
Trying to do what I can to 'initialize' the editor data at least. Some of what I'm experiencing has been called a sync serialization issue, but there's so much code I can't begin to grasp how to identify it.
Do you ever have to diagnose problems like that? I am going to dig up the general error checking, but that's quite a specific one
sync serialization issue? As in the loaded data is different than the stored data or something?
Ah. Sounds like my issue was misdiagnosed. I won't worry about that, then - I think it more had to do with a combination of other things.
Will take me a while but will try and hash this out. Thanks for putting up with my nonsense.
Sure thing all good, we all gotta start somewhere! Best of luck!
Trying to salvage this so I don't have to do my fifth total rebuild 😉 Part of the pressure is trying to code 'properly' in Unity - would rather learn it on this project rather than a much larger one.
had a huge battle with wsl2, docker, a custom upscaler, all that tonight. so now I go zz
Hi!
Is it possible to write the content of a string field in the inspector header?
i don't think so. if you create the inspector drawer from scratch it's possible, but without rewriting it custom i don't think so

this tells me it must be possible.....
You can if you use UIToolkit along with some reflection
But I would call it intermediate skill level or higher
Well you would need to use reflection to get the inspector windows, but from there it is actually pretty easy. You would find all child InspectorElements of the rootVisualElement and then add a element as a child of the header
At least I think so that would work
When working with custom reorderable lists is it possible to use the default behavior for showing list objects or do I really need to write my own drawElementCallback? Do I really need to basically remake the default behavior by manually showing each property field...? It currently looks like this and the only callback I wanna change is the add one
EditorGUI.PropertyField(..) 🙂
There are also other wrappers around the default reorderable lists that make life easier....
yeah I know how to show them.. I just want to use the default behaviour and not have to do that for each future field I want to add
you should be able to call that on the top list element
and it should show the sub fields as the default
oohhh shit that makes sense
i guess that should work didnt think of that lol
although still kinda dumb it doesn't do that by default :C
It is because it is made to show anything, not just SerializedProperties
You can show just a normal old C# list in it
I did a quick thing and I'm not sure if UIements would work...
As the header is a IMGUI box....
You basically add an element that overlaps it
I think you can add a child that will capture mouse events before the IMGUI but I can't remember
Uff that is a big hack......
why is there no "GetInspectorHeaderContent" returning a gui content....
Thinking about it, I would register a mouse down callback to the header IMGUIContainer, and on a double click create a textfield element as a child, and connect it to the name field
?
well sure but how would i replace the text that is there?
Oh that is just the .name
yourComponent.name
so this should make it editable?
cause that is the name of the game object
not the individual script
If memory serves
Hey guys, I'm trying to display an array of gameobjects in a custom inspector with the ability for me to add items to it
However, I can not see the array, can someone please help me, this is my code
attackObjectArraySize = EditorGUILayout.IntField("Attack Objects size", attackObjectArraySize);
if (attackObjects != null && attackObjectArraySize != attackObjects.arraySize) {
// attackObjects = new GameObject[attackObjectArraySize];
for (int i = 0; i < attackObjectArraySize; i++) {
// attackObjects[i] = EditorGUILayout.ObjectField("Object: " + i.ToString(), attackObjects[i],
// typeof(GameObject), false) as GameObject;
if(EditorGUILayout.PropertyField(attackObjects, includeChildren:true)) {
serializedObject.ApplyModifiedProperties();
}
}
}
I have additionally tried to use SerializedProperties and using the code below
if (attackObjects != null && attackObjectArraySize != attackObjects.Length) {
attackObjects = new GameObject[attackObjectArraySize];
for (int i = 0; i < attackObjectArraySize; i++) {
attackObjects[i] = EditorGUILayout.ObjectField("Object: " + i.ToString(), attackObjects[i],
typeof(GameObject), false) as GameObject;
}
}
@severe maple have you tested all the sub parts of your logic? there are 3 cases that could result in the property field not getting drawn
- attackObjects is null
- attackObjectArraySize == attackObjects.arraySize
- attackObjectArraySize == 0
so one of those is probably true and causing it not to get drawn
side note, you should be calling serializedObject.ApplyModifiedProperties() at the end of the inspector gui -- you don't need to do it more than once per pass
If I make a mono script run in the editor, Update() Runs every time the editor changes at all, but is there a function I could call that only runs when the object itself is changed?
Hello, so I was wondering, can we like change the 'Drag Icon thingy' of ReorderableList?
I hope this is the right place to ask:
(Visual Studio editor)
- Where can I specify which language I work in so that I get syntax highlighting?
- For some reason
Debugger for Unitydoesn't appear when I look for extensions in VS and a tutorial I'm following asks for it. How do I get VS to find it?
Start here - I believe this is what your asking for. Once this is installed - syntax highlighting should start working after.
I feel like I am being stupid, but it isn't possible for a EditorApplication.update to happen at the exact same time as a draw event right? I mean if I populate a list in OnGUI and clear in the update, there is no risk of the list being half populated and then cleared right?
Okay I didn't think so, but some times you just have those moments where you question yourself
Thanks for the sanity check
np
I'm getting the error 'You are pushing more GUIClips than you are popping' without it showing what in the code is causing that. It's old code so I can't tell what part would be doing that either. Looking online I'm seeing it happening from functions with a seperate begin and end function not getting ended, but I don't have any of those. Know any other things that could cause this?
Is it possible to make a custom property drawer for lists now that generic serialization is supported? I'm trying to make a property drawer that modifies the reorderable lists Add button to show a generic menu with every derived type to make working with lists and polymorphism nice
oh no. guess it's been too long since i wrote a property drawer. was wondering why this didn't work 😅
[CustomPropertyDrawer(typeof(List<>))]
@whole steppe
maybe try
if (Application.IsPlaying(this))
return;
If you put Application.isPlaying into the Debug.Log, does it show true? 🤔
Eventually you can substitute the Application.isPlaying in your if statement with
https://docs.unity3d.com/ScriptReference/EditorApplication-isPlayingOrWillChangePlaymode.html
I'm baffled by how little documentation done to GraphView even tho it's been used extensively in shadergraph and vfxgraph
It is still 'experimental' so its fine /s
Also, it is actually documented now? Last time I used it I had to just dig through the shadergraph code to figure out how to use it haha.
i have no clue about you guys but i just cant get my game working with mirror
Even the examples are outdated https://github.com/Unity-Technologies/UIElementsExamples
Many obsolete apis
#archived-code-general would be the appropriate channel 🙂
okay
its an extention tho
Ah, see this channel is for talking about making your own editor extensions like custom editor windows and inspectors and stuff.
Nope, never touched networking 😛 And even if I had, still not the right channel.
Yeah, Unity is notoriously bad at keeping their examples and demos up to date
If you do have any questions about the GraphView let me know, I might be able to help
It should not be experimental I think, shadergraph, vfxgraph etc are using those extensively... I guess it's just lack of documentation, thus experimental
How would you set center a newly instantiated Node into graphview ?
Yeah, idk why it is still experimental. It has been pretty stable for quite some time now, not like they are making breaking changes really.
See this @gloomy chasm
I tried getting the transform, layout, rect size etc all to no avail
Hmmm, I don't remember, lol. I would look at how the node moving tool moves them.
I've tried all these, they just won't work```
element.resolvedStyle.width ()
element.resolvedStyle.height ()
element.worldBound ()
element.transform
element.layout
If you are doing it right after it was created none of those will have been initialized yet I believe
does anyone know why all of my SerializedProperty would have hasVisibleChildren == false?
What controls what is "visible"?
the docs are unhelpful
mb isExpanded?
nope
They should be all true by default, unless it doesn't have children
[HideInInspector] affects visibility iirc
ooh ok
I have [HideInInspector] attribute but I'm trying to draw it using a custom inspector
so maybe that's screwing it up
There is something else that affects it as well I think but I don't remember
bc I don't want to bother creating an entirely custom inspector yet
but I also don't want the visual noise from certain fields
being drawn twice
thus I was hiding them
I mean, you said that it was annoying, so I was wondering what about it was annoying
it's annoying that HideInInspector also causes all the properties to be set to non-visible, even if I'm drawing it myself
I mean there is nothing stopping you from still drawing them yourself is there?
there is
And what is that?
Does PropertyField not work if they are non-visible or something?
Ah, well you can do it manually by iterating the children
yeah, that's what I thought
and I did that
this is what happens
I can't tell properties with custom drawers apart from those without
so I draw the custom drawer and then dive into the children and draw the x and y fields again
anyway, thanks for the help!
What now? I would be most interested to see the code as I feel like you are doing something unnecessarily complicated...
not really, was just drawing property fields in a loop
void DoSettingsEditor ( SerializedProperty property ) {
property.isExpanded = EditorGUILayout.Foldout( property.isExpanded, property.displayName );
if( property.isExpanded ) {
property.Next( true );
var startDepth = property.depth;
do {
EditorGUI.indentLevel = property.depth;
EditorGUILayout.PropertyField( property, true );
} while( property.Next( true ) && property.depth >= startDepth );
EditorGUI.indentLevel = startDepth;
}
}
I only did this bc I wasn't getting children drawn
my intent originally was just to use PropertyField
@gloomy chasm
Is this in a Editor or a PropertyDrawer?
it's in an editor
Editor I assume?
I see, yeah so I don't get why you would hide a property and then still want to show it. But you are right that is the only way.
Because I want to conditionally show several different serialized properties depending on the value of a field
I serialize all of it at once, but I only show one at a time
Yeah I still don't get how that means you need to show hidden ones
😄
because the items I want to show one at a time are the multiple serialized values I'm trying to hide earlier in the inspector
this entire thing is only a problem because I was trying not to do too much work too soon and lean on DrawDefaultInspector
but it seems I cannot
Oh I think I get it. Yeah seems like you are trying to have your cake and eat it too 😛
is that too much to ask? 😄
lol
anyway, it's a moot point bc I bit the bullet and am implementing a full custom inspector
lol, "one of us, one of us, one of us"
it's annoying to do it this early bc the serialized properties are still in flux and I don't like having to constantly update the editor
but needs must
Yeah, you could iterate over all of them like you are and then do special handling for ones with certain names?
blah
I'm using SerializedReference, so the properties that are getting serialized are arbitrary
I thought about doing it based on types but I just really don't want to create a giant switch case
That is what Cinemachine does... (I hate it thanks for asking)
Oh... yeah...
haha
really? I'm surprised they do that for their behaviours
since you can just do Editor.GetEditor for unity objects
Yeah, each editor has like a list of strings of properties not to show, and then they iterate over every SP and if it's name is in the list they skip it.
that's stupid
They do some other stuff too
yeah...
I chalk it up to 7 year old code and not fully understanding Unity at the time.
yah probably
editor stuff is pretty esoteric
maybe you can help me rubber duck on a related problem...
I had a call with them late last year about converting the editor to UITK
They ended up deciding that the back and forth wouldn't be efficient, but they do plan to redo their editors at some point so thats nice.
Sure
the reason I'm doing all the dynamic switching thing is bc I'm creating a custom importer -- this importer is built around the idea of running scriptableobject-based pipelines to process the file and generate the unity assets.
There's a couple of built-in pipelines, but I want the user to be able to provide their own as well
animation import example
sprite import example
that dynamic foldout on the bottom is the source of all my earlier problems
anyway, here's my dilemma -- I want pipelines to support arbitrary properties (a la cinemachine)
but this is an importer, so I can't just stick it on a child gameobject
right now I'm using SerializeReference to save the custom settings object for each pipeline
(and some permananently serialized values for the built-ins)
however the downside of this solution is that I can't easily support custom editors
because the settings aren't unity objects
if I make them scriptableobjects they need to live as an asset, I can't serialize them onto the importer meta
I think I am going to need to see some of the backend code to understand what the problem is fully. If they are not Unity Objects that is where you use PropertyDrawers
You sure 😉
Ya can save them to files outside of the assets folder or as subassets
I don't feel like I really understand the setup currently
that just feels really unwieldy
ok, let me try and sketch out the picture.
Asset comes in, OnImportAsset gets called
scripted importer takes the currently set pipeline (which is either created on demand if it's a built-in pipeline, or is an object reference to a pipeline asset in the assets folder) and executes it (passing it the serialized settings object), then writes the result to AssetImportContext
for quick reference, here's the current pipeline handling code inside the importer
spriteImportSettings and animationImportSettings is what you see in the inspector in the foldout
Okay, I think I am getting it. And spriteImportSettings is a normal C# class? Or what...?
yeah, that implements an interface
And the pipeline SO is an SO because?
still sketching it out, but I like the ease of use of the object picker
on the user side, for picking custom pipelines
Oh so will you be saving them in the future instead of creating/destroying them each time?
I could just make a dropdown of types
yeah, that's the idea
I'm debating making the pipeline a node graph
so it'd be relevant there
I can't just put settings on the pipeline bc I want it to be per asset
Got it, and so about the spriteImportSettings. You said that is what is seen in the inspector? Where are they stored?
right now, stored as variables on the importer
for per-asset settings
if I put it on the SO then it'd be per SO
I could make a key value store to store custom props, like they do for presets
The Unity importer?
yes
ScriptedImporter
I could make a key value store to store custom props, like they do for presets
Oh alrighty, I think I get it now.
that's just a big commitment & carries its own implications etc.
PropertyDrawer is not great, it doesn't exist in Layout space which is inconvenient
And so remind me again what the issue was now that I understand the system better
serializing a custom class by reference doesn't extend UnityEngine.Object so I can't use custom editors with the settings objects
and other more vague feelings of unwieldy-ness
Oh that it? PropertyDrawer or make a custom, custom prperty drawer system
Managed to finally set newly instantiated Nodes to center, by Re-setting the positiong via SetPosition right after 1st instantiation.. weird, but it work... Incase somebody facing the same issue as I do
element.layout works
element.resolvedStyle Works
The rest, just... meh
yah, ok...
I don't like PropertyDrawer for aforementioned not-supported-by-gui-layout reasons
but a custom editor system isn't terrible as far as UX goes
I don't know basically anything about UITK, so I don't know what adding support for that would look like either
seems like everything's moving in that direction
TLDR: Want to initialise my class via my property drawer by creating a new instance of the class and assigning it to the property.
Seem to be stuck, I have a class
public class class1
{
[SerializeField]
private int value;
public class1(int value)
{
this.value = value;
}
}```
I try to write a property drawer for this,
```[CustomPropertyDrawer(typeof(class1))]
public class class1PropertyDrawer : PropertyDrawer
{
public override void OnGUI(SerializedProperty property, Rect position, string label)
{
property.objectReferenceValue = new class1(0);
}
}```
and am able to get the value field but want to set the property 'objectreferencevalue' (hopefully) to point at this new instance of the class I have created within the property drawer as a way of initializing this class1.
```property.objectReferenceValue = new class1(0);```
but I have a conversion issue, is there a recommended way to perform this conversion? am I assigning this new instance to the wrong property?
If you are creating a custom editor and you know the settings will only be in that editor, it is super simply to create a custom property drawer system that supports layout
how so
It is, 10/10 recommend. It is imo, far better in almost every way to IMGUI
I'm sure it is 😄
but the evil you know...
how would I go about using a UITK inspector for my importer, as a way to experiment with it?
@misty igloo objectReferenceValue is for UnityEngine.Object types
Is there a property for assigning non UnityEngine.Object types?
you want managedReferenceValue, I think
noice
class PropDrawerAtt : Attribute { public PropDrawerBaseAtt(Type type) {} }
class BasePropDrawer
{
virtual void OnGUI(SerializedProperty prop) { }
}
// In editor
// In OnEnable
var classes = TypeCache.GetClassAttribute<PropDrawerAtt>();
foreach class in classes
dictionary[class.GetAttribute().DrawerType] = class;
// In ONGUI
foreach property
if (dictionary.Contains(property.type))
dictionary[property.type].OnGUI(property)
The code gets more pseudo and broken as it goes down, but I think that gives you the basic idea.
It is a great class
it is
Override CreateInspectorGUI
Then do like root.Add(new PropertyField(property)) instead of EditorGUILayout.PropertyField(property)
man they don't support GUIContent in UIElements? lame 😄
InvalidOperationException: Attempting to set the managed reference value on a SerializedProperty that is set to a 'class1' :/
I mean there is .tooltip and .text. The only GUIContent part it doesn't support is the image/icon
yeah, I mean that I like being able to just set GUIContent and have text and tooltip taken care of at once
Is the field serialized with [SerializeReference]?
Ah, haha
which field now? 😮
how do I do apply/revert gui with UITK?
Whatever field is Class1 yourField;
Eh?
it complains if I don't have it
but it's complaining about the IMGUI method
and I can't really combine the two
that's all IMGUI :c
class1 is the new class instance I'm trying to assign to the property
``root.Add(new IMGUIContainer(ApplyRevertGUI));`
value is the internal variable within that class
Oh sorry I didn't look at your code clearly. Why are you trying to set an instance of itself basically..?
@misty igloo oh yah, looking closer I don't think it's so simple to serialize a [Serializable] class
Is that UITK or IMGUI?
that's UITK
It might be being squished?
I'm assinging a scriptable and then creating an instance of this via the given scriptable
@misty igloo bc serializable classes get exploded into individual properties with children
it's not as simple as just setting it to a new value
bummer
@misty igloo what gets printed for the type of the serializedproperty you're dealing with
out of curiousity
.type
or .propertyType
rather
or both 😄
squishy elements >:c
the OnGUI property is the class1 type
the managedreferencevalue appears to be of the same type?
That is going to be Generic iirc
property.propertyType this one?
yah
cool
looks like this might help you @misty igloo https://answers.unity.com/questions/627090/convert-serializedproperty-to-custom-class.html
Unity is the ultimate game development platform. Use Unity to build high-quality 3D and 2D games, deploy them across mobile, desktop, VR/AR, consoles or the Web, and connect with loyal and enthusiastic players and customers.
Please don't, that has other ramifications and you almost never want to do it. Especially when you don't fully understand how SerializedProperties work.
using the extensions, you can call serializedProperty.SetValue(new class1(0))
yah but it's so fun to mess with the fabric of the universe
but seriously that is a good point, SP can act really weird sometimes, what are you trying to accomplish @misty igloo
Yes but you and I know what it does and what is happening. For some one who doesn't fully understand it and all of Unity's quirks, it is a very bad idea. (For example dirtying, undo, etc.)
oh wow
Also if you are, then use mine. The one linked doesn't support SerializeReference or lists https://github.com/MechWarrior99/Bewildered-Core/blob/main/Editor/Extentions/SerializedPropertyValueExtensions.cs
handy
Hey
Is there a way to get the caret position from an EditorGUILayout.TextArea?
I work with potentially very large strings and want to be able to perform what could be a very expensive operation (if run as is with the whole string as an input) on the single line I'm on
Argh
look for TextEditor
it's an undocumented class
I don't remember how you get it
when I was working with it I believe it needed some reflection?
here @delicate pivot https://answers.unity.com/questions/411022/texteditor-in-editor-gui.html
Unity is the ultimate game development platform. Use Unity to build high-quality 3D and 2D games, deploy them across mobile, desktop, VR/AR, consoles or the Web, and connect with loyal and enthusiastic players and customers.
thankfully the TextEditor class itself isn't internal
Oh you saved my day
@gloomy chasm success!
thanks for rubber ducking -- I had considered a custom attribute, but I think I was discarding it prematurely for being too complex
this will work nicely for now
Nice!
Does anybody know why my reorderable list is updated only the first time I try to add stuff?
private void AddCategory(ItemCategory categoryToAdd)
{
var prop = reorderableList.serializedProperty;
prop.arraySize++;
var newElement = prop.GetArrayElementAtIndex(prop.arraySize - 1);
newElement.objectReferenceValue = categoryToAdd;
serializedObject.ApplyModifiedProperties();
}
this is called in the onaddcallback
and any time after the first time I add something it does nothing
Are you sure it does nothing? Is it maybe adding it but simply not updating visually?
yeah I think so... I also tried to debug it and the array inside my target object is not getting changed
it updates visually/changes only the first time which is very weird
Open a second inspector in debug mode for easy debugging
I just added a breakpoint and checked which values are getting updated on add
@gloomy chasm do you know if there are issues around setting the value for scriptable objects in your code base?
There is not, however you need to dirty the object.
And if you are using a custom editor you need to make sure to call serializedObject.Update() at the start.
Update is being called in OnInspectorGUI like so
serializedObject.Update();
reorderableList.DoLayoutList();
serializedObject.ApplyModifiedProperties();
but I also tried adding it at the beginning of my add method and still no luck 😦
also my ItemCategory is a scriptable object.. could this maybe be the issue? maybe im not setting the objectReferenceValue propely?
I was talking to Solist when I talked about updating. I'm not sure what is going on, what I would recommend is to simplify until it does work and then go from there.
was under the impression I could set the property.objectreferencevalue to dirty but not working?
That is because the property.objectRefVal is the value of the field, not the object containing the field.
ya need to set the property.serializedObject.target dirty
serializedClass.SetValue(class1);
EditorUtility.SetDirty(property.serializedObject.targetObject);
property.serializedObject.UpdateIfRequiredOrScript();``` is this the correct ordering/steps?
Should be
What is serializedClass?
but the scriptable object doesn't go with it
serializedClass is a relative property I found from the main property
I thought the SetDirty method would set the targetobject + every child object below to dirty?
Alright I got it to work...
So in my ItemCategory I have two lists
[ReadOnly] public List<ItemCategory> categories;
private List<ItemCategory> oldCategories;
Before, my oldCategories list was set to public for testing purposes. And now what I did is just set it back to private and it started working fine again...
So somehow serializing my second list was affecting the serializedProperty that I pass into my reorderable list (categories).. which doesn't make any sense, but whatever it works...
What do you mean child object?
the object holds the class1, class1 could have a scriptableobject as a variable, I access this variable via "findRelativeProperty" then set the value
I assumed that using 'SetDirty'' on property.serializedObject.target would cover changes to the property and in turn changes to the serializedClass (scriptable object)
Oh, I see. No not at all. Think of it has storing an id to another scriptableObject. So it is a 'soft reference'
so would I have to dirty the serializedClass's serializedObject.target? or maybe even both?
I don't know what is going on or your setup. I would try a massively simplified setup for testing
got it working, turns out I needed ApplyModifiedProperties before UpdateIfRequiredOrScript
How do I get my custom inspector button to respond to Scene events? The behaviour I'm after is for these waypoints, I would like to click one, click my "Connect" button, then move the mouse back over to the scene and click another waypoint, and have my code know which game object was clicked so I can take over from there
I can already do this in an EditorWindow script with OnScene, get Event.current etc. but I can't find the equivelant for an Editor script
Maybe I need to do this in an EditorWindow instead?
SOLVED, don't mind me, I just hadn't typed the OnScene function properly so it wasn't being overridden.
Hey! I need some help with something. I'm trying to either create a custom PropertyDrawer for a List/Array of elements. However, I can't seem to get the PropertyDrawer to capture the List, it only captures the elements inside. Any ideas? Alternatively, I would also be able to work with overriding the default functionality of the + button in the default List interface. Thanks!
That is because Unity doesn't allow for creating property drawers for Lists or arrays
I think I may have found a solution. I want the default Unity drawing to happen, so I might just make a custom Editor, call DrawDefaultInspector, hide the fields I want, and create custom drawing for them below.
I know I can use a ReorderableList to achieve a similar result, but make it custom
Yup, that is a good way to do it
kinda dumb that we can't edit lists/array by default, but oh well
I know Odin inspector has the functionality I want, but I don't want to get it just yet
Hey friends, I'm running into an issue that I can't seem to solve on my own. Google provides some information but it's either not relevant or above my comprehension.
I'm getting this error:
I'm trying to write a custom property drawer that provides a dropdown for all other components on the gameobject
And I get the error when drawing said dropdown
Google says it's an issue of something changing between GUI passes, but I don't fully understand that so I can't fix it
#region Controller Select
var currentController = _controllerProperty.objectReferenceValue as MonoBehaviour;
var components = monoBehaviour.GetComponents<MonoBehaviour>();
var input = EditorGUILayout.Popup(
"Controller",
Array.IndexOf(components, currentController),
components.Select(mono => mono.name).ToArray());
_controllerProperty.objectReferenceValue = components[input];
#endregion```
Here's my code where currentController is the SerializedProperty that holds the MonoBehaviour
I don't see how that code could be causing that error
Is there somewhere you are conditionally drawing a control?
@acoustic egret
I really think that IEdgeConnectorListener should not be a separate interface... or rather something that we can subscribe to.. but ehh we don't have any choice here I guess
public class VPorts : IEdgeConnectorListener
{
public VPorts()
{
var g = (VGraphs[])Resources.FindObjectsOfTypeAll(typeof(VGraphs));
if(g.Length > 0)
vg = g[0];
}
private VGraphs vg;
public void OnDrop(GraphView graphView, Edge edge)
{
vg._vviews.ColorizeConnectedVNodes();
}
public void OnDropOutsidePort(Edge edge, Vector2 position)
{
vg._vviews.ColorizeConnectedVNodes();
}
}
How can I go about nesting the newly instantiated editorwindow to the existing one?
use the desiredDockNextTo overloads
how can I get which dock tho?
it's a type?
give me a sec, lemme try
This isn't working 😃 ... VGraphs.VGraphEditorWindow is just another editorwindow... proly I did it wrong?
public static void OpenVGraphsWindow()
{
var window = GetWindow<VCharacter>(VGraphs.VGraphEditorWindow);
window.titleContent = new GUIContent("VCharacter");
}
typeof(Example) is the type
is there anyway to add drop shadow to the Toolbar ?
not the text but the toolbar itself
guys i am trying to play particles system in editor mode , but idk why its not playing
Above that I'm checking if the property is in a monobehavior and drawing a label if it isn't
That's probably the cause
How would I avoid something like that?
Do I need to have my code behave differently depending on the pass?
Can you post that section
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
if (!(property.serializedObject.targetObject is MonoBehaviour monoBehaviour))
{
EditorGUILayout.LabelField("LocalFloat is only valid on MonoBehaviours.");
return;
}```
I don't know if this does what I expect it to, but I haven't had a chance to check due to the current error
The goal is to enforce the type is only used within a monobehaviour and not a scriptable object or something
So what I would do is add a like logging the current event and the result of that expression
It should not change in between layout and repaint
If it does that error will happen
I'm only seeing repaint events
Hmm
I'm getting this repeated
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
Debug.Log(Event.current.type);
if (!(property.serializedObject.targetObject is MonoBehaviour monoBehaviour))
{
Debug.Log("Not in mono");
EditorGUILayout.LabelField("LocalFloat is only valid on MonoBehaviours.");
return;
}
Debug.Log("In mono");```
Why is repaint lowercase.. what version are you on?
2020.3.18f1
How weird
Perhaps this isn't actually the issue?
Oh qait
If I comment out the dropdown from below the error goes away
Just clicked
You can't use layout events in property drawers
Leyout functions
It's all in gui space
Hmm
If you need more height then you override the get height method
I see
I dunno why it's like that, it's kinda dumb
Is there an easy way to know how large my UI parts will be?
But it is what it is
If you use singlelineheight that will be correct for one line of controls
And anything else I would probably hardcode the height anyway
Yah
Yay
I kind of wish there was that ability on UnityEvents, so that one could select sub-values of properties on objects, up until they select a valid float, int, bool, string, or Object.
agreed i find myself constantly writing utils like this cause unity events are a little lacking
im writing up a modular system for combat that can be dropped into nearly any project and itll just work
just attach damage senders on damage sources and damage receivers on things with health
then select their controller's values in inspector
anyone know if objectReferenceValues are safe to serialize or will they change each runtime?
just not sure if they use C# references or Unity instance references
it's of type UnityEngine.Object so I assume it's safe
objectReferenceValues seem to be safe... it is used inside the current UnityEventDrawer class I am investigating to see what's up with it
okay, how it seems to work, is that objectReferenceValue serializes to the {fileID: [number] } format inside of UnityScenes
gonna test it now to see if everything i wrote serializes fine
so far seems to be working, but im restarting to test serialization
in this case, the DamageSender is on the bullet, and the square has a DamageReceiver
the sender pulls from a pre-established controller on the bullet which holds its damage
and the receiver sets the value on a test script i wrote: ```cs
public class ControllerTest : MonoBehaviour
{
public float Damage = 5f;
public float Health = 25f;
private void Update()
{
if (Health <= 0f) Destroy(gameObject);
}
}```
works fine after a reboot, so objectReferenceValue is safe for my use case at least
thanks for all the help everyone! couldn't have gotten this going without you all
What's the correct way to raycast from the mouse in the scene view? Seems like my difficulty doing a raycast in my Editor script to hit an object in the Scene View, is that it's hard to get the correct mouse position within the Scene View. All my raycasts are off by some amount and always miss the target.
use HandleUtility
it takes that offset into consideration since the mouse position when you're doing scene gui is in GUI space which is not quite the same thing as screen space
Ahh thank you
Does anyone have something that allows me to automatically put prefabs under a parent object?
How can I select a gameobject I create? I'm currently listening for EventType.MouseDown and then spawn and select the new object. But doing a selection will cause the object to be deselected during mouse up. I thought I could manually Use() the MouseUp event but it still deselects my object? This is during EditorTool.OnToolGUI
And It's so hard for me...
Have you tried https://docs.unity3d.com/ScriptReference/PropertyDrawer.html ?
Yes I use it ^^
well if you look at code example 3 that's pretty much exactly what you want to do. Just draw the properties you're interested in. Right now it looks like you're drawing all of them?
You mean in editor, like when dragged in to the scene? If you are in 2020.3 there is a built in option, simply right-click a GameObject in the hierarchy and there will be a "Set as Default Parent" option.
using 2019.4 😭
What do you mean? Selection.activeObject = newlyCreatedObject;?
Basically my EditorTool sets the selection during MouseDown event, but then on MouseUp the selection is cleared by the editor. Because something else is interacting with it.
Ah, that is because the scene view sets selection on mouse up
Exactly, I'm not sure how to Use() that event so that it doesn't get deselected. Manually checking for the MouseUp event and calling Use() on it still causes it to be deselected.
Try changing the GUIUtility.hotControl
I just figured that out as you wrote it haha
That looks like it might do it after looking at the source
Anyone know a good way to Inject code into inherited PropertyDrawers? I am trying to implement this concept I wrote up:
The Goal: In UnityEventDrawer, there exists valid function calls within ScriptableObjects or other Unity Object Types inside Components on the GameObject.
Valid as in you can convert them into PersistentCalls. Thus I wish to edit UnityEventDrawer to be able to show these options that ought to be valid.
Line 722 in UnityEventDrawer
Grab all the fields on target and check whether they have an attribute [ConsiderForEvents] (maybe do this) and are derivable from UnityEngine.Object
foreach one with ConsiderForEvents
Do Lines 717 to 722, except target is now that object.
This should allow you to select valid functions on Sub-Properties of those behaviors, including ScriptableObjects.
Alternatively and probably better,
at line 690, grab such fields and run for each GeneratePopUpForType, where targetName is targetName.[type.Fullname]
possible issues: null values when running these functions may be a problem as they are usually guarenteed not to be null. a ?. call would probably
need to be changed somewhere.
To summarize it for future people, I get the controlID for this control, then when something I'm interesting happens I change the GUIUtility.hotControl
var e = Event.current;
var controlId = GUIUtility.GetControlID(GetHashCode(), FocusType.Passive);
if (e.type == EventType.MouseDown && e.button == 0)
{
GUIUtility.hotControl = controlId;
var instance = new GameObject("My Object");
Selection.SetActiveObjectWithContext(instance, this);
}
hello, I need to make a window that shows me all the things that need fixing in the project settings
with the traditional Fix/Fix All options
how could I do that?
The UnityEventDrawer is public meaning you can inherit from it. You can draw your own controls over existing ones and show your own dropdowns with your own logic. Alternatively you can use a public library called "harmony" which allows you to insert code before or after a method's code or replace it. However it is strongly advice you avoid this whenever possible.
What part are you asking how to do? Creating a editor window? Or finding the things that need to be fixed? Both?
Right so I would look up a getting started tutorial for using UIToolkit(UIElements) in the editor that should cover how to create a window. And as for the options. I am not really sure what you mean by 'fix' but you would most likely need to lookup what the API is for accessing each one, possibly having to look at the source code to figure out out.
there are certain assets like sdks that when imported, have a list of player settings that they ask you to fix
kind of like hdrp
ok one more question
is there any way to be able to drag and drop, reference, or do anything with a game object from the scene?
apparently not-
Of course! There is things like DragAndDrop which handles... dragging and dropping.
I mean like
if I can reference a gameobject in the scene inside a scriptable object
That is because the field is set to only allow assets
Oh no you can't
you can't reference scene objects from an asset
Not directly at least
oh god I need that tho
There is ExposedReference but you will need to resolve the reference from within the scene https://docs.unity3d.com/ScriptReference/ExposedReference_1.html
There is also GlobalObjectId, but it is editor only https://docs.unity3d.com/ScriptReference/GlobalObjectId.html
You can make a MonoBehaviour that sets the ScriptableObject reference to itself, thereby bypassing the no-scene references. Although you'd need a ScriptableObject for each reference you need. Use at your own risk though..
Okay, I was able to do it... I copied UnityEventDrawer, Inherited from it and then used a bunch of reflection to create a working abomination.
but, honestly, turns out it probably isn't needed
anyway, learned a lot, never doing that again.
quick question, so I have this event trigger when I click on an asset, however, I would like it to change when I double click on it instead
something like this official built in function
{
BehaviourTreeObject tree = Selection.activeObject as BehaviourTreeObject;
if (tree)
{
treeView.PopulateView(tree);
}
}```
Hey 👋
I'm trying to change the GameView size from code(https://answers.unity.com/questions/956123/add-and-select-game-view-resolution.html?_ga=2.222009296.915528479.1585746941-2112408147.1582032419)
However it doesn't work, a custom size is never added. Any ideas?
Unity is the ultimate game development platform. Use Unity to build high-quality 3D and 2D games, deploy them across mobile, desktop, VR/AR, consoles or the Web, and connect with loyal and enthusiastic players and customers.
Is there a good way to serialize the value of a serialized property in a generic way?, I was thinking maybe json, but not sure how well that would work with serialized reference, and from what I remember causes problems with Vector3s...?
I keep a bool value (flag) in a property drawer class and want it to be persistent even in game play mode.
It is not related to any serialized field.
The only way is to define a serialized field corresponding to it in that class (IPAddressV4)?
[CustomPropertyDrawer(typeof(IPAddressV4))]
public class IpAddressDrawer : PropertyDrawer
{
}
Yes. Though you can use SessionState if you want it to be shared by all the drawers.
and can't EditorGUILayout and GUILayout be used in Property drawers? So how can I group some fields inside a propertydrawer? nested box kinda
No, it is not shared
It is specific for a field
No, the Layout classes cannot be used in a PropertyDrawer
Then you either need to make do without or put it in the target class. If you do, you can surround it with #if UNITY_EDITOR so that the field will not be included in built.
Perfect, yes it is really messy if I add a field only because it is used in the editor. Thanks
Obviously not ideal, but it is what it is. Sure thing!
My problem
I have a toggle for Localhost. If it is ticked, the ip address should be changed to 127.0.0.1.
I wanted to keep that state in game mode as well
If you really wanted to you could get around this by creating a class that inherits from ScriptableSingleton, and have it contain a serializable dictionary where the key is the SerializedProperty's target object and the value is a list with the path. Then if the list contains the path then you know the bool is toggled, and vise versa.
OK
The problem with my proposed solution is that the dictionary and list would continue to grow over the editor session since they are never cleared.
However, we can consider it is as a solution 🙂
In the end, I think just having the field in the class is the better and cleaner way to go.
Normally I am strongly against having editor code in runtime classes, but sometimes it just can't be helped 🙂
My another problem is to get struct data in the property drawer.
Can you look at my approach :/
var obj = property.serializedObject.targetObject;
var type = obj.GetType();
var fieldInfo = type.GetField(property.name, BindingFlags.NonPublic | BindingFlags.Instance);
if (fieldInfo == null)
fieldInfo = type.GetField(property.name, BindingFlags.Public | BindingFlags.Instance);
if (fieldInfo.FieldType == typeof(IPAddressV4))
{
var height = position.height;
var posY = position.y;
var offset = height / 2f;
EditorGUI.LabelField(position, property.displayName);
EditorGUI.BeginChangeCheck();
var ipValue = (IPAddressV4)fieldInfo.GetValue(obj);
It is awful. I have searched to find a better solution. I think in Unity 2022, we have something for it
This will break instantly if the property is in another class or a list
I use 2019
Agree
You will need to split the property path and iterate over the whole thing, getting each value along the way to get the next field.
I did not get. You mean that my approach does not work in all situations?
When I start to work with editor, I have many problems so that I want to cry :/
Maybe because I am noob in editor coding
It doesn't work in 'most' situations. For example if I have a class MyClass which contains a IPAddressV4 field. The path for that would be _myClass._ipAddress._boolValue
So your type.GetField(property.name) will return null since you are trying to find the _myClass._ipAddress field inside of the targetObject
I happen to run in to this same problem @plain lake. So I wrote some extension methods to handle this exactly! Feel free to copy paste them in your project and ship them with it, it is fully MIT 🙂
https://github.com/MechWarrior99/Bewildered-Core/blob/main/Editor/Extentions/SerializedPropertyValueExtensions.cs
(You can also see what is required to do it)
Sure thing!
and finally, if you see 4 parts (ip address), the first one's position is not correct.
I have calculated it like below
var initialPos = EditorGUIUtility.labelWidth + IPPartWidth / 2f;
let me introduce you to EditorGUI.PrefixLabel(..)
None of them work, with out without IPPartWidth / 2f;
EditorGUIUtility.labelWidth
Solved, appreciated 🙂
var initialPos = EditorGUI.PrefixLabel(position,label).x;
how can I open a "Select Sprite" window via a script and save the selected sprite in a variable?
Do you mean the object picker window?
Yeah that is called the Object Picker window https://docs.unity3d.com/ScriptReference/EditorGUIUtility.ShowObjectPicker.html
how do I open one? its very vague
The method called EditorGUIUtility.ShowObjectPicker(..) 😉
how would I use Obj, SeachFilder and ControlID. I can vaguely understand searchFilter, but what options are there?
Did you already read the full documentation that I linked? I think it makes it pretty clear what most of them do/are used for.
oh yeah, I figured out how to open it, but VisualStudio says it saves as a void, whereas I want to save it to a sprite variable, how would I do that?
Did you read the second link I sent you? It goes over how to do it in the answers.
yes I did, but im having a hard time figuring out what im supposed to be looking for. Please dont get angry, im just as stressed out as you are. Not even something like this works;
then I get an error saying that it cant find the object in the print GetObjectPickerObject line.
All good, ya gotta wait for the 'event' before getting the object
if (Event.current.commandName == "ObjectSelectorUpdated")
{
print(EditorGUIUtility.GetObjectPickerObject());
}
It is a bit funky
You probably want to check that the controlID is the same so you know you are not getting the object from a different picker since you can have multiple open at once.
EditorGUIUtility.GetObjectPickerControlID() == currentPickerWindow
You will want to have the code that gets the picked object (snippet I just shared) inside of a GUI method (OnGUI, OnInspectorGUI, etc. whatever is correct for your situation).
And basically it just keeps checking if an object has been selected.
aka Event.current.commandName == "ObjectSelectorUpdated"
would this work if I have it inside a MenuItem "Containter"? (idk what its called), or would it only work in an GUI Method?
Ah, that makes it more complicated. So, no, not inherently it won't.
Why can’t these things be simpler
I think it will if it is in an Update.
// In MenuItem method...
EditorApplication.update += AssignObject;
// Elsewhere
private static void AssignObject()
{
if (Event.current.commandName == "ObjectSelectorUpdated")
{
Debug.Log(EditorGUIUtility.GetObjectPickerObject());
EditorApplication.update -= AssignObject;
}
}
I don't remember if Event.current.commandName is propagated in to the Update loop or if it is only in the GUI loop
So that might not work.
I’ll see if this works tomorrow I’ve got to go. Thanks for the info!
Sure thing, good luck and have a good night 🙂
I made a custom inspector for my waypoint nodes, and I can connect them to each other in the editor by clicking a "Connect" button, then clicking the next waypoint. The script adds that waypoint to a list of child nodes in the currently selected waypoint.