#↕️┃editor-extensions
1 messages · Page 113 of 1
var simulatorWindow = Resources.FindObjectsOfTypeAll<EditorWindow>().FirstOrDefault(window => window.GetType().FullName == "UnityEditor.DeviceSimulation.SimulatorWindow");
if (!simulatorWindow) {
throw new Exception("Could not find window!");
}
var element = simulatorWindow.rootVisualElement.Q<TextElement>("selected-device-name");
Debug.Log(element.text);
This worked in 2021.2 for me
Holy molly thanks @plucky knot this is great
You can do so much more since they did the UIElements stuff to the entire editor
It's so nice
But when in doubt pop open the UI Toolkit Debugger and see if what you want is available (and not hidden in an IMGUIContainer) 😄
ohhhhh this is amazing @plucky knot thanks so much for this advice!!
Anyone know a good way to store settings to be used at runtime?
Storing in the Resources folder is so ugly and messy...
For example, like tags. You create them in editor and then access them at runtime(build)
Yeah same, but it is so... ew
The file/folders are still going to be there though
I'm pretty good at ignoring that lol
anyone got a post processor* for importing fbx file ( prevent animation and material import ) ?
Can you just do https://docs.unity3d.com/ScriptReference/AssetPostprocessor.OnPreprocessModel.html and then change thoe settings..?
@tough cairn does a preset work?
you can set the preset as the default if that's what you're looking for
Did Unity hid a lot of Editor classes which were accessible before ?
I was looking at someone's github repo and they have used a lot of classes from UnityEditor that are not accessible anymore. Is there any replacement for that ?
My plans are for making custom debug console(replacement to Unity's default debug console).
Elaborate. Nobody can help you if you do not have any specifics at all
I am trying to upgrade:
https://github.com/akof1314/Unity-ConsoleTiny
and what is missing
classes from UnityEditor that are being used in that project
which are?
ListViewState, SplitterState, SplitterGUILayout, LogEntry, LogEntries, ListViewElement, ListViewGUI, FlexibleMenu, FlexibleMenuModifyItemUI
Methods such as TempContent, LoadIcon from EditorGUIUtility, ToolbarSearchField from EditorGUI
a lot of properties from EditorGUILayout and EditorGUI.
etc
I don't believe stuff like SplitterGUILayout has ever been non-internal
not even in v5 ?
I wonder if the "UnityEditor.Facebook.Extensions" assembly definition was some sort of hack to get access to the internals of Unity
because it doesn't make much sense to have named their assembly definition that otherwise?
Right, I am gonna explore that.
yeah... seems like a hack
What do they mean by open ?
definitely internal since it was made
I have no idea. I presume, clicking on it at all breaks it. I would seek out other methods for accessing the internals. I think there are assembly definition names you can use
Those are to access methods but what if one wants to use the type(class) defined internal? Like LogEntry class is defined internal in LogEntries.bindings.cs (UnityCsReference/Editor/Mono/LogEntries.bindings.cs )
That's what I'm saying. I have heard there are names you can use for asmdefs which make them compile as core code. But I cannot remember where I have seen that mentioned, so I can't be of much help there.
Maybe that's a false memory though. There's also this: https://github.com/mob-sakai/CSharpCompilerSettingsForUnity, which is a full-on dependency to have, but might be fine, as you can get it to modify one asmdef. I personally wouldn't want it in my project as a dependency unless it was important though.
https://github.com/akof1314/Unity-EditorInternalsVisibleDemo
Check out the ILSpy screenshot attached here. This is interesting
Gives the reason for having that asmdef
Name the assembly Unity.InternalAPIEditorBridge.001 (make sure you rename the Name inside the assmdef)
Thanks mate, that worked. I am noob in the assembly definition area, can you explain how it worked ?
https://github.com/Unity-Technologies/UnityCsReference/blob/master/Editor/Mono/AssemblyInfo/AssemblyInfo.cs#L81 just chose the one I vaguely remembered, it's also not clearly in use as an assembly that could be in a project, so I imagine it's one of the better ones.
Not sure what those assemblies are used for tbh.
https://docs.unity3d.com/Packages/com.unity.learn.iet-framework@2.1/changelog/CHANGELOG.html mentions it's using Unity.InternalAPIEditorBridge.007, so I presume there's some variation in the numbers they use across packages to avoid some sort of collision 🤷
Hello, how could I focus the Inspector editor window if I have them pinned in the same area?
Do you mean specifically that window? Or just any inspector?
Because the latter is much easier to do than the former.
the problem with that is that idk the name of the inspector window
dig into the reference source
It is either InspectorWindow or InspectorEditor, I don't remember witch
But I think it is InspectorWindow
It inherits from PropertyEditor (not that it matters in this case)
Type inspectorWindowType = typeof(EditorWindow).Assembly.GetType("UnityEditor.InspectorWindow);
beat me to it
Man, I am really starting to look forward to 2023 for the editor.
Cinemachine, Input system, Timeline, and others are moving to UITK.
Cinemachine, ProBuilder, Terrain, Particle system, and more are moving to using Overlays.
Localization package is doing a UI/UX redesign.
The inspector will be using UITK by default.
And I suspect the Editor Design System site will be up by then along with possibly seeing Graph Tools Foundation some time in 2023.
And of course there is Splines too.
anyone knows how to access remapped materials ?
can it be done in a postprocessor ?
all i really need are the string names "DarkBrown" , "DarkGreen" etc .
thanks
trying to write a postprocessor but every change to the script the editor will re-import all my assets ( which takes at least 2 minutes )
i thought about something like separating the classes so the compiler won't detect changes in the first one and avoid re-import the assets
class AssetPostprocessorEv : AssetPostprocessor
{
public static event System.Action<AssetPostprocessor> PreprocessModel;
void OnPreprocessModel() => PreprocessModel?.Invoke( this );
}
in a separate file :
public class FBXImporter : AssetPostprocessor
{
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterAssembliesLoaded)]
static void Import()
{
AssetPostprocessorEv.PreprocessModel += APP =>
{
Debug.Log( APP.assetPath );
};
}
}
but it doesn't seem to work
i right click on a single file and select re-import from the context menu
Hello to everyone.
I was wondering if is possible to create a custom editor window that automatically populates additional options based on your input.
For instances, I need a number of folders, but if the number is higher than 0, I need to be able to have options to input a value of how many assets will be created in those folders e.g scriptable objects.
I am able to create the parent folders (Such as Section 1,Section 2, Section 3), but adding the additional values I am uncertain of.
I created a image to help show what I aim for if it is understood. Sorry for my english.
Of course it is possible!
What UI framework are you using? IMGUI(GUILayout) or UIToolkit?
GUILayout I am using, thank you
You just use a for loop in that case
for (int i = 0; i < numberOfSections; i++)
{
sections[i] = EditorGUILayout.IntField("Assets in Section " + i, sections[i]);
}
Something like that
Please read the code and not just try to copy paste it as you will not learn much by copy pasting it. Feel free to ask questions 🙂
many thanks. i was unsure if i must have had to create a new int property value for each of the sections. I am just beginning to learn how to use the customised editors so thank you for your help sir
Sure thing.
I believe i am making an error in some area. I have created an array of values named assetsPerSection to save my new values. In OnGUI, i attempt to add the value as in your example of 'sections[i]', but it will always reset the value. How best to initialise and save the values? Should I use button perhaps to force the initialization only when I need to?
And I would use a list so you can just use Add(..)/Remove(..) instead and keep the values
Everytime i change something related to serialization (most often it's adding/commenting [SerializeReference]), i get this error and have to restart editor
(I think) it's a bit different each time
Should i be concerned?
Unity bug afaik, updating should help
ListView kinda broken when deleting multiple items
also, the bigger the list is the slower it will get... proly pooling would help?
the slowness is very noticeable, like so much delays when scrolling through
CollectionVirtualizationMethod.FixedHeight; only helps a bit, once it goes above 150 elements, the lag starts to kick in
What ListView? Do you mean the UIToolkit ListView? I assume not.
hi, how can i use "EditorGUILayout.BeginFoldoutHeaderGroup" from inside "ShowMaterialProperty" function
using UnityEngine;
using UnityEditor;
public class CustomShaderGUI : ShaderGUI
{
bool SettingsOpen = true;
bool Settings2Open = true;
string propertyName1 = "Base Map";
string propertyName2 = "Normal Map";
public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties)
{
ShowMaterialProperty(materialEditor, properties, SettingsOpen, propertyName1);
ShowMaterialProperty(materialEditor, properties, Settings2Open, propertyName2);
}
private void ShowMaterialProperty(MaterialEditor materialEditor, MaterialProperty[] properties, bool propertyStatus, string propertyName)
{
propertyStatus = EditorGUILayout.BeginFoldoutHeaderGroup(propertyStatus, propertyName);
if (propertyStatus)
{
string[] references = { "_MainTex"};
foreach (string reference in references)
{
MaterialProperty matReference = FindProperty(reference, properties);
materialEditor.ShaderProperty(matReference, matReference.displayName);
}
}
EditorGUILayout.EndFoldoutHeaderGroup();
}
}
When I use it as above, it doesn't turn off, it stays open all the time.
No problem when I use it inside the "OnGUI" function
using UnityEngine;
using UnityEditor;
public class CustomShaderGUI : ShaderGUI
{
bool SettingsOpen = true;
string propertyName1 = "Base Map";
public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties)
{
SettingsOpen = EditorGUILayout.BeginFoldoutHeaderGroup(SettingsOpen, propertyName1);
if (SettingsOpen)
{
string[] references = { "_MainTex"};
foreach (string reference in references)
{
MaterialProperty matReference = FindProperty(reference, properties);
materialEditor.ShaderProperty(matReference, matReference.displayName);
}
}
EditorGUILayout.EndFoldoutHeaderGroup();
}
}
That is because you are passing the SettingsOpen by value, bool is a value type not a reference type
The error you were getting was from IMGUI not UIToolkit
basically, only 1 editorWindow as a container for the uitoolkit
let me show you, give me a sec
oh wow, I think you're kinda on point, I added editor.minSize & maxSize and lock the layout size, and the error is gone...
the listview here was parented to a Box set to stretchedToParentSize, so I guess the error caused by the EditorWindow when child elements get shrunk.. either way this sounds like a bug
let me try to dock it somewhere and see if the error can be reproduce
ah yes, when docked, the error gets triggered again even with minSize/maxSize set
*dont mind the static background sound
just mute it
LOL
so what kind of structure should i use
I am still somewhat skeptical tbh. I would try to create a basic setup and go from there (Like, just a ListView, with a Label or something as the contents)
Do you understand what the problem is?
I'll give this a go
how do i get Texture2D from gameobject similar to this using asset data base loading a prefab ?
The static AssetPreview class
tried that
var prefab = AssetDatabase.LoadAssetAtPath<GameObject>( prefab_path );
Debug.Log( prefab ); > "prefab (UnityEngine.GameObject)"
var icon = AssetPreview.GetAssetPreview( prefab ); // GetMiniThumbnail
Debug.Log( icon ); > "Null"
anyway to use a temporarily camera so i can do Graphics.DrawMesh ? Doesn't seem like its possible to create new camera
unity why ? ....
public sealed class AssetPreview
{
[FreeFunction("AssetPreviewBindings::GetAssetPreview")]
internal static extern Texture2D GetAssetPreview(int instanceID, int clientID);
Yeah, but it is a pain 😛
There is PreviewRenderUtility for doing it custom
Should work
on prefab variants ?
also the Preview Render Utility is returning null as well
var preview = new PreviewRenderUtility( false );
preview.AddSingleGO( prefab );
preview.BeginPreview( new Rect( 0, 0, 128, 128 ) , "" );
preview.Render( true );
var icon = preview.EndPreview() as Texture2D;
Debug.Log( icon ); > "Null"
ah... its a render texture
is there anyway to convert to Tex2D ? seems like the other way around is the only way
Uhh it shouldn't be returning null
its not im just sleep deprived 🙃 its a render texture , the cast is null
still no luck
var preview = new PreviewRenderUtility(false);
preview.AddSingleGO(prefab);
preview.BeginPreview(new Rect(0, 0, 128, 128), "");
preview.Render(true);
var render_texture = preview.EndPreview() as RenderTexture;
var icon_flags = UnityEngine.Experimental.Rendering.TextureCreationFlags.None;
var icon = new Texture2D(256, 256, render_texture.graphicsFormat, 1, icon_flags);
icon.Apply(false);
try { Graphics.CopyTexture(preview.EndPreview(), icon); }
catch (System.Exception e) { Debug.LogError(e); }
finally { preview.Cleanup(); }
Debug.Log(icon);
byte[] bytes = icon.EncodeToPNG();
File.WriteAllBytes(Path.Combine(folder_icons, icon_name), bytes);
>> "Result texture output is black"
Hello again everyone. In relation to this, I have hit a wall where I can see the values, but they are not set/saved in the list. Can anyone provide an example of the correct process to initalise a list in an editor window, and have the values save from the newly created EditorGUILayout.IntField properties?
Use SerializedObjects instead of directly accessing the value
Yeah, as I said, its a pain to use. I have to look at how the GameObject inspector uses it to remember what needs to be setup. Again though, AssetPreview.GetAssetPreview should be working and might be a bug/corruption that it isn't.
(btw, it is black because the camera needs to be positioned as both the object and camera are at 0,0,0 by default)
Is it possible to "hook" into the Unity logger ? As in when Unity logger receives any kind of log(info, warning, error, etc), I wanna tap into that data(type of log, file name, line name)
[I am working on some automation]
I am gonna try that but not sure if that can replace the default logger, which Unity's.
Yep, can't do that.
How can I hide "(script)" ?
Add the AddComponentMenu attribute to the MonoBehaviour and give it a path.
Thanks!
do you remember which class is it that handles the GameObject inspector ?
@gloomy chasm look what i found https://github.com/CyberFoxHax/Unity3D_PreviewRenderUtility_Documentation/wiki/PreviewRenderUtility.BeginStaticPreview
Wow someone wrote docs for it
Neat!
i can no longer reimport after using the preview utility - and the prefab inspector will be blank
doing manual
AssetDatabase.ImportAsset( prefab_path , ImportAssetOptions.ForceUpdate );
will make the assets project window blank ( in addition to not being able to reimport from context menu and the inspector asset is blank )
blank ...
Its possible to do reimport from the context menu after script complication and it will make it normal again
why can't submit issues to the repo ❓
It is for reference only. Submit issues via the forums or the normal bug tracker
I would try in a new project... I think yours might be messed up...
sorry
ok i figured it out, the scale was wrong , in fact the it was so small that PreviewRenderUtility.DrawMesh didn't event render a single pixel
on the side note - all those odd behaviors were due to me calling DestroyImmediately on the textures after they have been rendered
which is quite odd - if i put DestroyImmediately anywhere in the same function After attempting to read data from it - it will break
almost like the code runner doesn't respect order of execution and will jump back in time to mess up with the code
I'm usually a bit of a lurker here... but has anyone else upgraded to Visual Studio 2022 after getting an in-app notice that the software was outdated, only to find that VS2022 doesn't do all the fancy Unity features like highlighting broken syntax or making suggestions? Like, if I type mathf. and it used to pop up the list of mathf things to choose, but now it only suggests previously declared variables and functions and nothing else
I'm hoping I'm just doing something wrong, but I can't figure out what
I hope I asked this in the right place. Nothing that I googled solved my problem.
#854851968446365696 has IDE configuration instructions in it
I'll run through it all again, but as far as I can tell I've already done all the required steps :/
Well, I've now been down that entire set of instructions twice, including reinstalls of Unity Hub, the editor, and an upgrade for Visual Studio. The tools for Unity thing is installed and shows up in the Tools menu for Visual Studio. Still, not auto-completion, and no debug help 😦
maybe I should give up and go back to VS 2019
Just upgrade 2020 to 2021 my project was broken and all prefab is missing
and you did not make a backup like the unity told you before you did the upgrade?
😀 yes
Hi all
I have a
[SerializeReference] SomeBaseClass data; in an SO and it doesn't persist editor restart
SomeBaseClass and all derived class has [Serializable], all have unique field
Im not sure why something this simple doesn't work
But a suspicion is.. i'm using plastic scm and i'm currently assigning data in OnValidate, and all t he SOs are still greyed out (need to press Check Out to edit values), even tho i can see the value updated
Maybe it's this? Nope, no difference
I'm on 2020.3.18
Anyone have tried something this basic? On this or earlier version?
Ok nvm
I need to do SetDirty in OnValidate
Huh..
Save massive compile cycle time! Turn off auto refresh! Use this script. Now your refresh hot key auto plays and stops games: https://pastebin.com/4PDY7xqy
Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.
Normally when you turn off autorefresh, you forget to hit it before play.
So nothing is gained.
so you NEVER forget
finally be able to get the gains of turning off auto refresh (tabbing from code to editor doesn't cause a load)!!!!!!!!
This should have been a core feature of Unity like 8 years ago
I just recently figured out how to make editor extensions
This is huge huge huge for those who want to turn off auto refresh
But don't cuz it takes a brain process to remember to hit refresh before play
It saves 30 minutes of dev time per 8 hours of coding. So if you have 100,000 devs world wide doing 8 hour sessions( a physics order of magnitude rough estimation), thats 3,000,000 minutes of dev time added a day or 1.5 million hours of man hours a day would be gained by adding this as a core feature.
When you hit f12: it compiles and runs, runs if compiled and stops if playing.
It takes a bit of training to get to f12 to compile+run/stop, but it is something you don't forget once you're in a habit unlike hitting two key combinations in the old mode.
This isn't the place to advertise, use #archived-resources instead
And in like, fewer words.
Where do I ask how to add Unity module to my microsoft visual studio so it is recognizing the code im writing and can autocomplete it? Sorry didnt find any channel so idk where to ask. As you can see by the picture it is now all white and its not letting me autocomplete the code
#💻┃unity-talk , iirc there's also a tutorial in #854851968446365696
Thanks I just managed to fix it. Just didnt know where to look for it so thanks for your help on pointing me in the right direction.
@mossy wren just some feedback, you may just want to do that automatically whenever the editor enters play mode is about to enter play mode (while Autorefresh is off)
that way you don't have to rely on the user remembering to press a button
Is there a resource somewhere with the order of execution for event functions for editor scripts? Having some issues with first time initialization and OnEnable/OnDisable during domain reload
How to create an array in the Custom Editor ? I see many posts online but none of them comes up with a the same solution 🧐
serialized properties
if it's an array on an editor window and not part of component editor, u need to get a ref to the window itself and use the FindProperty method w/ that ref to serialize the array
[SerializeField] private List<Sprite> _sprites;
private SerializedObject _serializedObject;
private void OnEnable()
{
_serializedObject = new SerializedObject(this);
}
private void OnGUI()
{
EditorGUILayout.PropertyField(_serializedObject.FindProperty("_sprites"));
_serializedObject.ApplyModifiedProperties();
}
here's an example for doing that on an editor window
it's pretty much the same thing for a component inspector editor, so if you find a tutorial or documentation that goes thru a similar process, that's your answer
FindProperty() and using the property name as a string for the parameter is the way to do it. make sure to serialize the property
hope that helps
@worldly echo
Thank you 🙂 I will look into that @lyric herald
cool, good luck!
just went thru the exact troubles myself, so figured i'd share the more complicated scenario
cuz there's 0 documentation for referencing an editor window itself as the serialized object
a fair bit more straight forward and clear documentation when dealing w/ inspectors
@lyric herald So let's say I have this In my MonoB class:
public int[] orderOfEvents;```
then In my Custom Editor I have:
//Number of Events
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("Number of Events", GUILayout.Width(EditorGUIUtility.labelWidth));
thisCutscene.numberOfEvents = EditorGUILayout.IntField(thisCutscene.numberOfEvents);
EditorGUILayout.EndHorizontal();
And now I want to make so my array is of size numberOfEvents
dont use IntField directly, use PropertyField instead. Then you can wrap it in a ChangeCheck and modify your array if needed
I didn't understand that :S (SOrry just started Custom Editor Scripting today)
did you set up a SerializedObject of the editor itself like tpop mentioned?
can read up on that
if u don't serialize the object and use a serialized property, the editor won't save the changes, and you also can't show an array
intfield is just for a single integer
afaik
the only way to surface an array in an editor window or inspector is thru serialized property, or by manually writing code to iterate thru the array and drawing each variable in it separately
which is not a good solution
I think I did
private SerializedObject _serializedObject;
and public void OnEnable()
{
_serializedObject = new SerializedObject(this);
}
right ?
EditorGUILayout.PropertyField(_serializedObject.FindProperty("orderOfEvents"));
The tl;dr is that you never ever want to directly edit a variable, you always want to do it through a property field
yeah. if you don't you'll just be banging ur head, cuz unity will not save half of what ur tryin to accomplish
the most important thing to know about serialized properties and objects, is that they are automatically integrated into unity's save system in the editor. and they also go thru some additional backend structure. None of which is easily reproduced manually thru code, and if ur struggling w/ serialized objects n properties, then trying to handle the backend stuff u get for free by avoiding serialized objects/properties is prolly over ur head anyway.
but using them is as simple as getting a serializedObject ref to the editor window ur working with, and using the FindProperty method to get the serialized property ur after.
Okay all this is still a bit obscure to me 😬 I will dig through the doc !
The SerializedObject page has a really clean example of how to do a Sine wave animation. The important detail here is that your editor window works exactly like any other MonoBehaviour editor. Note how the example specifies that it's an Editor for that script? Since it's an editor it has access to serializedObject which is simply the MonoBehaviour that's edited/shown in the inspector.
But in your EditorWindow you don't really have a specific object, so instead you reference your own window as a SerializedObject. That's what tpop showed before. From that point on it works exactly as if you were making an editor for a MonoBehaviour. So you can get the reference to any variables you want to draw using the exact same method as the SineAnimationEditor example
This way you have automatic undo support and everything will look just like it does in the editor
Are you starting to understand or still brain implosion? (I know I was stuck on brain implosion for some time)
Brain melting but I think it's because of Fatigue + Allergies x)
haha np, can you paste the code you have atm? and I'll show you how to change it
Oh boy if you want but it's very messy xD
Should be fine
I need to go to sleep I think. What I'm trying to build right now is a Custom Cutscene Editor for a 2D game
oh right you have a custom Editor, I though we were on EditorWindow
this makes stuff a lot easier
Let's assume we have a completely clean OnInspectorGUI()
All right
So bascially the code is currently```cs
[CustomEditor(typeof(Cutscene))]
public class CutSceneEditor : Editor
{
public override void OnInspectorGUI()
{
}
}```
The first thing you always want to do is make sure your serializedObject (the monobehaviour we're editing) is always up to date. And finally any changes we make should be applied ```cs
[CustomEditor(typeof(Cutscene))]
public class CutSceneEditor : Editor
{
public override void OnInspectorGUI()
{
serializedObject.Update();
//Actual code goes here
serializedObject.ApplyModifiedProperties();
}
}```
So it's important to make sure that you always .Update() before doing anythying. and always end with ApplyModifiedProperties()
for starters lets just draw the public int numberOfEvents; variable
[CustomEditor(typeof(Cutscene))]
public class CutSceneEditor : Editor
{
public override void OnInspectorGUI()
{
serializedObject.Update();
var numberProp = serializedObject.FindProperty("numberOfEvents");
EditorGUILayout.PropertyField(numberProp);
serializedObject.ApplyModifiedProperties();
}
}```
And that's it, now we're drawing a field that you can edit undo and whatever modify it however else you want
So how do we draw that array? Simple, the exact same way
[CustomEditor(typeof(Cutscene))]
public class CutSceneEditor : Editor
{
public override void OnInspectorGUI()
{
serializedObject.Update();
var numberProp = serializedObject.FindProperty("numberOfEvents");
EditorGUILayout.PropertyField(numberProp);
var numberArrayProp = serializedObject.FindProperty("orderOfEvents");
EditorGUILayout.PropertyField(numberArrayProp);
serializedObject.ApplyModifiedProperties();
}
}
You can skip the whole making a local variable and just put it straight in the PropertyField call if you want
If you try this out, does it draw for you?
Yup
Right nice, see the pattern here? I don't use any of those specific IntField, ObjectField, FloatField etc. Only PropertyField
PropertyField automagically knows what it's supposed to draw
So for your original question, how do we detect a change and update the array accordingly?
Nice, and it's suseptible to undo shenanigans if I understood correctly ?
correct, it handles undo without any problems
So to see if something was changed we use a ChangeCheck: ```cs
[CustomEditor(typeof(Cutscene))]
public class CutSceneEditor : Editor
{
public override void OnInspectorGUI()
{
serializedObject.Update();
EditorGUI.BeginChangeCheck();
var numberProp = serializedObject.FindProperty("numberOfEvents");
EditorGUILayout.PropertyField(numberProp);
var change = EditorGUI.EndChangeCheck();
if(change)
{
//Value was changed!
}
var numberArrayProp = serializedObject.FindProperty("orderOfEvents");
EditorGUILayout.PropertyField(numberArrayProp);
serializedObject.ApplyModifiedProperties();
}
}```
Last thing is to modify the array size of your array
[CustomEditor(typeof(Cutscene))]
public class CutSceneEditor : Editor
{
public override void OnInspectorGUI()
{
serializedObject.Update();
EditorGUI.BeginChangeCheck();
var numberProp = serializedObject.FindProperty("numberOfEvents");
EditorGUILayout.PropertyField(numberProp);
var numberArrayProp = serializedObject.FindProperty("orderOfEvents");
var change = EditorGUI.EndChangeCheck();
if(change)
{
numberArrayProp.arraySize = numberProp.intValue;
}
EditorGUILayout.PropertyField(numberArrayProp);
serializedObject.ApplyModifiedProperties();
}
}```
since we call serializedObject.ApplyModifiedProperties(); at the end it will apply the modification we did in code
And that's about it really
Keep using PropertyField for the rest of your UI and draw what you want etc
Okay Thanks a lot four your time and fo rthe help !
I would lie if I understood all of it but I will come back to it tomorrow 😁
Yeah it's a pretty simple base to start on, give it a good rest and it will probably make a lot of sense tomorrow ^^
Yeah that's probably wiser x)
Thanks again though 🙂 I will keep you updated if I manage to make something cool with it ^^
Sure, feel free to @ me tomorrow if something crops up
Hi guys, I am writing a property drawer for a serializable class but I am running into an issue. I have the drawer in it's simplest form right now (basically doing nothing):
#if UNITY_EDITOR
[CustomPropertyDrawer(typeof(AssetSwitcher<GameObject>), true)]
public class AssetSwitcherDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
EditorGUI.BeginProperty (position, label, property);
EditorGUI.PropertyField(position, property.FindPropertyRelative("collection"), label);
EditorGUI.EndProperty ();
}
}
#endif
And soething goes wrong with the height not being calculated right (Check screenshot). I am pretty sure I am just making a really stupid mistake.
@tight pine you need to override GetPropertyHeight
right now your PropertyDrawer thinks it has 0 height
so you need to tell it exactly how tall of a space it needs to reserve
ho, so I need to do something like ask the property how tall it is (it changes depending on the number of elements) do I need to use EditorGUI.GetPropertyHeight on the "collection" property?
Thanks a lot @patent pebble!
a curiosity, Why don't property drawers work like custom editors where you can use EditorGUILayout instead to automate most of this stuff?
I think it's because they don't receive a pre-pass that calculates the total GUI size, as that prepass uses the PropertyHeight of your PropertyDrawer. So it would probably cause some weird recursion error. That's why you get the rect directly in OnGUI
@vapid prism Good point. Makes sense 🙂
as for overriding GetPropertyHeight, make sure you also check the .isExpanded property of your array to ensure that it works for both closed and expanded views. You can use EditorGUIUtility.singleLineHeight to get a standard line height, and EditorGUIUtility.standardVerticalSpacing to get the spacing between the lines
Then it's just a matter of calculating all the lines and multiply by those values
This seems to work perfect:
#if UNITY_EDITOR
[CustomPropertyDrawer(typeof(AssetSwitcher<GameObject>), true)]
public class AssetSwitcherDrawer : PropertyDrawer
{
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
return EditorGUI.GetPropertyHeight(property.FindPropertyRelative("collection"), true);
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
EditorGUI.BeginProperty (position, label, property);
EditorGUI.PropertyField(position, property.FindPropertyRelative("collection"), label);
EditorGUI.EndProperty ();
}
}
#endif
For both expanded and collapsed
yeah that seems to work fine for PropertyFields
if you are doing something else like buttons or other GUI fields you usually have to manually calculate the height
But of course when I add more stuff I will need to calculate stuff and add to it
yeye
Just one more thing, how can I get access to the object represented by property? (On the code above I want to access my AssetSwitcher<GameObject>)
I don't think there is an easy way to do that. What do you need it for?
I want to call a function on that object when a button is pressed
Basically to autofill the 'collection' array
Hmm, would it be easier if you made an editor for whatever your AssetSwitcher<GameObject> is used in? Since you're in a property drawer it could technically belong to any class
But it can be used in anything 😬
I do not need to deal with the class containing it. It can handle itself.
But I see how that can be a problem...
Yeah I'm not sure actually how to do this
Thanks @vapid prism, I will explore a little more and make some tests. If I find a solution I will post it here.
I should be able to add and change elements on the array from the property. So my only problem is that I cannot call the function on the AssetSwitcher class that autofills the array.... so I guess I will have to move that logic into the PropertyDrawer
@tight pine there's a couple ways of doing it
it depends exactly what target object you want to get to call the method from
for example if the field your property represents is a C# class's instance in a field inside of a MonoBehaviour
or if it's just a field in a MonoBehaviour
Which should be ok cause this would be the only place where it gets called.... as far as I can see....
so I guess I will have to move that logic into the PropertyDrawer
this is also a viable option
i guess it depends what your design needs
usually if the code is editor-only it should be fine to move into the drawer
but sometimes that's not possible
brb, gonna dig out an example I have somewhere
@tight pine here's a quick example
and the extension method for the SerializedProperty
https://pastebin.com/ndvqQm5B
i'm a bit rusty so I may be forgetting some caveats of this solution, so don't take it as a 100% perfect approach
so test it thoroughly when you use it
no problem
with this sort of thing, specially when mixing "normal" stuff and SerializedProperty/SerializedObject stuff
you will most likely need to use reflection
unless it's a very simple thing
Yeah, it's a really smart solution!! A lot of thinking went into this 🙂
I am testing just moving the logic to the drawer, in my case that is totally ok. And I am now trying to fill the array directly on the property. Still not sure if it is going to work but about to test it.... but it might be I will have to go the reflection way...
doing the filling logic directly form your drawer should be fine
dealing with arrays and serialized properties can get tricky if you've never dealt with them
so feel free to ask for help here if you need it
lots of helpful peeps around this channel usually
I see what you mean hahaha
calling
collection.objectReferenceValue = objects[i]; // collection is a SerializedProperty and objects[i] is a GameObject
and I get:
type is not a supported pptr value.
🙂 @visual stag Thanks I thought that would be the case
It's important to note that you cannot get/set serialized properties which are not at the base of the serialization hierarchy.
The only thing you can do with a serialized property of a collection is set .arraySize, and get its members via the helper methods. It doesn't have a .xValue property
Damn... today I am hitting walls 🤦🏻♂️
Ok, I think I need some sleep, tomorrow I'll come up with something hahaha Thanks a lot guys!! It was super helpful!!
Kinda dumb question. Is there a way to have a specific custom editor extension still be available even when there are compiler errors? I'm building a package where upon import it has errors due to not finding references for certain scripts which need to be pointed to with an asmdef that I want to generate in a different location. Currently I manually create an asmdef in the desired location but I want to add a context menu option for it instead so it's easier for the end user.
yes move it into a dll
serialized fields are null/empty during the OnPreprocessBuild method, anyone have an idea on this as the fields are definitely populated in the inspector
Hi guys, I tried to make buttons for every direction with PropertyDrawer. If is there a template or by default a code in unity I can use it.. otherwise my quesion is. How can I fill left and right button like up and down which uses the origin "position" variable.
I did for the left and right button this
Rect origin = position;
Rect horizontal = origin;
horizontal.width = 100f;
Ok I just guessed it but this is enough horizontal.width = Screen.width / 2f
It works with it
@rare surge the rect you get for property drawer expands to the entire available width of the window
so you can use that rect width instead of Screen.width
@crude relic thanks, it is even better.
yw
I have "ActiveSkill : ScriptableSkill : ScriptableObject" and i wanna change it to simply "DataSkill : ScriptableObject", and currently there is still "ActiveSkill : DataSkill" but empty
All my SO data's are all of type ActiveSkill
Can i change this type to DataSkill now?
ItemData = serializedObject.FindProperty("_itemData");
ItemDataType = ItemData.FindPropertyRelative("Type");
...
int previousValue = ItemDataType.intValue;```
@visual stag I can do first part in OnEnable() without issue?
Yeah, as long as you create the SerializedProperty field for ItemDataType
how does this behave for null ItemData?
Ah, actually, with your setup it's much more annoying... sorry
ItemData is an objectReferenceValue, meaning it's in a whole other serialized property hierarchy
But I can check if it is null and then do the appropriate thing right?
you could just use ItemData.objectReferenceValue directly, which is the ScriptableItemData
But if you want to actually perform SerializedProperty operations on it, you have to do a lot more work, and also handle null.
I go over it here https://help.vertx.xyz/programming/editor-issues/serialisation/serializedobject-how-to#objects
okay, I'll check it out 😄 thanks
I noticed that having a IMGUI Scroll view taller than all it's content will add a horizontal scroll bar for some reason. I also noticed that setting max height fixes this.
So how can I limit the max height of the scroll view to it's content's total height? In my case it's only filled with 32 GUILayout.Label so I thought that I could just get the max height like so: var maxHeight = EditorGUIUtility.singleLineHeight * 32; but it doesn't match and limits the scroll view to 29 items in height. How would I calculate the height?
The behaviour I am looking for is no scroll bars to show when the window with the scroll view is large enough to show all of the content.
Hmm I think this was some sort of bug actually. I was manually setting the alwaysShowHorizontal to false in my ScrollViewScope, but by not setting it at all it works as expected.
You're probably forgetting the https://docs.unity3d.com/ScriptReference/EditorGUIUtility-standardVerticalSpacing.html
Oh yeah I forgot to mention that using the space it's too big instead
Is there a way to tell if a SerializedProperty has a CustomPropertyDrawer?
you can probably use TypeCache 🤔
Yeah probably, just ended up not worrying about it though. Might revisit it later.
Has anyone seen this error before when using EditorGUI.PropertyField:
InvalidOperationException: The operation is not possible when moved past all properties (Next returned false)
It happened when I reordered my list
i've had that happened sometimes while manipulating a SerializedProperty or SerializedObject "improperly"
as in them getting destroyed before the serialization stuff has time to finish
the error seems pretty generic, so it probably can be triggered by a variety of situations
as far as I can tell, the error is telling you "a SerializedProperty doesn't exist"
I see, I'll look through my reordering code again. Thanks!
if you are removing/reordering stuff from a list it can mean you are manipulating the list and not applying the changes
I've had similar situations happen to me
So the problem was in my CustomPropertyDrawer for the serializedProperty. I was trying to store relative properties so it wouldn't have to find them every OnGUI call, but it seems they were becoming "bad" references even though they weren't null.
Hi there! i was thinking of having a label with a tooltip in a property drawer of mine. So, i did it! first, i first initialised my guicontent:
text = "Dialog line : " + LocalizationManager.GetTranslation(((ETranslationKeys)key.enumValueIndex).ToString()),
tooltip = "Dialog line : " + LocalizationManager.GetTranslation(((ETranslationKeys)key.enumValueIndex).ToString()),
};```
It basically reads a line of dialogue, and the tooltip is basically going to be used so that even long paragraph can be displayed if there's not enough space in editor. It goes like this:
so you can see my label on the right. But weirdly enough : no tooltips when hovering.
at first, thought it was the rect, might just be wrong, so i decided to draw it:
it's there, and perfect.
Unity tooltips are buggy af
then i thought maybe another rect is overlapping with it, but still nothing
And it's bugged in 2021.3 that it doesn't show ever
IIRC it also doesn't show in playmode
How to reproduce: 1. Open the attached user "tooltip.zip" project 2. Open the SampleScene Scene found in the Scenes folder 3. Select...
(if you saw my upgraded tool, Navi; you'd be proud )
Send pics
Is that graph view?
Ah I think I used that in the past
Was a little painful back then 😛
(also the contrast on that great line 😬 )
Looks good though
i think i can change it, i'll see lol
yeah! I changed the architecture of my dialogs, and... Of anything lol
We're currently developping a game with this tool and it's so amazing how easy it was
it's going to be a patreon, might send it in #archived-works-in-progress soon 👀
Wanna be tagged when i do?
Sure
nice! i won't forget 👀
xNode, ugh, the good ole imgui
oh yeah that's a thing now as well
only 2020.1?
still in preview, yes
ooooh okok
Oof lol
i'll upgrade my project when they announce Unity 2.0 and redo basically everything, at least deleting useless things that still are codeable lol
I mean at some point, you gotta admit redoing a project from the beginning is easier when you have really precise experience: you coded the EXACT same thing in the past
So if you correctly wrote what went wrong, you can do it better, right? 🤡
One day, we gonna have it one day
Why do you think most rewrites fail?
i don't think it does fail, i've done this all my life and it's incredible how this works amazingly well
I just don't know if unity devs would make a rewrite work 
By the way, GUIStyle.CalcHeight still doesn't work with wordwrap in 2021.2.8f1?
i mean, is there an issuetracker of this somewhere?
(i'm testing this, brb)
Code:
GUIStyle labelStyle = new() {
wordWrap = true,
alignment = TextAnchor.UpperLeft,
};
GUIContent labelContent = new() {
text = "Dialog line : " + LocalizationManager.GetTranslation(((ETranslationKeys)key.enumValueIndex).ToString()),
tooltip = "Dialog line : " + LocalizationManager.GetTranslation(((ETranslationKeys)key.enumValueIndex).ToString()),
};
Rect labelRect = new Rect(keyRect) {
x = keyRect.x,
y = keyRect.y + keyRect.height + 4,
height = labelStyle.CalcHeight(labelContent,keyRect.width),
};
Rect CharRect = new Rect(labelRect) {
y = labelRect.y + EditorGUIUtility.singleLineHeight + 4,
height = EditorGUIUtility.singleLineHeight,
};
Rect conditionsRect = new Rect(CharRect) {
y = CharRect.y + EditorGUI.GetPropertyHeight(property.FindPropertyRelative("character")) + 4 + EditorGUIUtility.singleLineHeight,
x = CharRect.x - 10,
};
EditorGUI.LabelField(labelRect,labelContent,labelStyle);
Behavior:
im i missing something on my Character Rect maybe?
oh wait-
ok it works lol
Weird, i'm trying some things and:
Code:
//In my dialog line:
[Serializable]
public class LocalizedDialogLine : DialogLineBase {
[SearchableEnum] public ETranslationKeys Key;
public bool functionsUnfolded = false;
public float LabelHeight=18;
public override string ToString() {
return "- " + character.ToString() + " : \"" + LocalizationManager.GetTranslation(Key.ToString()) + "\"\n";
}
}
//########################In Editor: script (of my dialog line)
var Height = property.FindPropertyRelative("LabelHeight");
Rect labelRect = new Rect(keyRect) {
x = keyRect.x,
y = keyRect.y + keyRect.height + 4,
height = labelStyle.CalcHeight(labelContent,keyRect.width),
};
Height.floatValue = labelRect.height;
Debug.Log(Height.floatValue);
Basically, after calculating the height, i'm stocking it into a variable i've got into my dialog line object.
behavior:
Basically tells me that sometimes the height is actually fifteen
Yeah that's not what you're suppsoed to do
(i need to do that so that i can have my GetPropertyHeight that's well calulcated:
public override float GetPropertyHeight(SerializedProperty property,GUIContent label) {
var functionsUnfolded = property.FindPropertyRelative("functionsUnfolded");
var Height = property.FindPropertyRelative("LabelHeight");
return EditorGUI.GetPropertyHeight(property.FindPropertyRelative("Key"))
+ EditorGUI.GetPropertyHeight(property.FindPropertyRelative("character"))
+ (functionsUnfolded.boolValue ? EditorGUI.GetPropertyHeight(property.FindPropertyRelative("Conditions"))
+ Mathf.Max(EditorGUI.GetPropertyHeight(property.FindPropertyRelative("reactionsAfterLine")),EditorGUI.GetPropertyHeight(property.FindPropertyRelative("reactionsBeforeLine")))
+ Mathf.Max(EditorGUI.GetPropertyHeight(property.FindPropertyRelative("AfterDialogEvents")),EditorGUI.GetPropertyHeight(property.FindPropertyRelative("BeforeDialogEvents")))
: EditorGUIUtility.singleLineHeight)
+ Height.floatValue
+ 10;
}```
You should recalculate it in your height method
oh well i can do that too yeah
Thanks lol
but how?
Ive got position.width in public override void OnGUI(Rect position,SerializedProperty property,GUIContent label), but not in getPropertyHeight
(because i need this width to calculate my height)
My window doesn't take the whole screen lol
Brb need to grab something to eat, don't hesitate to spam me with answers lol
screen.width is magic and returns the width of the window
No way 😳😳
I'll try naively lol
and what do you propose for the y of the rect? screen.y? 🥴
(i think i don't need it, i'm messing with you)
Okay, things aren't working, and other things are
you know what's working? The tooltip 🥴
that's a thing i didn't expect 
The height is what you calculate
y was the y position of the rect, but i do not need it because all i need is the height (so basically, the deltaY, so distance between y and y+height)
Yes
but forget about it, since the tooltip works, i'll just cut the text if it's too long, or just display "hover for dialog line"
so for the tooltip to work, i guess you need to also have a GUIStyle
Hi! Is there some high level functions in unity to implement "Rect Tool" controls like for sprites on a screen?
Never used it though
@waxen sandal yes, this is for creating custom editor tool, but i want just use already existed Rect Tool for my monobehviour
Oh, I don't think so then
Hello, i installed visual studio 2022 community edition, but my editor doesn't have intellicode... Do you guys know how to install the autofill with unity scripts ? I installed the unity dependancy and also the intellicode one
i reinstalled the 2019 edition, but still, there is no autocompletion
I have an .fbx file exported from Blender with a bunch of different meshes.
I'm writing a tool that will take those meshes and do some processing,
Since the importer seems to create a GO for every mesh and automagically populates the right materials and everything I thought I could use these GO in the code but when I use AssetDatabase.LoadAllAssetsAtPath the resulting GOs don't have meshes or materials populated
// filters out prefabs starting with _ and main assets
var prefabs = paths.Select(path => AssetDatabase.LoadAllAssetsAtPath(path))
.SelectMany(x => x)
.Select(x => x as GameObject)
.Where(x => x != null && !x.name.StartsWith('_') && AssetDatabase.IsSubAsset(x.GetInstanceID()))
.ToList();
var mesh = prefab.GetComponent<MeshFilter>().mesh; // null but in the editor it's populated
var materials = prefab.GetComponent<MeshRenderer>().materials; // also null
Can I get the path of created scene?
Hey guys! Hope you are all good (Happy kingsday if you are in NL :)) I'm still juggling serialized objects and found an issue that I can't find enough info on:
I am writing a property drawer for a generic (serializable) class and all its subclasses and template types. And I need to check some loaded assets against the type that an array expects:
My class structure (just the important part):"
public class AssetSwitcher<T> : Switcher<T> where T : Object
{
public T [] collection;
}
And I am loading assets from a folder on the project and adding them to the collection. But I want to load only the ones with the right type
Here's the relevant code from the PropertyDrawer:
[CustomPropertyDrawer(typeof(AssetSwitcher<>), true)]
public class AssetSwitcherDrawer : PropertyDrawer
{
[...]
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
[...]
SerializedProperty collection = property.FindPropertyRelative("collection");
string folderPath = GetCurrentlySelectedFolder();
if(folderPath != "")
{
if(GUI.Button(buttonRect, "Load from folder"))
{
Debug.Log($"Loading objects in folder: {folderPath}");
IEnumerable<string> assetFiles = GetFiles(folderPath);
foreach (string path in assetFiles)
{
if(!path.Contains(".meta")) {
Object obj = AssetDatabase.LoadAssetAtPath(path, typeof(Object));
Debug.Log($"Found a object of type: {obj.GetType()}. Looking for: {collection.arrayElementType}"); // THIS IS THE PROBLEM == Output: Found a object of type: UnityEngine.GameObject. Looking for: PPtr<$GameObject>
//if(obj != null && obj.GetType().ToString() == collection.arrayElementType) // <== Thus, this does not work
int index = collection.arraySize;
collection.InsertArrayElementAtIndex(index);
collection.GetArrayElementAtIndex(index).objectReferenceValue = obj;
}
}
}
}
}
}
Actual question: How can I get the actual type of the object (UnityEngine.GameObject in this test case) instead of the serialized object type PPtr<$GameObject>?
Does anyone know how I can display these dashes when multiple objects are selected?
Using EditorGUI.FloatField
I mean the simplest solution is to just get a substring of the serialized type.
Otherwise you will need to get the field info and get the type from that.
This is my implementation that you can rip if you want (MIT). https://github.com/MechWarrior99/Bewildered-Core/blob/main/Editor/Extentions/SerializedPropertyValueExtensions.cs#L160
EditorGUI.showMixedValue = true
But if it is just a label then —
Wow! That's where it was hiding! Thanks 😄 Will try it out
I did realize I am using a custom style on the FloatField
Will see how that affects it
Works fine 🙂
@gloomy chasm Thank you so much! Having a look...
@gloomy chasm Works amazing!! What a cool product! and super clean code!
Thanks! Glad you like it! 🙂
Hello everyone. Can you help me with CustomInspector. I have a struct with 2 fields and want to make that looks like in Vector2
You make a property drawer for that type, then calculate the positions to be on the same line and draw them using EnumField and FloatField
I never before do CustomEditor what should I do at first. Be glad if you leave link to article
Seems pretty similar to what you're doing
It doesn't matter for propertydrawers
And I already use CustomEditor
Did you read the link?
Basically for MonoBehaviours and ScriptableObjects you create custom editors and for structs and class you create custom property drawers
It's because first two from Unity?
Yes
Yeah
What do you mean?
That is because there is no serialized field called position I imagine
Unity can't serialize interfaces unless you serialize the field with the [SerializeReference] attribute (even if the field is public)
is there a way or an asset, that lets me add a gameobject to multiple scenes at once? I have 100 scenes and opening it one by one to add the objects takes bit long 🙂
why that
idk. for example: If in each scene you just changing obstacles you can use one scene
its actually a level based game where each scenes has a different style
but I need a object on some of these scenes to add
cool, heard about that, so there is no way to add it with like drag and drop?
I don't sure about this. But if you drag one scene to another them have to merge
hmm ok, this don't destroy thing, this the same like if I would drop a object to multiple scenes, I just save some time with it, right?
yup
cool thx
Can't
I mean, you can, but it would be a lot more work than it is worth and takes a bit of trickery.
ok
Thank you any way
😄
@gloomy chasm then how I can get number of element but write Item instead of ELement
string number = label.text[label.text.Length - 1] 😛
label.tooltip
There is just eights
Are you caching it some where?
stop...
What about... double digit numbers
Yeah, using Substring would be better with a const "Element ".Length
You're right
What about, if it's not in an array 🤯
😐
Listen, I was just answering the question that was asked!
Ooh I know
Use the propertyPath instead
duh
string path = property.propertyPath;
if (path.EndsWith(']'))
{
int index = path.LastIndexOf('[') + 1;
label.text = "item " + path.Substring(index, path.Length - 1);
}
What about... double digit numbers
Yeah I just remembed
Okay, I think that will do. I don't remember exactly what numbers Substring takes
I don't think you have to pass the second parameter (also it's not the end index, it's the length)
The last character is ]
The second param is the character count isn't it.
Ehh it is close enough to get the idea across
Unrelated. But in the newest 2022.2 alpha there is this, and I have no idea what it could mean
And I really want to know
Well, time to install the alpha
I need to analyze all of my scenes as part of the build process. How do I get the root game objects of every scene in my build settings? SceneManager.GetSceneByBuildIndex(i) only works when the scenes are loaded.
Yeah... no idea what changed :/
I looked at float and object fields, try dragging and stuff, tried the list. Looked at it in the UITK Debugger, and the inspector in debug mode. Absolutely no idea...
You can't get game objects from a scene if the scene is not loaded.
hm. ill have to think of something else, then
You can read the actual file if that helps
maybe
hey! anyone knows if the shadergraph node editor framework is out of experimental state? It's usable but I thought that with the release of the visual scripting thing they might have something that can be used to make custom node editors?
Nope, still 'experimental'. But should be quite safe to use!
Yeah I actually have a whole dialogue editor based on it, but I'll soon need to make a generic node editor version so that I can make node editors for other purpose and not have to redo everything
So it would be nice if they released something official
Ah, Unity is working on a package called GraphToolsFoundation which will handle both the view and data side of creating graph based tools. At some point every graph based tool in Unity will use it. However it's development has moved internal and I wouldn't expect to see anything until 2023.2, maybe 2023.1 (could be 2024 or later of course)
ooh damn that's very cool!
Because right now I have to handle it myself and it's quite a pain haha
Yeah I get that! It really is a pain. There is a github project called like "Blue Graph" or something like that
it does the same sort of thing
Not official of course
I would say right now to definitely not use the GraphToolsFoundation package that is publicly available though
Yeah I expect it to change a lot. The lead dev has moved over to who was the lead(?) of UIToolkit, so I expect it to be a lot nicer
The API right now it really bad with a lot, and I mean a lot of boilerplate
oooh yeah well I'll stick to my thing for now I guess lol
Yeah haha
And then in 3 years I'll probably make the switch, seems reasonable enough haha
thanks for the tips!
Sure thing! Best of luck!
Ay thanks!
hey
i’m on unity apple silicon
and for soem reason cant find progrids
i went to the projetc settings
and enabled preview packages
but still couldnt find it
Does anyone have any idea why this:
string folderPath = EditorUtility.OpenFolderPanel("Load assets from folder", "Assets", "");
inside of the OnGUI() of a property drawer results in:
InvalidOperationException: Stack empty.
System.Collections.Generic.Stack`1[T].Pop () (at <6073cf49ed704e958b8a66d540dea948>:0)
UnityEditor.EditorGUI.EndProperty () (at <780782bc035845f9909cebbd4c983ae3>:0)
Moonlander.Shapeshifter.AssetSwitcherDrawer.OnGUI (UnityEngine.Rect position, UnityEditor.SerializedProperty property, UnityEngine.GUIContent label) (at Assets/Shapeshifter/Switchers/AssetSwitcher.cs:93)
UnityEditor.PropertyDrawer.OnGUISafe (UnityEngine.Rect position, UnityEditor.SerializedProperty property, UnityEngine.GUIContent label) (at <780782bc035845f9909cebbd4c983ae3>:0)
UnityEditor.PropertyHandler.OnGUI (UnityEngine.Rect position, UnityEditor.SerializedProperty property, UnityEngine.GUIContent label, System.Boolean includeChildren, UnityEngine.Rect visibleArea) (at <780782bc035845f9909cebbd4c983ae3>:0)
UnityEditor.GenericInspector.OnOptimizedInspectorGUI (UnityEngine.Rect contentRect) (at <780782bc035845f9909cebbd4c983ae3>:0)
UnityEditor.UIElements.InspectorElement+<>c__DisplayClass59_0.<CreateIMGUIInspectorFromEditor>b__0 () (at <3d6ac16e3c754a199373804b462a1b72>:0)
UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr, Boolean&)
Note: The call to EditorUtility.OpenFolderPanel works fine, panel appears, right path comes out of it but it fails on the end of the OnGUI function. Even if I comment out everything else and just leave that call, it still fails.
On the other hand, if I replace it with:
string folderPath = "[Path to the same folder that I selected on the panel]";
everything works just fine.... 🤔
@waxen sandal ho Maybe that's something. A timing issue maybe...
Thanks a lot.
That gives me some room to explore... it's weird that everything else I do after the call runs just fine and the error just happens when the function returns
But yeah, it also makes sense that the problem can appear only when unity does not expect OnGUI to take that long....
Strange that there is not much mention of that anywhere (Googling around like a maniac)
How do I validate a scene name on OnValidate on a ScriptableObject?
https://forum.unity.com/threads/invalidoperationexception-stack-empty.517358/ it's efectively this
Thanks a lot
@waxen sandal in the end I just changed it to a "Drag&Drop the folder here". It's more fun then browsing anyway :). Thanks a lot!
@tight pine try slapping a GUIUtility.ExitGUI after you get the file back
Oh the link mentions that already
🙂 yeah, I think that would work. I first though it would stop execution of the function so I didn't eve try it cause I thought drag and drop would be better UX anyway.
Now that I read the docs I see that it does not stop the execution, just prevents other events from evaluating
In any case, smarter every day! 🙂 next time I know
Thanks a lot @crude relic
Could someone lend me a hand on a custom property drawer? It's my first time implementing one of these and I'm getting a bit of odd behaviour:
List resize:
List Resize:
public static void Resize<T>(this List<T> list, int newSize, T defaultValue = default(T)) {
if (newSize < 0) return;
if (newSize == list.Count) return;
int size = list.Count;
if (newSize < size) {
list.RemoveRange(newSize, size - newSize);
} else if (newSize > size) {
if (newSize > list.Capacity) {
// this bit is purely an optimisation, to avoid multiple automatic capacity changes.
list.Capacity = newSize;
}
list.AddRange(System.Linq.Enumerable.Repeat(defaultValue, newSize - size));
}
}
That's pretty complicated for your first property drawer, so well done for getting it somewhat working
Prefab Matrix:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Centribo.Common.Extensions;
[System.Serializable]
public class PrefabMatrix {
public GameObject this[int x, int y] {
get {
if (x >= Matrix.Count) return null;
if (y >= Matrix[x].Count) return null;
return Matrix[x][y];
}
set {
if (x >= Matrix.Count) return;
if (y >= Matrix[x].Count) return;
Matrix[x][y] = value;
}
}
public int Width, Height;
public List<List<GameObject>> Matrix; // [col][row]
public void ResizeMatrix() {
Matrix ??= new List<List<GameObject>>();
Matrix.Resize(Width, new List<GameObject>(new GameObject[Height]));
foreach (List<GameObject> column in Matrix) {
column.Resize(Height, null);
}
}
}
PrefabMatrixDrawer:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
namespace MaplePoweredGames {
[CustomPropertyDrawer(typeof(PrefabMatrix))]
public class PrefabMatrixDrawer : PropertyDrawer {
const float GRID_SPACING = 2;
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
PrefabMatrix matrix = fieldInfo.GetValue(property.serializedObject.targetObject) as PrefabMatrix;
label = EditorGUI.BeginProperty(position, label, property);
// EditorGUIUtility.labelWidth = 48f;
Rect contentRect = EditorGUI.PrefixLabel(position, label);
EditorGUI.indentLevel = 0;
// Width/Height control:
float fullContentHeight = contentRect.height;
float fullContentWidth = contentRect.width;
contentRect.height = EditorGUIUtility.singleLineHeight;
contentRect.width *= 0.5f;
EditorGUIUtility.labelWidth = 48f;
EditorGUI.PropertyField(contentRect, property.FindPropertyRelative(nameof(PrefabMatrix.Width)), new GUIContent("Width"));
contentRect.x += contentRect.width;
EditorGUI.PropertyField(contentRect, property.FindPropertyRelative(nameof(PrefabMatrix.Height)), new GUIContent("Height"));
matrix.ResizeMatrix();
if (matrix.Width == 0 || matrix.Height == 0) return;
contentRect.x = GRID_SPACING;
contentRect.width = EditorGUIUtility.currentViewWidth - (GRID_SPACING * 2);
contentRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
contentRect.height = fullContentHeight - EditorGUIUtility.singleLineHeight - EditorGUIUtility.standardVerticalSpacing;
float cellWidth = (contentRect.width - (GRID_SPACING * (matrix.Width - 1))) / (float) matrix.Width;
float cellHeight = (contentRect.height - (GRID_SPACING * (matrix.Height - 1))) / (float) matrix.Height;
for (int y = 0; y < matrix.Height; y++) {
for (int x = 0; x < matrix.Width; x++) {
float xPos = contentRect.x + (x * (GRID_SPACING + cellWidth));
float yPos = contentRect.y + (y * (GRID_SPACING + cellHeight));
Rect cellRect = new Rect(xPos, yPos, cellWidth, cellHeight);
Object value = EditorGUI.ObjectField(cellRect, matrix[x, y], typeof(GameObject), false);
matrix[x, y] = value as GameObject;
}
}
EditorGUI.EndProperty();
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label) {
PrefabMatrix matrix = fieldInfo.GetValue(property.serializedObject.targetObject) as PrefabMatrix;
if (matrix.Width == 0 || matrix.Height == 0) {
return EditorGUIUtility.singleLineHeight;
} else {
// Could be reduced but this makes it clearer what's going on
return EditorGUIUtility.singleLineHeight + (matrix.Height * EditorGUIUtility.singleLineHeight);
}
}
}
}
Thanks!
So if i set the size of the matrix, it displays correctly, but if i drag a prefab into a slot, it fills the whole row of values for some reason
even more oddly, if i then increase the width to another size:
- if i drag a prefab into the same slot, it will fill that whole row again, except for the empty slots that got added by the width increase
If I had to guess what is happening, it's that somehow the same list instance is being used in more than one row/column
Unity can't serialize a List<List<>> can it?
Or are you not trying to serialize this?
nope, hence needing to write a custom property drawer
But it probably won't save
Have you checked that? Like if you set some of the items, save the scene and then reopen the scene
no i don't think it'll save right now, just been focusing on trying to get the editor working first before i figure out the serialization part
oh i know what it might be
Matrix.Resize(Width, new List<GameObject>(new GameObject[Height]));
they're all going to point to the same thing
Makes sense
If I were to make something like this, I would use a flattened 1D array. It's also best to write property drawers to only use SerializedProperty to interact with the serialized field, which would be easier with a flattened 1D array.
fair, i might need to flatten it to a 1D array
for anyone reading, here was the fix:
public void ResizeMatrix() {
Matrix ??= new List<List<GameObject>>();
Matrix.Resize(Width, null);
for(int i = 0; i < Matrix.Count; i++){
if(Matrix[i] == null){
Matrix[i] = new List<GameObject>();
}
Matrix[i].Resize(Height, null);
}
}
i think this is entirely correct, i'd have to write a custom serializer for the 2D array, would be way easier to just flatten it to a 1D array
Update for anyone following:
Flattening to 1D list makes unity serialize it automagically. Here's the new PrefabMatrix class:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Centribo.Common.Extensions;
[System.Serializable]
public class PrefabMatrix {
public GameObject this[int x, int y] {
get { return FlattenedMatrix[Width * y + x]; }
set { FlattenedMatrix[Width * y + x] = value; }
}
public int Width, Height;
public List<GameObject> FlattenedMatrix;
public void ResizeMatrix() {
FlattenedMatrix ??= new List<GameObject>();
FlattenedMatrix.Resize(Width * Height, null);
}
}
my suggestions for any fixes/additions for anyone looking to use this:
- Add safeguards for index out of bounds on the getter/setter
- Make resizing the matrix make sure elements are in their correct positions in the 2D matrix once resized
some more context for the curious: It actually throws a GUIExitException (or something like that) which is then caught by the GUI event manager, so it cancels the rest of that event cycle. Since events happen often, there's no detectable effect to doing this in-editor. It's useful if a change made within IMGUI would put it into an invalid state
is there a way to customize InitializeOnLoad? InitializeOnLoad is run on project startup, domain reload, script compilation, ....
i would like to only run the code when opening the project and creating a new script (and optionally when closing the project)
so is there a way to check for the current editor state or any specific api i could use for this?
Prolly you're looking for sessionState
👍 looks promising
I want to set the color of some gui in a property drawer based on a non serialized property
public class WeightedObject<T>
{
float lastPingTime;
public float LastPingTime => lastPingTime
public void Ping() { lastPingTime = Time.time; }
}
This is all good.
However I'm not sure how I can get the actual value so as I can check for the LastPingTime value in my custom property drawer.
The actual property drawer is a generic type, so usual casting is not working.
[CustomPropertyDrawer(typeof(WeightedObject<>), true)]
public class WeightedObjectPropertyDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
var value = //How to get the actual value?
if (Time.time - value.LastPingTime > 1) { Debug.Log("Was pinged within the last second."); }
}
}
Any ideas?
I really dont want to serialize the ping
You can theoretically use the fieldInfo property to get the value but t's a bit of a pain
You need to use reflection
@gloomy chasm has some utilities here https://github.com/MechWarrior99/Bewildered-Core/blob/main/Editor/Extentions/SerializedPropertyValueExtensions.cs#L160
I have created an unity editor tool to speed up the work flow which I am going share with other users. I don't want them to edit code so I am trying to create dll library of the code using visual studio.
I have added all my script and unityengine.dll, unityedtior.dll references to the visual studio. Since the tool is using components from TextMeshPro. I am unable to create it as this requires reference of tmpro's namespace. How can I add reference in my dll for tmpro as there is no .dll file for it?
I thought of creating .dll of tmpro or add scripts to visual studio form package folder to get around with it but I am unsure if this will workor not.
@waxen sandal @slim zinc
I tried reflection, but came across some issues specific to using the generic type
I will try again and show any specific block!
Also will check out the utilities first in case that solves things
var targetObject = property.GetValue();
var field = targetObject.GetType().GetProperty("LastPing");
var lastPing = field.GetValue(targetObject);
Debug.Log(lastPing);
Using @gloomy chasm s extensions I was able to do it!
Thanks!
Works great!
Looks super cool @astral shadow
#if UNITY_EDITOR
[CustomEditor(typeof (CharacterBehaviour)), InitializeOnLoadAttribute]
public class CharacterBehaviourEditor : Editor {
CharacterBehaviour customInspectorVariable;
SerializedObject customInspector;
private void Awake() {
customInspectorVariable = (CharacterBehaviour) customInspectorVariable;
customInspector = new SerializedObject (customInspectorVariable);
}
public override void OnInspectorGUI() {
customInspector.Update();
EditorGUILayout.Space();
GUILayout.Label("Character Behaviour", new GUIStyle(GUI.skin.label) { alignment = TextAnchor.MiddleCenter, fontStyle = FontStyle.Bold, fontSize = 16 });
EditorGUILayout.Space();
}
}
#endif
``` `NullReferenceException: Object reference not set to an instance of an object` for the line where `customInspector.Update();` is, but I am setting it in Awake so why does it not work?
try to explain what you are trying to do
just make a custom inspector and display "Character Behaviour" in it
why do you need a custom inspector for that?
because "Header" does not have a way to center it and make it look like a title
It's a lot of work for something non essential, but here are a couple things wrong with your code:
- You dont need the '#if Unity_Editor' and '#endif', they are used for something different. Awake() won't be called on Editor scripts. OnInspectorGUI() is called every time you want to display a 'CharacterBehaviour' in the Inspector, so use that as your Awake substitute.
And again, this is so much work it's not worth it. You need to make a label for every variable you want to display. If you want to add a new variable to your CharacterBehaviour you also have to go into this script and add a new Label.
@celest pilot
The property or indexer 'CharacterBehaviour.CanPlayerMove' cannot be used in this context because the set accessor is inaccessible
also make your your CharacterBehaviourEditor script is a seperate File and in a folder called 'Editor'
it's alright
CanPlayerMove getter is private, use the field name, I assume canPlayerMove
#if UNITY_EDITOR
[CustomEditor(typeof (CharacterBehaviour)), InitializeOnLoadAttribute]
public class CharacterBehaviourEditor : Editor {
string Version = "v0.1.0b";
CharacterBehaviour characterBehaviour;
SerializedObject customInspector;
SerializedProperty CanPlayerMove;
void OnEnable() {
characterBehaviour = (CharacterBehaviour) target;
customInspector = new SerializedObject(characterBehaviour);
CanPlayerMove = customInspector.FindProperty("CanPlayerMove");
}
public override void OnInspectorGUI() {
customInspector.Update();
EditorGUILayout.LabelField("", GUI.skin.horizontalSlider);
EditorGUILayout.Space();
GUILayout.Label("Character Controller", new GUIStyle(GUI.skin.label) { alignment = TextAnchor.MiddleCenter, fontStyle = FontStyle.Bold, fontSize = 16 });
GUILayout.Label("Version: " + Version, new GUIStyle(GUI.skin.label) { alignment = TextAnchor.MiddleCenter });
EditorGUILayout.Space();
EditorGUILayout.LabelField("", GUI.skin.horizontalSlider);
GUILayout.Label("Movement Flags", new GUIStyle(GUI.skin.label) { alignment = TextAnchor.MiddleCenter, fontStyle = FontStyle.Bold, fontSize = 13 }, GUILayout.ExpandWidth(true));
characterBehaviour.CanPlayerMove =
EditorGUILayout.ToggleLeft(new GUIContent("Can Player Move", "Determines whether the player can move around."), characterBehaviour.CanPlayerMove);
}
}
#endif
it's serialized though?
wait don't tell me I have to make everything public
that's CanPlayMove
could you explain what exactly do I have to change in order to make it work?
Hang on, I misread a bit
uhh sure
Okay, so instead of having all your variables public you instead use the serialized property system. I will use your [SerializeField] private Camera Camera; as an example since it doesn't have any public getter.
So for a bare minimum custom Editor what you need is this: ```cs
[CustomEditor(typeof (CharacterBehaviour))]
public class CharacterBehaviourEditor : Editor {
SerializedProperty cameraProperty;
void OnEnable() {
cameraProperty = serializedObject.FindProperty("Camera");
}
public override void OnInspectorGUI() {
serializedObject.Update();
EditorGUILayout.PropertyField(cameraProperty);
serializedObject.ApplyModifiedProperties ();
}
}
note how I grab the property through FindProperty and supply the name of the variable. Then draw it using PropertyField
Also note the Update and ApplyModifiedProperties happening first and last, respectively. Which is required to support undo etc
what is serializedObject? I don't see it declared anywhere
It's inherited since it's an Editor
It represents the CharacterBehaviour (because of the attribute) of whatever you current have shown in an inspector
So unless you don't need a method reference or similar you can just straight up use FindProperty
public override void OnInspectorGUI() {
customInspector.Update();
EditorGUILayout.LabelField("", GUI.skin.horizontalSlider);
EditorGUILayout.Space();
GUILayout.Label("Character Controller", new GUIStyle(GUI.skin.label) { alignment = TextAnchor.MiddleCenter, fontStyle = FontStyle.Bold, fontSize = 16 });
GUILayout.Label("Version: " + Version, new GUIStyle(GUI.skin.label) { alignment = TextAnchor.MiddleCenter });
EditorGUILayout.Space();
EditorGUILayout.LabelField("", GUI.skin.horizontalSlider);
GUILayout.Label("Movement Flags", new GUIStyle(GUI.skin.label) { alignment = TextAnchor.MiddleCenter, fontStyle = FontStyle.Bold, fontSize = 13 }, GUILayout.ExpandWidth(true));
characterBehaviour.CanPlayerMove =
EditorGUILayout.PropertyField(new GUIContent("Can Player Move", "Determines whether the player can move around."), characterBehaviour.CanPlayerMove);
customInspector.ApplyModifiedProperties();
}
``` I have no idea what this error means ` error CS1529: A using clause must precede all other elements defined in the namespace except extern alias declarations
`
that's informative
I see
I fixed it by doing this, but now I got 3 more errors popping up
Is your Editor part of a Editor folder?
You have to put it in that folder unless you want to deal with tons of #if
I'm fine with that
could you tell me how to fix these errors?
The property or indexer 'CharacterBehaviour.CanPlayerMove' cannot be used in this context because the set accessor is inaccessibleArgument 1: cannot convert from 'UnityEngine.GUIContent' to 'UnityEditor.SerializedProperty'Argument 2: cannot convert from 'bool' to 'UnityEngine.GUILayoutOption'
2 and 3 is probably just wrong argument on whatever function it is. As for 1 I need to see code, but you're trying to set the value of a Property that doesn't have a set{} implemented
I think I fixed it... but
#if UNITY_EDITOR
[CustomEditor(typeof (CharacterBehaviour)), InitializeOnLoadAttribute]
public class CharacterBehaviourEditor : Editor {
string Version = "v0.1.0b";
CharacterBehaviour characterBehaviour;
SerializedObject customInspector;
SerializedProperty CanPlayerMove;
void OnEnable() {
characterBehaviour = (CharacterBehaviour) target;
customInspector = new SerializedObject(characterBehaviour);
CanPlayerMove = customInspector.FindProperty("CanPlayerMove");
}
public override void OnInspectorGUI() {
customInspector.Update();
EditorGUILayout.LabelField("", GUI.skin.horizontalSlider);
EditorGUILayout.Space();
GUILayout.Label("Character Controller", new GUIStyle(GUI.skin.label) { alignment = TextAnchor.MiddleCenter, fontStyle = FontStyle.Bold, fontSize = 16 });
GUILayout.Label("Version: " + Version, new GUIStyle(GUI.skin.label) { alignment = TextAnchor.MiddleCenter });
EditorGUILayout.Space();
EditorGUILayout.LabelField("", GUI.skin.horizontalSlider);
GUILayout.Label("Movement Flags", new GUIStyle(GUI.skin.label) { alignment = TextAnchor.MiddleCenter, fontStyle = FontStyle.Bold, fontSize = 13 }, GUILayout.ExpandWidth(true));
EditorGUILayout.ToggleLeft(new GUIContent("Can Player Move", "Determines whether the player can move around."), EditorGUILayout.PropertyField(CanPlayerMove));
customInspector.ApplyModifiedProperties();
}
}
#endif
NullReferenceException: Object reference not set to an instance of an objectI'm getting this again
Remove InitializeOnLoadAttribute I don't see why you need it
Probably what's causing issues
let me try that
https://docs.unity3d.com/ScriptReference/Editor.html
You should really check the manual on editor. No need to make your own SerializedObject for example.
which file and line?
also I just realised something
do you know how auto implemented properties work?
I don't think so
UnityEditor.EditorGUILayout.IsChildrenIncluded (UnityEditor.SerializedProperty prop) (at <4cbd678da9d34d10b88d29af4998c9e0>:0)
UnityEditor.EditorGUILayout.PropertyField (UnityEditor.SerializedProperty property, UnityEngine.GUILayoutOption[] options) (at <4cbd678da9d34d10b88d29af4998c9e0>:0)
CharacterBehaviourEditor.OnInspectorGUI () (at Assets/Scripts/Mechanim/Movement/CharacterBehaviour.cs:183)```
full error
EditorGUILayout.ToggleLeft(new GUIContent("Can Player Move", "Determines whether the player can move around."), EditorGUILayout.PropertyField(CanPlayerMove));
this line specifically
Yeah okay, so whenever you use any form of this:
public int MyThing {get; set} C# will automatically create a field for you. Meaning that it will expand that to ```cs
public int MyThing
{
get { return myThing; }
set { myThing = value; }
}
private int myThing;
Now the problem here is that the name of the private field `myThing` isn't actually that. It will actually be something like `private int <MyThing>k__BackingField`
And since Unity serializes field by the name, that's what will be serialized. So your FindProperty will have to look for that name instead.
This is only an issue since you specified `[field: SerializeField]` on your property
https://docs.unity3d.com/ScriptReference/EditorGUILayout.ToggleLeft.html
How is PropertyField a right parameter to that?
removing that didn't fix it either
then how else do I specify which property to modify?
You cant, if you specify ToggleLeft.
If you just do PropertyField then it does work
If you want to do toggleleft, then do prop.boolvalue = toggleleft()
but I need that specific button..
Yeah so if you remove it it will not longer serialize, so it won't exist at all. This is one of the reasons you ideally shouldn't use C# Properties all that much in anything that needs editor support in Unity. So either create your own private backing field or skip the property
what is prop and what is boolvalue?
You should read through https://docs.unity3d.com/ScriptReference/Editor.html
then what do I make of it?
becaue what you're saying makes me think that it won't work at all
SerializeProperty
Also make sure you're firmly understanding https://docs.unity3d.com/Manual/script-Serialization.html
Can you confirm that your CanPlayerMove serializedproperty is found and works?
yes
Then this properties is not relevant right @vapid prism ?
If he finds the Serializedproperty, its not the backing field
EditorGUILayout.PropertyField(CanPlayerMove) doing just that should work, yes?
if the serialized property does work of course
Yes. But if you want toggleleft, you need to set the boolValue of your SerializedProperty
It's possible it's been fixed and is now supported, but I am not sure on what version in that case. I'm doing on a test on 2020.3
could you write how exactly that would work with my property? I'm unsure of what you're trying to show me here
I cant, you can search the manual for SerializedProperty though
it gives me NullReferenceException: Object reference not set to an instance of an object still with doing just EditorGUILayout.PropertyField(CanPlayerMove); :/
this is all CanPlayerMove is atm public bool CanPlayerMove { get; private set; } = true;
I removed serialization
Then why are you trying to use a SerializedProperty on it
I could before removing ^
Yes
And after you made it not serializable, you couldnt use a serializeable property on it.
I mean..
whoops that is my bad, let me bring it back and try again
YOu can do:
target.CanPlayerMove = Editor.ToggleLeft(target.CanPlayerMove, etc etc)
If you make the setter accessible. But i dont understand why you would, this value is not stored in any way
still gives me that error... I'm about to give up
What error my friend
null reference NullReferenceException: Object reference not set to an instance of an object
it persists, I have no idea why
did this yes mean that the serialized property was not null?
When you debug.log it, what does it show?
I mean I was able to edit it in unity's inspector while serialized
should I debug it in the editor or not?
or the mono itself
I dont understand what you mean, but whatever suits you
[field: SerializeField] private int TestInteger { get; set; } serializes to <TestInteger>k__BackingField on 2020.3
FindProperty does not find TestInteger but does find <TestInteger>k__BackingField
(imo, once you do serialization, you shouldnt do properties. But thats just my opinion)
So the thing i explained about auto implemented properties is what's currently screwing you over
so you have to do FindProperty("<CanPlayerMove>k__BackingField") if you actually want to use a backing field.
It will be a lot simpler to not use auto properties here
Also you really have to read through and make sure you understand both links I sent earlier:
https://docs.unity3d.com/Manual/script-Serialization.html
https://docs.unity3d.com/ScriptReference/Editor.html
If you don't editor coding is going to be hell
I'm using 2021.11.1f
man this is really confusing
I did both
The easiest solution here is what Tijmen was hinting at, do not use properties. Also never use [field: SerializeField] until you're comfortable with auto properties
could you repeat what he said? I didn't quite catch it...
If you want to use C# Properties make sure to type out the full backing field yourself
That way you will have control of that Properties serialization
as an example:
Instead of cs [field:SerializeField] public int MyIntegerProperty {get; private set;} always do```cs
[SerializeField] private int _myIntegerField;
public int MyIntegerProperty
{
get { return _myIntegerField; }
private set { _myIntegerField = value; }
}
then in your custom editor you simply FindProperty("_myIntegerField")
and it will always work
I see, thanks !
say @vapid prism I know this is not a place to ask this but would you be up for testing my game sometime?
Nah, but I sometimes test some stuff that's posted in #502171626805133312 and #archived-works-in-progress so if I come across your project there and I have time maybe I'll try it out. But no guarantees
I had a moderator here tell me that I'm not able to post download links nor links to devlogs in #archived-works-in-progress
You're also not allowed to post off topic in these channels.
You can't post random download links, obviously. We already have enough bots scamming people that way.
I know, and I won't do it since I don't wanna get muted again
You can, of course, use itch to share you game.
would a link to an itch.io page be okay?
I'm referring to this.
Yes
great thanks
You can still do it with an auto property, the name is just mangled: FindProperty("<MyIntegerProperty>k__BackingField")
Easy enough to make a FindAutoProperty extension method
Alternatively the method can do a normal FindProperty, and if that returns null, attempt to find <PropertyName>k__BackingField
If they just wanted a modified header, they should have just made a property decorator, not a whole editor
uhoh i've been brought to the dark side
As I was saying you could probably have an easy solution by serializing the array of objects
objects being what a class or struct
So something like:
[Serializable]
public class MyClass {
public Sprite sprite;
public Sprite[] replacements;
}
// then, in your script body
public MyClass[] sprites;
This will appear as a list in the editor
unity's having a fit about [Serializable] seems to think it doesn't exist
👍
hello i have a problem can anyone help please?
i made an editor window and cant seem to find how to only allow behavior when clicking inside the green area (Rect)
i tried making a button but it didnt work.
currently my code detects a mouse click anywhere in the window which is not what i want
This is my current Code
if (Event.current.type == EventType.MouseDrag)
{
if (Event.current.button == 0 && insed)
{
TimelineOffset += Event.current.delta.x;
GUI.changed = true;
}
}
if (Event.current.type == EventType.ScrollWheel)
{
if (Event.current.button == 0 && insed)
{
TimelineZoom -= Event.current.delta.y * TimelineZoomSpeeds;
TimelineZoom = Mathf.Min(0, TimelineZoom);
//Debug.Log(Event.current.delta);
GUI.changed = true;
}
}
timelineRect.Contains(Event.current.mousePosition)
@gloomy chasm dude thank you so much :))))))
Since that is one of the main focuses of this channel, I would guess so haha. 😛
There are some pinned messages in this channel for how to do it and a quick google of "How to create a custom editor in Unity" or something should come up with some good results 🙂
ok
I've been looking around online with none seeming to work, what is the correct way to display a GameObject Array in a custom editor?
is there a way to serialize the interface IList ? I'm generating the List<T> on runtime via MakeGenerics see below if my question wasn't clear (english isn't my 1st language!)
[System.Serializeable]
public class SomeClass
{
IList value;
Type dummy;
Type createList = typeof(List<>);
Type[] typeArgs = Array.Empty<Type>();
public SomeClass(VTypes listType)
{
if(listType != VTypes.None)
{
if(listType == VTypes.String)
typeArgs = new[]{ typeof(string) };
else if(listType == VTypes.Integer)
typeArgs = new[]{ typeof(int) };
//some other types here ...
}
dummy = createList.MakeGenericType(typeArgs);
value = (IList)Activator.CreateInstance(dummy);
}
}```
PropertyField (or ObjectField)
Probably not, Array/List<> are special cases
Unless you do your own ISerializationCallback implementation that is
Sounds promising, I'll look into this
I've tried this and it resulted in a blank window, various ways..
tbf it was probably working for their case (not a gameobject array)
that is, the example I was reading
there are quite a few different ways apparently.. one of which was to "do it manually"
Looks like that should work, ObjectField is the manual one which I wouldn't recommend
Post some actual code and that might say something more
foreach( GameObject go in myGameObjectArray )
{
go = EditorGUILayout.ObjectField( go.name, go, typeof( GameObject ) );
}
so you would not recommend this one, I'm using it (ObjectFiled) for a single object and that did work so.. if all else fails
If you care about resizing of your array or some other built in functionality or arrays, you won't get it by default with that solution
And they can be a pain to implement
(And you have to handle dirtying and undo yourself)
https://forum.unity.com/threads/editorwindow-gameobject-array.509218/
so here where they suggest PropertyField , you see this as working?
unfortunately doesn't in my case.. not sure what I'm doing wrong it could be the fact this editor is for a SO..
Ah that probably explains
You should use this.serializedObject instead of creating your own
afk but I will definitely try this it would be a huge help.. thanks!
Hey yo!
If I want to replace ALL serialized field instances of a certain type on ALL serialized objects in a project with a new serialized field, how should I approach it?
For example, I have 50 different serialized objects (Scene, Prefab, Scriptable Object)
These have TestGradientField serialized properties.
I want to replace all of these with BetterGradientField and convert their serialized properties into the new structure.
Any ideas?
Any chance https://docs.unity3d.com/ScriptReference/Serialization.FormerlySerializedAsAttribute.html works for your case?
If not, I'd write a one time utility to fix it
I.e. Load all scenes, for each scene find either known types with that field or all monobehaviours, fix them up using serializedProperties, save scene then load all scriptableObjects with that field
@waxen sandal
Formerly serialized may not work because I have a much different structure. Like subtypes
I think I have to write migration code
So yeah I'm doing the one time utility right now! Thanks!
Ah yeah, then the one time thing is the best
I've done similar things in the past where I rewrote all monobehaviour references to reference scripts in Unity rather than in a DLL
ISerializationCallback could also work I think but not 100% sure
Ooh! Nice lead!
Will check it out
Is it possible to check if the build setting contains a certain scene in an editor script?
int index = SceneUtility.GetBuildIndexByScenePath("Assets/Scenes/Scene1.unity");// path to your scenes
Hey guys if I want to add images to my custom Editor whats the correct syntax? .GUILayout Image? or something like it?
You can use GUILayout.Label
If you want to set the size then you will need to use GUI.DrawTexture
what's the current method to get json from a server and download zip files from within the a unity editor window ? i am hoping to avoid installing extra libs
HttpClient works, UnityWebRequest should also work
which one has wider support for older versions ?
I've got massive json file, and the smallest it can get is around 12mb it can get to 20+ mb sometimes. Trying to re-serialize it right before building via IPreprocessWithBuildReport.
public class VProcessBuild : IPreprocessBuildWithReport
{
public int callbackOrder { get { return 0; } }
public void OnPreprocessBuild(UnityEditor.Build.Reporting.BuildReport report)
{
VVariableUtils.ReSerializeOnEditorPlayMode(true);
}
}
The serialization would sometimes failed (inconsistently). Tried with a dummy file, around 2mb or less it worked consistently. Any idea why this is happening?
The serialization will ofcourse work as it should if it's NOT before build. Only right before building the scene it would failed inconsistently(by inconsistent here, sometimes it worked)
if that sounds weird let me know, english isn't my 1st language
Show code
public void StartSerializingVPool(VVariablePools variables, string vobjectGuid)
{
json = string.Empty;
string fileName = "VelvieR-" + vobjectGuid;
object obj = variables;
json = JsonConvert.SerializeObject(obj, Formatting.Indented);
File.WriteAllText(path + fileName, json);
}
standard serialization stuff, nothing much tbh
Yeah that's weird, should be working just fine
Also no async going on so it can't be some weird race condition
I guess but I wouldn't know in what
Hi, is there a way to listen to Mouse Input (Mouse4 & Mouse5) in an Editor extension? I used "MenuItem"s and tried to rebind them in my Unity Shortcut Menu, but I can't bind mouse buttons there
how to get target for Property drawers ? the following always returns null for me
var target = ( MyClass ) fieldInfo.GetValue( property.serializedObject.targetObject );
That doesn't work if you're in a collection, or the property is in a serialized structure, because fieldInfo will point to that.
i use this as a single public field , its not a collection
class ClassA : Mono
{
public ClassB field;
}
...
[CustomPropertyDrawer(typeof( ClassB ))]
public class Drawer : PropertyDrawer
{
// ...
}
also tried :
var target_o = property.serializedObject.targetObject;
var target = target_o.GetType().GetField( property.name ).GetValue( target_o ) as ClassB ;
@onyx harness Any chance you can add unity packages to your api versioner? e.g. TMP
Hey,
I made a Unity Engine Toolbar but i am not able to put the prefab inside it.
i made a prefab by making a 3d shape then make a cube then put it in assets then it turned blue then i delete it from scene then add it there but it would still show none
if this is correct then i will give the code
Show code
Don't recreate your SerializedObject and store it in the EditorWindow instead of recreating it
Also, dispose of it when you're done with it
e.g. in the OnDisable
Hello there, there is an extremely low chance of me implementing packages.
These are the reason why Sabresaurus shut the door.
I already made a pre-research about them, and it sounds much more heavier and complexe (I'll explain complex below), since I have to make a parallel system commit-based instead of Unity-version-based.
Due to the potential sheer size, my personal database (100MB) might not have enough space for the packages (UI, TMP, and more?).
Since it is not making me any money, I am not encline to invest some to upgrade the DB. (beside the whole implementation complexity)
The main culprit is: I have to compile packages commit against every Unity versions due to... Preprocessor! 😁
And this single thing makes everything much more complex.
okay what should i do instead of it then?
pardon i am a student i just started unity
GameObject?
@waxen sandal ?
@zenith estuary whenever you're on, wondering if you know anything about the compact int array format unity uses in its meta files. My code breaking skills are dumb and I don't understand what they're doing here
Just looks like a bunch of hex values to me
yeah, I got that far at least 😄
There is a flag for serialized values internally called TransferHex64 too
("Transfer" is generally what Unity calls (de)serialization internally)
hm
I'm assuming it's quite literally just raw binary data in hex
so it's just a bunch of fixed size hex values then
why would that matter for serialization
It's just a more compact way to store it, I imagine
Text compresses well, and there is a lot of repeating data there in sequence
no, I get that the hex is more compact for serialization, I don't understand the part where you care if it's int16 or int32 when serializing it
Whereas if it were an array, it'd be a lot of strings of varying length
That was moreso about why it's storing "raw" data
hm
I just figured that it was purely for compactness & compressability
I imagine that's the case, yeah
anyway, thanks for telling me I'm overthinking it 😄
A bit yeah, Unity used to only support 16bit indices
And thus likely since the engine relied on 16bit, why not also do serialization the same
remind me, that would be ... big endian?
No? endianness is only about bit order
byte order*
Right yeah
So yes, endianness matters here
I'm talking about how the significant digits are on the left
I can never remember which is which (spot the high level programmer)
If the indices are 16-bit, then it would be 1B 00 which would be 6192 in big-endian
or 27 again if still little-endian
both values seem possible, can't know for sure without actually seeing the mesh data lol
I'm going to assume that it's 32 bit since the indices array is int
this is for sprites
yah
I was being lazy and not wanting to do any practical testing to figure this out 😄
also, I cannot believe I never knew about EditorJsonUtility, that thing is seriously magic for editor work
It's a very handy tool when combined with proxy types
yeah, I'm currently building out proxy types for TextureImporter
so I can import newly generated texture files (with sprites attached etc.) in one pass
thus the need to serialize a meta file by hand
How can I create an intfield with 3 ints next to eachother with their own labels? Identical to the position property on transforms
Or use Vector3Int
Is there any extension to show logs as warnings on Rider or VS ?
Hi, how can i access functions like buttons do
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.
Hello, is it possible to have editor only persistent fields per component? Here's a minimal example of what I'm trying to do:
public class BuildArea : MonoBehaviour
{
// This isn't used in the game. It only exists to display
// things in the editor.
public bool editor_draw_details = false;
}
[CustomEditor(typeof(BuildArea))]
public class BuildAreaEditor : Editor
{
[DrawGizmo(GizmoType.NonSelected | GizmoType.Selected)]
static void DrawSceneVisualisation(BuildArea build_area, GizmoType gizmoType)
{
if(build_area.editor_draw_details)
{
// draw more stuff
}
}
}
Is there a better way to achieve this? It would be nice not to have data in the component that isn't necessary during the game's runtime.
I think you can technically wrap them in #if UNITYEDITOR but iirc it throws some warnings sometimes
Also you might still have the serialized data in the build
Thanks for the info. From searching around it seems there isn't a straightforward way to do it. I can leave the data in the MonoBehaviour for now.
Is there a way to make a label field show ellipsis (...) when the text is too long?
Only way is to measure the string and then trim it and add an ellipsis to it
I have an implementation if you want it 🙂
I'd love to, actually, it would make things much easier
I just ripped it out of the codebase that I created it for, so it might require a bit of editing, but should be pretty minor
Alright, thanks a lot!
Sure thing! It was a real pain to do, so happy to save someone else the pain too.
I am facing an issue,
I have included " UnityEditor.EditorTools" namespace, but when trying to use ToolManager class I get error
"the name 'toolmanager' does not exist in the current context"
how to fix this?
Please.. can anyone help?
Hello all, i apologize in advance if this is the wrong channel for this. I'm just diving into custom editors, this editor i made looks "normal" when viewed in the original scene and prefab it lives on. However when manually added to an object it become "squished" or misformatted. Any ideas? Both pictures are same script with same editor script.
Is it an Editor or a PropertyDrawer?
Is there a way to detect Addressable changes in editor and run some code when it happens?
Specifically I'm trying to detect addressables being added/removed from a group.
I guess detecting changes on an .asset file could work too.
IIRC there's a callback somewhere but I forget where
An editor
I have a question: I added a HelpBox (EditorGUILayout.HelpBox) to my custom inspector, but the message text is super small. Can I somehow increase it?
ok so
is there any way
I can publish a scene and all the models used in it
and then load it at runtime?
like, someone can publish a scene to my database and then load it in game
How do I add another editor extension which results in two assembly definition assets correctly?
This one also has its own Editor file aswell as the other one which has its own editor file too
this happens otherwise
What do you mean?
this
This doesn't really help clarify for me what the issue is.
Im not sure how to place them within each other to only use 1 editor and 1 attachment file as having two causes errors during unity build
I'm sorry, can you try explaining the issue again in detail? What exactly are you wanting to do and what is happening that is preventing you from doing it?
I am wanting add and use both TextMesh pro Effect and BrightAnimator which are both Editor extensions. However, upon adding both into the same project they seem to interfere with one another due to there being two files of unity tries to use.
This results in the UnityEditor.Buildplayer and numerous "couldnotbefound" errors. What should I do to have them both work simultaneously without errors?
Do I create a new editor file and only place what was in its editor files and what to do with two Unity Assembly definition assets?
Are you sure the errors are not just because of BrightAnimator ?
It looks to me like the editor scripts are being included in the build which is resulting in the errors.
Does the BrightAnimator/Runtime/Editor folder have a assembly definition in it?
it had occured the other way around when I added textmesh secondary
yes
Is it set to only editor?
its to any platform
There ya have it
The assembly definition overrides the default behavior of putting scripts in any folder called Editor in their own assembly.
So if you have a assembly definition for only editor scripts, you need to set it as such
this seems to have removed most of its files and given this message, its also blanked the two scripts and attachments left
over thousand errors
re import i go
could you maybe look into the extension for me? it could be very well that something is wrong with it on its own but am unsure
@ivory hearth I took a quick peek at the githib and your package is all messed up. It looks fine on github
ill try getting it directly from github as previously I got it from his unity package maybe some patch fix