#↕️┃editor-extensions
1 messages · Page 106 of 1
ok
like so?
[MenuItem("Window/VRtex Studios")]
public static void ShowWindow()
{
varLoaderEditor window = GetWindow<varLoaderEditor>("VRtex Studios");
window.Show();
}
yes check the documentation for EditorWindow
but the data won't get serialized (saved) like it does with an Editor script
if you close and open the EditorWindow the data will reset to the default values
that's probably fine for some situations, it depends on what you're doing exactly
ahhh i see yeah it will be open the entire time of use unless someone accidentally closes it
there is a save mid way though aswell but this was really annoying me haha
thank you very much
why do all my sliders slide together?
probably because they are all using the same field
Hey does anyone know why some scriptable objects are changing InstanceID? Like I'm trying to save UIElement.ObjectFields referencing a scriptable object as Json, but when I reload the project after a restart or something, their instance IDs have changed and loading them via the old value in the JSON leads to wrong objects being loaded
InstanceIds aren't persistent and are reliant on what order assets are loaded in
You can use GUIDs instead perhaps
yeah so I guess my system can't work this way, I took another approach and I now save my stuff in nested scriptable objects (that have correct references)
thanks for the help tho
i had the script working just fine and turned on my pc today and now am getting this error
using System;
using UnityEngine;
namespace VRtexStudios
{
public class VarLoader : MonoBehaviour
{
public GameObject avatar;
public int BlendShapes()
{
SkinnedMeshRenderer mesh = avatar.GetComponent<SkinnedMeshRenderer>();
Mesh currentMesh = mesh.sharedMesh;
return currentMesh.blendShapeCount;
}
public Array getBlendShapeNames ()
{
SkinnedMeshRenderer mesh = avatar.GetComponent<SkinnedMeshRenderer>();
Mesh m = mesh.sharedMesh;
String[] arr = new string[]{};
for (int i= 0; i < m.blendShapeCount; i++)
{
arr[i] = m.GetBlendShapeName(i);
}
return arr;
}
}
}
thats the current main script and i have no clue why its not assigning avatar. any ideas?
ok
i make a slider for each blendshape and need them on seprate fields how do i do that?
i have them as all separately generated names but none move independently
for(int i = 1; i < totalShapes; i++)
{
scale = EditorGUILayout.Slider(Blendshapenames[i],scale, 0, 1);
}
that is how i generate them
what is moves like
That is because they are all setting the variable scale's value
so make a array of floats and assign it to them?
It depends on what you want
each of them need to be customizable and i need to be able to save a current state of them all
Since you have a collection of blend shape names, I assume you are wanting to set the value of the blend shapes
yes
So set the value of the blend shape then... no? If you want to just store the values, then yeah you will need a array/list of floats
my man...
sorry for the @
If ya have a question, ask and someone will answer. If it is about a previous conversation you can either at me or reply to my previous message. But please include the question in the message
i have set up the array and i get no errors whether it be syntax or in unity but i am now unable to slide any of the sliders.
yeah thats why i @ you cause its about the same problem
my bad for not having the question in there
sorry
All good, now you know for the future 🙂
thank you 🙂
Are you defining the array in the class or the method?
class definition method assignment
namespace VRtexStudios
{
[CustomEditor(typeof(varLoader))]
public class varLoaderEditor : Editor
{
public int totalShapes;
public string [] blendShapeNames;
public float [] blendShapeVal; //decleration
private static float scale;
/*
[MenuItem("Window/VRtex Studios")]
public static void ShowWindow()
{
varLoaderEditor window = GetWindow<varLoaderEditor>("VRtex Studios");
window.Show();
}
*/
public override void OnInspectorGUI()
{
varLoader mainWindow = (varLoader)target;
if (GUILayout.Button("Collect Blendshapes"))
{
totalShapes = mainWindow.BlendShapes();
blendShapeNames = mainWindow.getBlendShapeNames();
}
EditorGUILayout.IntField("Blendshapes", totalShapes);
blendShapeVal = new float[totalShapes]; //asignment
for(int i = 1; i < totalShapes; i++)
{
blendShapeVal[i] = EditorGUILayout.Slider(blendShapeNames[i],scale, 0, 1);
}
}
}
}
You are reassigning it each update, that has the same effect as if you defined it in the method
Also note that since you are defining it in the Editor class, the values will not be saved to the component so when you select a different GameObject the values will be lost
hmmmm
so if i define it in the script then use it in the editor would i be able to save the values?
Yes
thank you 🙂
so i have refactored it and all variables so there is no reassigning every update. However it still isnt working
namespace VRtexStudios
{
[CustomEditor(typeof(varLoader))]
public class varLoaderEditor : Editor
{
private static float scale;
public override void OnInspectorGUI()
{
varLoader mainWindow = (varLoader)target;
if (GUILayout.Button("Collect Blendshapes"))
{
mainWindow.Load();
}
EditorGUILayout.IntField("Blendshapes", mainWindow.totalShapes);
for(int i = 1; i < mainWindow.totalShapes; i++)
{
mainWindow.blendShapeVal[i] = EditorGUILayout.Slider(mainWindow.blendShapeNames[i],scale, 0, 1);
}
}
}
}
@unkempt sparrow you are reading the scale value on every the loop
of course it's never gonna change
your scale value is never changing because you are never assigning anything to it
but why are you still using a single float value to represent EVERY value of an array?
change scale for blendShapeVal[i]
interesting i mis understood the documentation
i thought where i had scale was the type of value used on the slider not the value itself
works fine now 🙂
this is the example in the Slider method documentation
scale = EditorGUILayout.Slider(scale, 1, 100);
you need to pay more attention to the docus examples
yeah i looked at that specifically
i guess i do it also was 330 am when i was doing it haha
so makes sense
i need to sleep more running on like 3 hours today...... buuut first prototype it done!
Im running this code to build a library of all the rooms in my game.
I was able to build and run this no problem before, but now im getting errors that AssetDatabase is only do-able in editor.
I dont know why it was building and working before or what changed to make it not, but how do I remove editor namespace dependancy on this code?
How do I build a dictionary of all the rooms in my project if I am not allowed to reference the project?
whats the stack trace?
I am not experienced enough to know what a stack trace is, how can I get you that info?
are you running it in unity?
yes click on one
and then copy paste the code underneath
The build fails because I am trying to reference UnityEditor namespace in a build
which you can't do
but I don't know how to build my dictionary without it
why do you need unityeditor namespeace?
#↕️┃editor-extensions message
see the highlighted references to AssetDatabase, those
I need a way to do that same functionality, without using AssetDatabase
lemme look at something real quick
thank you
You can't serialize a Dictionary so I can't save it, I have to build it at runtime (to the best of my knowledge)
do you have to use assetdatabase?
or could you make your own dictonary and populate it with the information you need?
nvm
assetdata base is thing you should use for this. i think
aight yeah if you make the script in the "Editor" folder and then use assetdatabase you should be fine just have it edit the script it should relate to.
this script must be in a folder called "Editor"
You arent understanding
I need this dictionary at runtime, in my game, for my game to work
Dictionaries cannot be serialized
its fine though I thought about it, I can separate the code to build the list and the dictionary and pre-build only the list during Build I think
you can declare the dictionary in the main script and then use them in the editor which will allow you to save them and have them at runtime
@idle tree for a simple approach most people just store two lists in a ScriptableObject and then at runtime they make a dictionary from the lists
you could also just implement your own serializable dictionary
was i close?
nope, bunp's problem was because they are trying to read data from an asset at runtime in the build
they need to predefine the data somewhere (ie: in s ScriptableObject in the Resources folder) to be able to load it at runtime
this whole conversation should have been in other channels like #archived-code-general
this channel is for editor extensions and such
ok would they be able to do that if they defined it in there script first and then used a editor to allow for the assetdatabase?
check me on this but is this channel for questions regarding custom editors and extensions?
yes, any topic related to making editor tools and extending Unity's functionality
ok cool just making sure
when in doubt, check #🔎┃find-a-channel for a list of all the channels
it's important to keep questions and conversations on the topic of the channel
will do
yeah i feel like i have done a alright job with that so far or would you say i need to improve a significant amount?
yes, you need to make sure to share appropriate context when asking for help. Like when asking about a console error, if you don't provide any code people can't try to help you
put the effort in your questions so other people can help you better 🙂
very true
ill do better this is a very big project and i have a decent amount left to do so i will for sure be asking many more questions and hopefully answering questions better aswell.
and it's ok to ask in #💻┃code-beginner and #archived-code-general if you are having problems with basic code stuff, even if they are in an Editor script 👍
Dictionaries have been serializable for at least 5 years, but you have to use a special callback to do it EDIT: as MedLed linked to - but most of us have by now made this into re-usable code so we don't have to think about it any more) (and there's a wider automated solution Coming Real Soon (tm))
Hey there, maybe someone can point me in the right direction.
I have custom timeline track and clips that allow me to loop within a defined section of a timeline while a script is running. I've made it so it's possible to set the start time of the loop with an offset relative to the clip's start time (checkout the screenshot), and everything works quite well.
However at the present time there is no visual information that indicate when the loop will start on the timeline itself, the only information you have is the time offset, in seconds, that you can change manually in the clip's inspector.
Is it possible to add an icon, like an open square bracket for instance, on top of the custom clip's rectangle, in order to indicate when the loop begins? I know I can change the looks of the inspector, but I don't know if I can mess around with the looks of the timeline.
Hi!
I'm searching for some kind of addon to make my nodal custom window. In the past, i tried making my own nodes, but... It didn't really work out 💀
I'd like to know if you guys know any extensions or package that allow me to create new nodes easily, i've got "XNodes" but idrk what it's worth
In this tutorial we are going to create a SUPER SIMPLE node based dialogue system with the ability to branch story lines. We gonna create the main setup and make our graph entirely functional in this episode.
In the next episode, we gonna add save&load system for nodes and game play implementation.
This tutorial will help you to build your bran...
Never mind that, I just learned of the existence of ClipEditor which should be able to do what I'm looking for.
this might be kind of a dumb question, but do I need to call SerializedObject.ApplyModifiedProperties if I'm using an EditorGUI.PropertyScope?
iirc there's no need for it, but asking just in case
can't find a concrete answer online
Yeah you do
But most often you do it in a property drawer which handles it for you iirc
(looking at the source)
You you do, all it is is
EditorGUI.BeingProperyty(..);
// your code...
EditorGUI.EndProperty();
(I mean that literally all it is)
ah right, that may be it
i'm making a sort of generic property drawer base class and neither it nor the derived classes call ApplyModifiedProperties
so I was kind of freaking out about the values retaining the data correctly
yeah just tested on an EditorWindow, you do indeed need to apply the modifications
That is how the PropertyDrawer works, you handle applying in whatever draws the properties in the end
Yeah it makes more sense now. I had only scratched the surface on PropertyDrawers/PropertyAttributes with the basic stuff
i'm trying to make more complete implementations now so I was going over everything to see how it worked
for example I was trying to do SerializedObject.Update() in my drawer which reset the values of all the previous fields to the default value
😅 silly me
Is it possible to mark a serialized object properties as modified?
Just curios, is there a way to access the "Select Object" window that pops up when your assigning object fields by the inspector? Im wondering if its possible to make it show up on a button press or something that isnt specifically a ObjectField
Sure is. iirc it is something like EditorGUIUtly.ShowObjectPicker(..)
What do you mean?
Oh aawesome, thanks Mech
I'm calling a method with an InspectorGUI button on a MonoBehaviour script. That method reads in some values from a file on and modifies some of the properties. The scene is not showing as modified even though the properties are updated.
And if I reload the scene the changes are gone
You should use SerializedProperty and SerializedObject to modify properties in the editor (more info in pinned messages in this channel)
I'm not modifying the properties with SerializedProperty, because I wanted the method to work at runtime and in Editor, but I'm guessing that's not possible
What you would do is basically recreate the method in the editor script using SerializedProperty. That is the 'right' (and heavily recommended) way to do it. The other option is to use EditorUtility.SetDirty(obj).
However that will not support Undo or prefab overrides
Thanks I figured that was the case. Thanks for the info!
hmmmm i'm struggling a little bit with PropertyDrawer heights
i'm getting different results depending on if the Inspector is docked or not
is there a way of getting the EditorWindow in which the current PropertyDrawer is being drawn?
i need to know in what window its being drawn to add an extra pixel to get the correct value
it's literally just a +1 when the Inspector window is floating not docked to anything
it's so annoying... UNITY WHY YOU DO THIS TO ME... 😓
Can you show?
sorry not at my computer right now, i can share all the code tomorrow and provide better gifs 😅
Basically i have a property drawer that draws a custom HelpBox that wraps the text.
At some point there's a discrepancy of 1 pixel between the actual WIDTH of the HelpBox and thw width of the inspector,
which makes the box wrap the text but the height gotten from the property drawer doesnt match
The weird bug is that it only happens when the inspector is docked, when it's floating the width and height match perfectly
I had shared that gif before
I dont know if this is caused by me using a custom GUIStyle with non standard padding values ( i've experienced situations where having odd padding values instead of even values would cause situations like this)
Or maybe it's a floating point inaccuracy issue
Or some other obscure internal bug with Unity
In that gif there was actual height errors caused by me setting incorrect values. But now i fixed everything, and it works correctly, except for that rogue pixel 😅
yo
does anyone know why when i parent an object to a bone it changes the anchor point of the bone?
@gloomy chasm here's the gif with the problem
as you can see, as soon as I undock the window, there's no issue
welcome to the world of IMGUI
🙃
where pain is pain and pain pain pain
Odd...
Just an idea, and could be wrong, but you could try rounding the x and width after getting them and before using them just incase something is happening there
done that already 😅
i was printing non-rounded float values, but rounding them didn't fix it
Can you share the code that calculates the property height?
yep, one sec
private static float Spacing => EditorGUIUtility.standardVerticalSpacing;
private static float InspectorWidth => EditorGUIUtility.currentViewWidth - EditorStyles.inspectorDefaultMargins.padding.horizontal;
//private static float InspectorWidth => EditorGUIUtility.currentViewWidth - EditorStyles.inspectorDefaultMargins.padding.horizontal - 1;
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
if (ValidTargetType == false)
{
Vector2 errorBoxSize = GetErrorBoxSize(_errorContent);
return Mathf.Round(errorBoxSize.y) + Spacing;
}
return base.GetPropertyHeight(property, label);
}
public static Vector2 GetErrorBoxSize(GUIContent errorContent)
{
float width = InspectorWidth - EditorGUIUtility.labelWidth - Spacing;
float height = ErrorBoxStyle.CalcHeight(errorContent, width);
return new Vector2(width, height);
}
private static void SetUpStyle()
{
ErrorBoxStyle = new GUIStyle(EditorStyles.helpBox);
ErrorBoxStyle.fontSize = 12;
ErrorBoxStyle.padding = new RectOffset(24, 5, 1, 2);
}
here's all the relevant code
i'm also suspicious of EditorGUIUtility.currentViewWidth
When docked
- The point where the wrapping happens visually is at a EditorGUIUtility.currentViewWidth of 339
- The point where the wrapping actually triggers the correct value is at 337
When not docked
-Both happen at 337 in sync
Okay
So it is probably a less than ideal solution
but you could get the rect in OnGUI and use its width instead
@gloomy chasm that might work. I wanted to avoid having to workarounds like that
but seems undocking the window doesn't affect the position Rect
while it offsets the EditorGUIUtility.currentViewWidth by 2 pixels
i guess Unity just adds 1 extra pixel on each side of the EditorWindow when it's undocked for some god damn reason
Its the outline of the window
hmmm i do this
public static Rect DrawGenericError(Rect position, GUIContent labelContent, GUIContent errorContent, bool disableLabel = false)
{
// Calculate rects
Rect labelRect = CalculateErrorLabelRect(position);
Rect errorBoxRect = CalculateErrorBoxRect(position, errorContent);
Rect errorIconRect = CalculateErrorIconRect(position);
// Draw label
using (new EditorGUI.DisabledScope(disableLabel))
{
EditorGUI.LabelField(labelRect, labelContent);
}
// Draw error help box
if (Event.current.type == EventType.Repaint)
{
ErrorBoxStyle.Draw(errorBoxRect, errorContent, false, false, false, false);
}
// Draw error icon
GUI.DrawTexture(errorIconRect, PropertyDrawerGlobalCache.ErrorIcon);
return errorBoxRect;
}
private static Rect CalculateErrorLabelRect(Rect position)
{
Rect result = new Rect(position);
result.x = position.x;
result.width = EditorGUIUtility.labelWidth;
result.height = EditorGUIUtility.singleLineHeight;
return result;
}
private static Rect CalculateErrorBoxRect(Rect position, GUIContent errorContent)
{
Rect result = new Rect(position);
result.x = position.x + EditorGUIUtility.labelWidth + Spacing;
result.width = position.width - result.x + EditorStyles.inspectorDefaultMargins.padding.left;
result.height = PropertyDrawerErrors.ErrorBoxStyle.CalcHeight(errorContent, result.width);
return result;
}
private static Rect CalculateErrorIconRect(Rect position)
{
Rect result = new Rect(position);
result.x = position.x + EditorGUIUtility.labelWidth + Spacing + PropertyDrawerErrors.ErrorIconLeftPadding;
result.y += 2;
result.width = PropertyDrawerErrors.ErrorIconSize;
result.height = PropertyDrawerErrors.ErrorIconSize;
return result;
}
so in the CalculateErrorBoxRect()
i get the width like:
result.width = position.width - result.x + EditorStyles.inspectorDefaultMargins.padding.left;
and in the method that gets the height for GetPropertyHeight() i do
float width = EditorGUIUtility.currentViewWidth - EditorStyles.inspectorDefaultMargins.padding.horizontal- EditorGUIUtility.labelWidth - Spacing;
i guess that's causing the discrepancy
yeah, i mean... one would guess using EditorGUIUtility.currentViewWidth for an editor window
would give a consistent, reliable value that I can use for all of my IMGUI needs!
HOW NAIVE OF ME 🙃
Well you shouldn't really be using that anyway
Because if the property is drawn in an editor window it could be very in consistent for what you actually want
hmmm yeah
what approach do you recommend for this sort of thing
just caching the Rect position from the OnGUI method and using it for the GetPropertyHeight method?
I think so
it seemed like a non-ideal approach since the drawer gets first the height and then draws the OnGUI
but eh, i guess it'll do
Yeah, it isn't ideal
My only concern really is that I don't remember how EditorGUI.GetPropertyHeight(..) works
Because if that calls the GetPropertyHeight method of the property drawer...
yes it does iirc
there's an internal method to get the height
i've used it a couple times
i used it for a PropertyDrawer where I needed to have some custom logic on GetPropertyHeight but then I actually needed to get the "raw" height in the OnGUI method
object nullHandler = ScriptAttributeUtilityAccessor.SharedNullHandler;
PropertyHandlerAccessor accessor = new PropertyHandlerAccessor(nullHandler);
propertyHeight = accessor.GetHeight(property, GUIContent.none, true);
by using an "empty" PropertyHandler
Really what it comes down to is that the property drawer system wasn't made for this sort of thing
yeah i've seen a couple of implementation for this sort of complex PropertyDrawers and they just end up overriding the entire Editor so they can handle things more comfortable
NaughtyAttributes does that iirc
Yeah
it is the only choice for things like the Button attribute
I once helped a guy with some NaughtyAttribute stuff and that is when I learned that it was extremely inefficient
what's inefficient? overriding the Editor or doing it the "normal" way?
I just mean NaughtyAttribute's code. For example it gets every class that inherits from x every single OnInspectorGUI instead of caching it
oh yeah
Naughtyattributes also likes to break your inspector under certain conditions
I think that case may be that they simply don't understand how IEnumerable works though (in the case of the reflection example)
yeh maybe
one time NaughtyAttributes locked my entire project because I had deleted a script and there was still fields of that type
so their Editor override was freaking out and not rendering anything
But overall I found the code kind of messy
there's also StackableDecorators, i digged around through their code and I think they do all of their stuff in actual PropertyDrawers and not overriding the Editor
and they do anything NaughtyAttributes can do
When you round a value, make sure you round position & size (not just the size)
ah, thanks for the reminder lol
That can't be true if they have the Button attribute afaik
i can't remember exactly, it's been a while since i've look at their code
well I was about to try implementing a PropertyAttribute for adding a button to a method
so I guess I'll find out the hard way lmao
Might be difficult
lol RIP
Actually, I wonder if you can inherit from it and use AttributeTargets.Method
👍
nah it doesn't call the OnGUI method
You can always add the name of the method as an argument of the Decorator
But you will end up with static only
@onyx harness yeah but if you use a PropertyAttribute in a method the drawer doesn't call any of the methods
it just becomes useless
i wonder if there's some internal callback to hook up to Editor GUI updates
similar to EditorApplication.projectWindowItemOnGUI
You can't put a PropertyAttribute on a method O_o
Does anyone have an idea on how to automatically uncollapse the hierarchy when starting the game? I hate it that Unity automatically collapses the hierarchy upon entering play mode.
it doesn't happen for me
are you sure you don't have some tool or something that collapses your hierarchy
test if an empty project does the same thing
It's a multiplayer game with an extra scene for loading all the background stuff and I think once there is a dontdestroyonload in it, it automatically collapses everything
Hello. I have 2 monitors. In monitor 1 I keep my visual studio in other the Unity editor. I would like that any time I press save in Visual Studio the editor compiles the changed scripts. Unfortunately its only happening when I move my cursor over the editor and focus it. This is very ineffective and I wonder if it can be tuned as I describe?
There is a discussion here. https://www.reddit.com/r/Unity3D/comments/e9qwe3/recompile_in_background_when_saving_script_in/
1 vote and 7 comments so far on Reddit
I believe it would be possible to write a an editor script that does this, but you'd probably need to set up a file watcher and force a reimport when any file changes.
There may be an option for this I'm not aware of.
Not only is that method broken (has been broken for YEARS) but the latest bug I submitted (few monhts ago IIRC) on it got closed as 'FIXED', and when I asked for more info was told: 'we're changing the documentation in future releases to state that it doesn't work'. LMAO. TL;DR: Unity's trying to kill that API call, don't even try to use it.
I restarted Unity (did not change anything) and now it works as I want.
Like it read my mind orsmth
Use Rider instead, if it still doesn't work
What is Rider?
A better ide than vs
Hi, is it possible to change docked editorwindow width from the script?
Do you mean undock/dock a window?
actually I want to change it without undocking.. Right now if I set EditorWindow position it automatically undocks. I want to prevent it.
I need to set the exact width of the docked window, just as I do it in UI
Ah, you will need to use quite a bit of reflection to do that
trying to hack that right now.. thought maybe somebody already done it 🙂
Why are you trying to set the width in the first place?
well, I need to render my scene view pixel perfect: so that all texels would be perfect squares. I thought maybe snapping the editor window size would be the easiest way to do it 😄
its not a problem for gameview, I can easily control that with camera rect (by adding small line so that all pixels are squares). But in scene view I cant change the camera rect.
well, I can, but it gets overwritten somewhere I think.. has no effect unfortunatly
To be fair, it is a jetbrains* product
is the preview window some kind of scene or "place" i can put arbitrary things for previewing assets, or like if i want a 3d thing there do i need to actually just render it using a camera onto a rendertexture or whatever
an example close to what i'd actually like to do is create a preview for a scriptableobject asset which would display a UI element based on the strings and textures contained/referenced in the scriptableobject
is plasticscm down because it takes 2 minutes for me to preview my game and it gives the error message "the host closed the socket"
i just straight up cant playtest my game because every frame its trying to run this
Hi guys. I took this screenshot from a 3rd party asset and I wonder how I can implement my own buttons like this.
I am experienced on developing editor extensions but I have no idea about how to do this.
Any idea how to start?
It depends, the top right buttons might be able to be done with reflection, otherwise you need to use Harmony. The button on the left could be done with UIToolkit, otherwise again the answer is Harmony. What is the asset?
void ShowButton(Rect r)
for a regular EditorWindow that you make, you can do this to add buttons to the top bar and generic menus to the three dots menu
public class EditorWindowTopBarButtons : EditorWindow, IHasCustomMenu
{
private GUIStyle _lockButtonStyle => "IN LockButton";
private bool _locked = false;
[MenuItem("Test/Top Bar Buttons")]
public static void MakeWindow()
{
EditorWindow.GetWindow<EditorWindowTopBarButtons>();
}
// Add generic menus to the three dots button
void IHasCustomMenu.AddItemsToMenu(GenericMenu menu)
{
menu.AddItem(new GUIContent("Lock"), _locked, FlipLock);
menu.AddItem(new GUIContent("Button"), false, DoButton);
}
// Magic method which Unity detects automatically.
private void ShowButton(Rect position)
{
// Drawing a toggle
_locked = GUI.Toggle(position, _locked, GUIContent.none, _lockButtonStyle);
// Drawing a button
position.x -= position.width;
if (GUI.Button(position, ""))
{
DoButton();
}
}
private void FlipLock()
{
_locked = !_locked;
}
private void DoButton()
{
Debug.Log("Button pressed");
}
}
but the screenshot you shared is probably doing something different
It probably uses exactly ShowButton
but i don't think they are making their own project view from scratch, they are probably just injecting the buttons in some other way
or can you use ShowButton to add to the Unity default windows?
what do you mean by that?
You can overdraw out of the given Rect
ah lol
Try it with a Button or a DrawRect
so you think they're creating a mock editorwindow and using the ShowButton from there?
to add it to the Project browser window?
Oh you are right, I forgot it was in Project window
Well probably injected I would say
yeh that was my guess
maybe you could just gett the total Rect of the Project browser window and draw the buttons on the top right
but i guess they are doing something else since they also inject the star button for the favorites thing on the top left
Oh I thought the star was from recent Unity
So basically.. what I said to start with 😛
The asset seen in my screenshot is this one:
https://assetstore.unity.com/packages/tools/utilities/favorite-assets-198746
Thanks guys for detailed info. I checked what Harmony is. It looks like an interesting library but I won't go to that length (like injecting code to Unity editor) just to be able to add a button to project window. I'll see what I can do with UIToolkit.
@gloomy chasm I developed IMGUI extensions for Unity but I haven't experienced UIToolkit yet. Even if I implement my own window with UIToolkit, how am I supped to inject a button into an existing window? Like querying for the project window in a DOM like object structure?
var windows = Resources.FindAllOfType(projectBrowserType);
foreach(var win in windows)
{
var newButton = new Button(() => Debug.Log("Custom Button") {text = "New Button" };
win.rootVisualElement.Add(newButton);
}
Thank you. I'll check that.
Also, I have this checkbox implemented before with the help of a library called UnityToolbarExtender.
https://github.com/marijnz/unity-toolbar-extender
Now I checked the source code of this library and saw that it's doing its job with reflection and by looking for a VisualElement in a Root object. This root object is in a scriptable object called "UnityEditor.Toolbar" and loaded by Resources.FindObjectsOfTypeAll method. Interesting stuff...
That's the same way you showed in your example. Thank you!
One last question. How would I know the value of projectBrowserType ?
By cleverly searching it
Project is trickier than the rest
as its type name is not following the "normal convention"
UnityEditor.ProjectBrowser is what you want
Awesome. Thank you!
"ProjectBrowser" does not follow the common "Window" suffix
Anyone knows where the gradle external tool settings are located in the source? I find references to IPreferenceWindowExtension and HasExternalApplications but no gradle implementation of that exists
Or what the editorpref is called that lets you use a non bundled gradle?
Foudn it btw, GradleUseEmbedded
Anyone know how you get an object field to show the "Missing (..)" text?
i think there was an internal ObjectContent method that accepted an instance ID as a parameter
and if you passed a non-valid InstanceID it would show that
but can't remember
Turns out you can't. The only option is to just draw the style, oh well I guess that works
you can also pass a destroyed object of the type you want to get the missing text
private void OnEnable()
{
_go = new GameObject();
DestroyImmediate(_go);
}
private void OnGUI()
{
string missingString2 = EditorGUIUtility.ObjectContent(_go, typeof(GameObject)).text;
EditorGUILayout.LabelField($"missingString2: {missingString2}");
}
what's the name of the style to get the "Missing" thing? I'm curious
That seems so much dirty and less performant haha
haha yes indeed 🙃
This is what the Material variant parent field does in 2022
ah they just manually do it
@gloomy chasm ah digging around on my reflection examples found this one
public class EditorGUIUtilityAccessor
{
private static MethodInfo MI_ObjectContent = typeof(EditorGUIUtility).Method("ObjectContent", new Type[] { typeof(Object), typeof(Type), typeof(int) });
public static GUIContent ObjectContent(Object obj, Type type, int instanceID)
{
return (GUIContent)MI_ObjectContent.Invoke(null, new object[] { obj, type, instanceID });
}
}
GUIContent missingString = EditorGUIUtilityAccessor.ObjectContent(null, typeof(Material), -1);
EditorGUILayout.LabelField(missingString);
GUIContent noneString = EditorGUIUtilityAccessor.ObjectContent(null, typeof(Material), 0);
EditorGUILayout.LabelField(noneString);
if you pass an instance ID of -1 it gives you the "Missing" content
and 0 for "None" content
@onyx harness is there a way to change the instance ID of an object?
ah, right
Dont do that on existing object though
probably not good idea
But if you want to fetch any object, you can create an empty Object, reassign its InstanceID and serialize it, you will have all its content fetched naturally
I mean, that all could work, but also just drawing the style seems like a much more stable and performant solution
I would prefer drawing the style too
But if you prefer to stay consistent in using an Object, creating a fake object does not cost anything
ah, note for the reflection approach
using the internal EditorGUIUtility.ObjectContent() causes problems because it caches the content in this field
private static readonly GUIContent s_ObjectContent;
so if you do this
- Call ObjectContent to get a "Missing" content
- Call ObjectContent to get a "None" content
-Draw withEditorStyles.objectField.Draw using the missing content
-Draw withEditorStyles.objectField.Draw using the none content
both of your draws will get the "None" appearance
you can instead just use this other internal method to get the "Missing" GUIContent
private static extern string GetTypeNameWithInfo(string typeName, int instanceID);
it's what they use internally
internal static GUIContent ObjectContent(UnityObject obj, Type type, int instanceID)
{
if (obj)
{
s_ObjectContent.text = GetObjectNameWithInfo(obj);
s_ObjectContent.image = AssetPreview.GetMiniThumbnail(obj);
}
else if (type != null)
{
s_ObjectContent.text = GetTypeNameWithInfo(type.Name, instanceID); <-------
s_ObjectContent.image = AssetPreview.GetMiniTypeThumbnail(type);
}
else
{
s_ObjectContent.text = "<no type>";
s_ObjectContent.image = null;
}
return s_ObjectContent;
}
pass instanceID of -1 to get "Missing" and instanceID of 0 to get "None"
I don't know if Unity ever uses the instanceIDs -1 and 0 for internal stuff tho
haven't seen it so far, but who knows 😅
0 is by default a none existing object
So pretty sure it is widely used in their codebase
i mean if they only use it for a non-existing object it should be fine
We use -1 for a natural non-used ID, but perhaps 1, 2, 3, etc. are also missing ones 🙂
seems safe enough then
if it ever makes my Unity explode i'll share the cautionary tale 🙃
Hi, I've made a little extension to add object arrays similar to the ones in blender. Not the first of its kind, but this is mine :)
https://github.com/Moolt/Unity-GameObject-Array
Nice job, but wrong channel @eternal surge
What would be the fitting channel? It may fit asset-store-advertising, but I didn't put it on the asset store but only GitHub
@eternal surge #archived-resources for free resources/assets
ah, makes sense. thank you very much
Hello 🙂
I would like to understand how to implement undo in the editor
I want to replace GameObjects from the scene with prefabs
I have a editor script with this sequence within a method:
foreach ( GameObject sceneGameObject in selectedObjectsInScene){
PrefabGameObject = GameObject.Instantiate(GameObjectReplacement) as GameObject;
Undo.RegisterCreatedObjectUndo(PrefabGameObject, "created object");
PrefabGameObject.transform.position = sceneGameObject.transform.position;
PrefabGameObject.transform.rotation = sceneGameObject.transform.rotation;
PrefabGameObject.transform.localScale = sceneGameObject.transform.localScale;
PrefabGameObject.transform.parent = sceneGameObject.transform.parent;
Undo.DestroyObjectImmediate(sceneGameObject);
}
Everthying works as intended, but Unity crashes when hitting ctrl+z after running the script.
It seems the problem comes when calling Undo.RegisterCreatedObjectUndo(..) as when I comment it out, unity does not crash anymore
any ideas?
I am not sure the explanations on in the manual can help me ( https://docs.unity3d.com/ScriptReference/Undo.html)
I think it looks okay... Simply for a readability thing I would change PrefabGameObject to be defined where it is instatiated, so GameObject prefabInstance = (GameObject)GameObject.Instantiate(GameObjectReplacement);
You also want to combine all of the undo operations in to one so that when you perform an undo/redo all of the gameobjects will be destroyed and created in the same operations
int undoGroup = Undo.GetCurrentGroup();
// foreach loop here...
Undo.CollapseUndoOperations(undoGroup);
just a random guess, your Editor may be crashing because you are destroying an object that is part of the undo operation?
try to do the PrefabGameObject.transform.position, etc lines before the RegisterCreatedObjectUndo and see what happens
this is a nice idea. i will try and implement it
hey, this one did the trick!
now it works properly, thank you very much
i actually had no idea if that was the problem, just a random guess 😅
glad it's working
I am trying to find a way to not use harmony for this thing I am doing. And I almost have found a way....
Not for the first time I have wished I could inherit from an internal class 😢
what ya doing exactly?
I am working to finish my ScriptableObject Variants asset, and need to support VisualElements showing the override.
sounds like one of those things that seems simple enough but then Unity does a 360 on you
"pls unity stop being unity"
😢 ...
Harmony in an asset in the Asset Store is dangerous, hope you will go through
There is a VisualTreeUpdater that takes a list of IVisualTreeUpdater and does exactly what I want... if I could implement IVisualTreeUpdater in a class
is Harmony considered against terms of service? I know it's a tool modders use to hack code into games and stuff
Yeah, I think I can find a way to make it work without it. I would really prefer not to use Harmony in an asset, especially since it is not 'mission critical' for the asset to function
I know some assets use it. Like the Needle guys just released an asset that uses it I know
- There are magic methods you're supposed to use (that aren't mentioned in the main API docs - you have to know they exst before you can discover they exist ;)) instead of core methods if you want Undo to work correctly. There are replacements for (off the top of my head): .position, .rotation, .transform.parent, and AddComponent <-- the parent one is important and the addcomponent one is slightly important. You don't have to use them (apart from the parent one - not using that one causes actual problems) but they are worth using. Almost no-one knows about these, but then ... Undo doesn't work correctly for most assets so that's not a surprise 🙂
- Unity wrote a one-class utility that makes Undo much easier to get right, and auto-compiles-itself-out of non-Editor builds. It's called "UndoBlock". It's here: https://docs.unity3d.com/Packages/com.unity.reflect@1.0/api/Unity.Labs.Utils.UndoBlock.html - you can get the source from their repo IIRC.
- ...UndoBlock is missing some features/API calls required to fully implement Undo in Unity, so I use an extended version of that class (which I sent back to Unity, the changes might (?) have been incorporated), and now it's easy to make Undo work in new assets/projects.
I've been filing bugs on Unity's Undo implementation since approx 2014. I consider it an embarassment that it was never really tested or designed.
What magic methods do you mean...? As far as I know there are no 'undo alternatives' for setting the position or rotation.
Undo doesn't work correctly for most assets
What do you mean? Do you mean that most assets don't implement it properly, or that Undo doesn't allow functionality that would support most assets?
Man that Unity.Labs package has so many handy utilities! Too mad it is not on github 😦
The undo block is pretty basic right? Just a get and collapse the undo group, no?
IME: Most assets don't implement Undo correctly. You can undo some actions but not all, or you can undo 'everything' or 'nothing' but not 'the actual steps I performed, in reverse order'. etc.
The undo block is circa 300 lines of code, so I guess basic yes?
Yeah, most assets don't. Which is funny because it is a requirement to be on the store...
I disagree, you can implement Undo just fine, you just register an undo before each change. That is exactly how it is designed to be used
(Whether that is a good design or not is very much so up for debate though haha)
No, it's not how it's designed, sadly
That simply won't work a lot of the time
It's things like: do you remember to never do "transform.parent = X" and instead do "Undo.SetTransformParent( X )"?
Simple cases today mostly work (although one bug I filed a few years back was "create a cube, rotate it once, move it with the mouse, hit ctrl-z, and undo breaks" with core UnityEditor 😄 )
I am pretty sure that is the only exception to the rule
Uhh... they how is it designed?
Can you give an example of where undo won't work?
If it were designed simply then we wouldn't need most of the API, we'd only need a couple of method calls, they would work in all situations, and there'd be no excuse for any asset to be missing full Undo support
In practice it's: do it simply, discover the MANY cases that break in-editor, play whack-a-mole trying different combinations of API calls to try and force the Editor to honour the API, play whack-a-mole some more re-writing your code in ways that should make no difference but do make the Editor Undo system work / stop working ... etc
(and, of course, every method call has to be #if UNITY_EDITOR because none of the API calls are allowed in runtime code)
TL;DR: it's a mess
What the heck are you doing...?!
If you are trying to use undo in runtime classes (like components) you are using undo and editor scripting wrong...
Any change to any data that can be triggered from inside the editor needs to be wrapped in undo logic. If your editor menu does something that uses your runtime components/code/etc ... and you don't insert/wrap all the Undo cases ... it will screw up. The code will run fine in runtime and Editor, but Editor will fail to Undo (sometimes you get 'nothing happens', but about 1/3 the time you get 'Unity corrupts the scene' by making weird random changes to MonoBehaviour data)
(corruption that - of course - can't be undone using ctrl-z; it's 'git checkout --' time again)
When editor scripting you should almost never need to use #if UNITY_EDITOR
TL;DR: if Undo is simple, and works as designed -- why did Unity staff feel the need to make a wrapper for it that makes it easier to use? 🙂
Gizmos and Undo are the two places I keep having to do it, on project after project. Off the top of my head there aren't any others
It is literally basically just this.
public class UndoBlock : IDisposible
{
private int undoGroup;
public UndoBlock()
{
undoGroup = Undo.GetCurrentGroup():
}
public void Dispose()
{
Undo.CollapseUndoOperations(undoGroup)
}
}
What, why?? What is the use-case for having Undo in runtime scripts?
(Gizmos are already in the UnityEngine namespace so you don't need them in #if UNITY_EDITOR right...?)
In general if you are changing properties of a runtime object, you should be using SerializedObject to do it not calling the APIs.
Gizmos have no meaning at runtime. But Unity requires the (editor-only) code for gizmos to go inside runtime classes. If you constrain yourself to the crappy/ugly Unity-3.x era editor extensions then, sure, you'll be OK. But if you want to do anything particularly valuable/interactive it usually means interacting with Editor APIs sooner or later.
The Gizmos class should work in build unless I am wrong (not visible, but won't stop the build)
Most of the time, if you are doing something with a Editor API, then you should be doing it in an editor specific class. There are some cases where that is not the case, normally those have to do with the asset database in some way, but general editor code goes in editor class
I tried that approach. It's insane. It will kill you. The amount of code duplication is incredible (I recently refactored an 8 year old editor extension that was built that way - So. Many. Bugs! due to code duplication).
Or: I have an extension that was originally editor-only, but users required it to be also available at runtime. That was painful to change.
It depends on what you are doing, but there should be that much duplication. Either way, that is the way that Unity designed it to work.
If you don't like doing it that way that is fine, but it isn't fair to say that something like Undo doesn't work well when you are not using it as intended.
Not saying the design is perfect, but it does function well and covers any use-case as long as you are using UnityEngine.Objects
Editor code should basically be treated like the view and controller in an MVC (assuming I remember the MVC properly)
Where the runtime stuff is the model
https://docs.unity3d.com/ScriptReference/Undo.html
What do you call main API docs?
Is there a decent way to get the folder for your asset?
Right now I am doing this and it feels really dirty
internal class EditorAssetsFolderLocator : ScriptableObject
{
/// <summary>
/// Reterns the project reletive path to the "MyAsset/Editor" folder in the assets folder.
/// </summary>
public static string GetFolderPath()
{
var locator = CreateInstance<EditorAssetsFolderLocator>();
var script = MonoScript.FromScriptableObject(locator);
string path = Path.GetDirectoryName(AssetDatabase.GetAssetPath(script));
if (Path.DirectorySeparatorChar != '/')
path = path.Replace(Path.DirectorySeparatorChar, '/');
DestroyImmediate(locator);
return path;
}
}
@gloomy chasm you can use the [CallerFilePath] attribute or a StackTrace
private static string GetFolderPath1(bool projectRelative = true, [CallerFilePath] string filePath = "")
{
filePath = Path.GetDirectoryName(filePath);
filePath = MakePathUnityStyle(filePath);
if (projectRelative)
{
filePath = MakePathRelative(filePath);
}
return filePath;
}
private static string GetFolderPath2(bool projectRelative = true)
{
string filePath = new StackTrace(true).GetFrame(0).GetFileName();
filePath = Path.GetDirectoryName(filePath);
filePath = MakePathUnityStyle(filePath);
if (projectRelative)
{
filePath = MakePathRelative(filePath);
}
return filePath;
}
private static string MakePathUnityStyle(string path)
{
return path.Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
}
private static string MakePathRelative(string path)
{
return path.Replace(Application.dataPath, "").Insert(0, "Assets");
}
typeof(EditorAssetsFolderLocation).Assembly.Location perhaps
works for AsmDef, which might link to Library, crap
I'm using this to fetch from a Type:
https://gist.github.com/Mikilo/bbeda90ed7125a35a11cbcaab6aa6e39
Which basically uses your trick, but has fallbacks
So basically, there isn't really a nicer way to do it :/
But my utility is mainly to extract GUID & LocalID
If
If you rely on "C# Type must match its filename"
You can use this:
static class PrintAssembliesSources
{
[MenuItem(Constants.PackageTitle + " Internal/Print Assemblies Sources")]
public static void Print()
{
var list = Client.List(
#if UNITY_2018_1_OR_NEWER
true
#endif
);
while (list.IsCompleted == false);
foreach (var item in list.Result)
NGDebug.Snapshot(item, item.packageId);
Assembly[] playerAssemblies = CompilationPipeline.GetAssemblies();
StringBuilder buffer = Utility.GetBuffer();
foreach (Assembly assembly in playerAssemblies)
{
NGDebug.Snapshot(assembly, assembly.name);
buffer.Length = 0;
for (int i = 0, max = assembly.sourceFiles.Length; i < max; i++)
buffer.AppendLine(assembly.sourceFiles[i]);
Debug.Log(buffer.ToString());
}
}
}
Which gives you the the .cs for any Asm
Not very reliable
I mean, you can't handle duplicate
I know there is another way to get scripts, but I forgot, someone mention another way on the publisher Discord or the forum, I don't recall
But the StackTrace should work pretty decently
i can't say how reliable it is because I'm not super experienced in this topic
but so far for me it has been working fine, and it's relatively clean
using the [CallerFilePath] works fine too, but you have to wrap the method in another method or you will get a different path if the method with the attribute is called from an external script
so
public static string GetFolderPath(bool projectRelative = true)
{
return GetFolderPath(projectRelative);
}
private static string GetFolderPath(bool projectRelative, [CallerFilePath] string filePath = "")
{
filePath = Path.GetDirectoryName(filePath);
filePath = MakePathUnityStyle(filePath);
if (projectRelative)
{
filePath = MakePathRelative(filePath);
}
return filePath;
}
which is kinda boilerplate-ish
i just keep both examples just in case one of them doesn't work for some reason
StackTrace is pretty reliable, we all rely on it when writing a console
Yeah, seems like StackTrace might be a good idea. I will give it a try, thanks Madled
Don't forget to cache to keep it efficient
@onyx harness well... it took ~5 hours but I finally managed to remove harmony! 😄
Trying to follow the code for how Unity handles it was such a pain. You know how it is, both trying to understand the implementation and also look to see how you can hook in to it
Such a pain
The MonoScript was broken in 2020 (they only just fixed it today), so we moved over to using the Assembly trick. However it requires a bit more work than just grabbing the Assembly - you need to handle special cases of "am I in a local Package? (because file locations there aren't writeable, and you usually need to know that!)", and "am I in a DLL? (because I got slightly different results on this one - but there's a Unity API for working around this specifically)"
Manually copying from other machine (IDE on this machine doesn't have that checked out):
var asm = Assembly.GetAssembly(GetType)).GetName().Name;
var asmDef = CompilationPipeline.GetAsssmeblyDefinitionFilePathFromAssemblyName(asm);
var asmDLL = CompilationPipeline.GetPrecompiledAssebmlyPathFromAssemblyName(asm);
if( asmDLL == null ) asmDLL = CompilationPipeline.GetPrecompiledAssebmlyPathFromAssemblyName(asm+".dll"); // yes, really - Unity's API a bit wonky here
var pathForAssembly = asmDef ?? asmDLL;
... which gives you a reliable root position, and then you can navigate relatively
Using the MonoScript works fine for me in 2020.3 and newer. I think I will either keep using that or try out the StackTrace method as that seems a bit cleaner. Thanks for the heads up about the assembly method though!
@honest crater wrong channel. This belongs in #⚛️┃physics or #💻┃code-beginner / #archived-code-general
oh sorry didnt realize
When deleting an asset, you get a prompt like this.
Does anyone know of a way to show my own prompt instead?
@gloomy chasm yes! i've made a similar prompt for an asset processor
gimme a sec
ah whoops
misread
i don't know how to override the default prompt
😓 ...
ooh 😦
Shoot... I don't think there is a way without using Harmony, but I just got rid of it!
Maybe I can try intercepting the key down event in the project browser?
Its not perfect...
It's so silly. Getting SO variants to actually function has taken the least hacking (meaning none) while adding all this 'extra' stuff has taken so much xD
the devil is in the details
i get super bogged down by so many little menial things like that too
Getting sidebars to work took less hacking than this
Well.. no that's not really true since it is almost 100% reflection... but still!
What are you trying to do?
Instead of showing the normal prompt when deleting an asset, I want to show one like this
But for scriptableObject variants of course
Sounds tricky & dificult 🙂
im trying to impliment the ReadOnly attribute, and it works for classes inside the editor script, but my other normal scripts dont recognize it. I have the editor script in the Editor folder. Am i missing a step?
so there's the EditorGUILayout.FloatField() and for other types as well, but where is the boolean version of it?
nvm it's .Toggle()
You need the file where the attribute is defined to not be in the editor folder
then what goes in the editor foldeR?
The code for drawing
You have public class ReadOnlyAttribute : PropertyAttribute { }
And that does not go in the editor folder
i see
your class that inherits from DecoratorDrawer does go in the editor folder
i was able to fix it thanks to you
LOL, I was trying out the new Splines tool and learned that the property drawer uses a naive implementation to get the value of a serialized property just using the property path
That means you can't have a Spline field in another class or list xD
Is there anyways to update nested prefab but do not trigger reimport of father prefab?
Or at least, reimport later
I figured it out. AssetDatabase.StartAssetEditing() + AssetDatabase.StopAssetEditing();
How to build a project with editor script without deleting?
any scripts you put inside an "Editor" folder won't be included in the build
@crystal vale
Oh, ok. Thank you very much
So I am making an extension for my game that procedurally generates a roof made of convex sections based on some control points (child gameobjects). I'm using handles to allow easily moving the points. Moving the handle updates the point's position and regenerates the roof. How do I solve the following issues?:
- An undo operation should only be made when the point begins being moved, not every frame while it is moving (currently I'm storing last saved time and checking if it's been more than a second).
- Undoing/redoing a control point movement should regenerate the roof.
when accessed through a SerializedProperty, why is this class considered a Generic and not an ObjectReference?
[Serializable]
public class SomeClass {}
Because it does not inherit from UnityEngine.Object
ah
makes sense
stupid me 💀
All good. I've been there
is it safe to use UNICODE characters in Unity?
such as this (U+27F6)
⟶
i have been scared of using them because I don't know if they will display inconsistently or if they will break under certain conditions
Using them where?
Yes, for one the PackageManager uses them for the sort order dropdown button
oh, interesting
[Serializable]
public sealed class SceneRef
{
[field: SerializeField] public string ScenePath { get; private set; }
[field: SerializeField] public int BuildIndex { get; private set; }
public static implicit operator string (SceneRef reference) => reference.ScenePath;
public static implicit operator int (SceneRef reference) => reference.BuildIndex;
#if UNITY_EDITOR
[CustomPropertyDrawer(type: typeof(SceneRef))]
public class SceneRefDrawer : PropertyDrawer
{
private const string _SCENE_PATH = nameof(ScenePath);
private const string _BUILD_INDEX = nameof(BuildIndex);
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
SerializedProperty _scenePathProperty = property.FindPropertyRelative(relativePropertyPath: _SCENE_PATH);
SerializedProperty _buildIndexProperty = property.FindPropertyRelative(relativePropertyPath: _BUILD_INDEX);
```Any reason why `_scenePathProperty` and `_buildIndexProperty` are null?
Can **property**.Find**Property**Relative not find properties?
Because ScenePath is not the name of the field that is serialized, it is the backing field which is serialized
And no, FindPropertyReletive some what paradoxically cannot find c# properties. Only public fields and private fields with the [SerializeReference] attribute since those are the only field types that Unity serializes
$"<{nameof(ScenePath)}>k__BackingField" would be how to get the serialized backing field from a property
it's not nice, so it's best to just serialize backing fields
I was wondering if I can have a bunch of CreateCustomGameObject in a separate static class(es). Of course with different method names, as long as the [MenuItem()] directive made the editor recognise those methods?
Is that possible? Or do I need to keep them in the Monobehaviour derived classes?
hey. how can i set some Editor local method to be called right after load ?
I want to subscribe to onHierarchyChanged as soon as possible
EditorApplication.hierarchyChanged += onHierarchyChanged;```
but the soonest thing I know is OnEnable, which is not good, because its only called when someone clicks on the gameobject with that script
I'm trying to learn about ScriptedImporter as I have a file with a unique extension that contains data for various meshes. In my OnImportAsset(AssetImportContext ctx) method I'm able to make children and components (MeshFilter and MeshRenderer for exmaple) to the object, but for some reason no matter how I make Meshes and assign them to the MeshFilter.mesh property, the file never shows the meshes. When I attempt to use the example code on the API it does properly show a primitive cube for the GameObject though. Any help appreciated. Thanks!
[ScriptedImporter(1, "XPR")]
public class XPRImporter : ScriptedImporter {
public Mesh[] meshes;
public override void OnImportAsset(AssetImportContext ctx) {
GameObject root = ObjectFactory.CreateGameObject(Path.GetFileNameWithoutExtension(ctx.assetPath));
root.transform.position = new Vector3(0, 0, 0);
GameObject meshRoot = ObjectFactory.CreateGameObject("MDL");
meshRoot.transform.position = new Vector3(0, 0, 0);
meshRoot.transform.SetParent(root.transform);
GameObject mesh = ObjectFactory.CreateGameObject("OBJ");
mesh.transform.position = new Vector3(0, 0, 0);
mesh.transform.SetParent(meshRoot.transform);
MeshFilter meshFilter = ObjectFactory.AddComponent<MeshFilter>(mesh);
MeshRenderer meshRenderer = ObjectFactory.AddComponent<MeshRenderer>(mesh);();
meshes = new Mesh[1];
meshes[0] = new Mesh();
meshes[0].Clear();
meshes[0].vertices = new Vector3[] {
new Vector3(0, 0, 0),
new Vector3(0, 0, 1),
new Vector3(1, 0, 0)
};
meshes[0].triangles = new int[] { 0, 1, 2 };
meshFilter.mesh = meshes[0];
ctx.AddObjectToAsset("main", root);
ctx.SetMainObject(root);
}
}
You probably need to dirty the meshfilter
I guess I'll create a utility function for that amd test it out, thanks guys!
How would I do that?
Not sure what you are talking about exactly, but yes.
Lookup the InitializeOnLoad attribute
Creating additional entries under 'GameObject' in the heirarchy context menu
There or anywhere else for that matter
Oh, yeah you can
Did a EditorUtility.SetDirty(meshFilter); call and it didn't alter the results.
Also I get the following error on import if I have public Mesh[] meshes; Line in the class like in Ln3 of my example. I don't understand why, even if I don't do anything with it:
NullReferenceException: Object reference not set to an instance of an object
UnityEditor.PropertyHandler.IsArrayReorderable (UnityEditor.SerializedProperty property)
Anyone know how or if it's possible to draw gizmos within the PreviewRenderUtility please?
How can I tell when a hotkey is used when I am in the UnityEditor
Anyone know whether to use PreviewRenderUtility over GUI.DrawTextureWithTexCoords when trying to make an editor that's similar to the animation window?
yes, with reflection, Unity has this internal delegate
internal static CallbackFunction globalEventHandler;
you can access the information of a KeyDown and KeyUp using that
it also has this one, to check if a shortcut is triggered
internal static Func<bool> doPressedKeysTriggerAnyShortcut;
here's an example on how to use them
public static class GlobalKeyEvents
{
// Exposed delegates to hook up your methods to them.
public static event Action<KeyCode, EventModifiers> GlobalKeyDown;
public static event Action<KeyCode, EventModifiers> GlobalKeyUp;
public static event Action AnyShortcutTriggered;
[InitializeOnLoadMethod]
private static void EditorInit()
{
RegisterToGlobalEventHandler();
RegisterToTriggeredAnyShortcut();
}
private static void RegisterToGlobalEventHandler()
{
FieldInfo info = typeof(EditorApplication).GetField("globalEventHandler", BindingFlags.Static | BindingFlags.NonPublic);
EditorApplication.CallbackFunction value = (EditorApplication.CallbackFunction)info.GetValue(null);
value += OnGlobalKeyPressed;
info.SetValue(null, value);
}
private static void RegisterToTriggeredAnyShortcut()
{
FieldInfo info = typeof(EditorApplication).GetField("doPressedKeysTriggerAnyShortcut", BindingFlags.Static | BindingFlags.NonPublic);
Func<bool> value = (Func<bool>)info.GetValue(null);
value += OnAnyShortcutTriggered;
info.SetValue(null, value);
}
private static void OnGlobalKeyPressed()
{
if (Event.current.type == EventType.KeyDown)
{
GlobalKeyDown?.Invoke(Event.current.keyCode, Event.current.modifiers);
}
else if (Event.current.type == EventType.KeyUp)
{
GlobalKeyUp?.Invoke(Event.current.keyCode, Event.current.modifiers);
}
}
private static bool OnAnyShortcutTriggered()
{
AnyShortcutTriggered?.Invoke();
return true;
}
}
however, the doPressedKeysTriggerAnyShortcut delegate seems like it doesn't trigger for EVERY shortcut, like for example Ctrl + R or Ctrl + C don't trigger it
so you probably want to rely more on the globalEventHandler to manually check for your key combinations
I think the handles class should "handle" that for you
Is there a way I can add a MenuItem without using the attribute?
I don't think so, what would be your preferred way to make them?
You seem like you know your stuff... But I got some errors, probably easy to fix for you.
you need to use the namespaces where those types are in
with the "using" directives like
using System;
using UnityEngine;
etc...
if you press "CTRL + ." while the caret (cursor) is on top of those errors in Visual Studio it should give you a list of recommended fixes
one of them will be to import the namespaces
Any idea whether you can make editor window top part to be windows style? not this one that snaps only inside unity
just like main unity window
like that
Good question, I’d like to know too. I doubt it though
@north sphinx @harsh hull yes, search the documentation for EditorWindow, it has multiple ''Show...'' methods to show the window in different ways
Normal, utility, etc
I don't think you can change the style of the default windows like the scene, inspector, etc
Or at least i dont know how
But you can show your own windows however you like
There's the Wizard thing that has the normal windows bar
ah I'm stupid, you actually can show the default windows however you like too
you can't change the already existing ones, you have to create a new instance
@north sphinx but you will lose the functionality that comes with the top bar buttons like the lock and the context menus
wait, what do I click in that context menu?
to open window as separate window
no, i mean with the other styles like the ShowUtility, you will lose those top bar buttons
to open the windows as extra instances with the different styles you need to use CreateInstance
one sec, i'll share example
using System.Linq;
using System;
using UnityEditor;
using UnityEngine;
public class ShowsWithDefaultWindows : EditorWindow
{
private EditorWindow[] _foundWindows;
private int _selectedIndex;
private string[] _popupOptions;
[MenuItem("Something/Default windows Show test")]
public static void MakeWindow()
{
GetWindow<ShowsWithDefaultWindows>();
}
private void OnGUI()
{
// Get all windows
if (GUILayout.Button("Get all open windows"))
{
_foundWindows = EditorWindowUtility.GetAllWindows();
_popupOptions = _foundWindows.Select(window => window.GetType().Name).ToArray();
}
// Draw popup, button and labels
if (_foundWindows != null && _foundWindows.Length != 0)
{
_selectedIndex = EditorGUILayout.Popup(_selectedIndex, _popupOptions);
if (GUILayout.Button($"Call ShowUtility on: {_popupOptions[_selectedIndex]}"))
{
EditorWindow newInstance = CreateInstance(_foundWindows[_selectedIndex].GetType()) as EditorWindow;
newInstance.ShowUtility();
}
for (int i = 0; i < _foundWindows.Length; i++)
{
EditorGUILayout.LabelField(_foundWindows[i].titleContent.text, $"Type: {_foundWindows[i].GetType()}");
}
}
else
{
EditorGUILayout.LabelField("No found windows");
}
}
}
i have no idea if there's unintended consequences of showing the default windows in that manner...
because Unity... you know 🙃
so use at your own risk
ah forgot to share the utility method
public static class EditorWindowUtility
{
public static EditorWindow[] GetAllWindows()
{
return Resources.FindObjectsOfTypeAll<EditorWindow>();
}
}
wow, thanks
let's see how it works
yep, it is indeed opened in windows style window
but, is it possible to do it with exactly this style?
that has minimize/maximize
and x to close
like main Unity window
Mainly I want that because unity own windows are not snapping to screen
no idea to be honest
I haven't dug that far into this topic
maybe someone else knows
how aren't they snapping?
when I click "maximize" on mine they snap to the edges of the screen
like that, screenshot top is edge of screen
it just goes above, like unity window
@north sphinx i don't know what you mean exactly, both my main Unity window and the EditorWindows snap by default when doing maximize
EditorWindows don't snap by dragging like the main window does tho
🤷♀️
kinda that's what I mean, I dragged window partially into top side of screen and if I stop holding mouse, screen will maximize itself
editor windows don't do that
and that's what I aim for
Hi 🙂 I am looking for a bit of help/insight in setting up my ability system. One of the things I would like to be able to do is create them as scriptable objects and edit them in the inspector, rather than having to program each of them individually. What I am considering right now is having a custom editable list of steps to happen when the ability hits (abstract class AbilityStep). Would it be possible to make a list like this, but with an abstract object type, rather than one all incompassing class with all the values needed for all of them?
I had this in a previous project, but I just don't find it very configurable/changable
I don't really understand what you are asking, but yeah, you can use polymorphism if that is what you mean.
Does it work smoothly for saving and reloading them?
If I have a list of objects that all inherit from the same type?
Yes if you use the [SerializeReference] attribute instead of [SerializeField]
Cool 🙂 Thanks
On a SerializedProperty, is there a way to see all available children?
namespace Abilities.Steps
{
[Serializable]
public class AbilityStepList
{
public List<AbilityStep> Steps;
}
[Serializable]
public abstract class AbilityStep
{
public abstract bool DoStep();
}
}
When I am making my propertyDrawer for this, I can't access Steps? I also can't get it to work with SerializeReference?
[CustomPropertyDrawer(typeof(AbilityStepList))]
public class AbilityStepListDrawer : PropertyDrawer
{
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
var list = property.FindPropertyRelative("Steps");
return Mathf.Max(list.arraySize, 1) * 90 + 50;
}
}
List is null in this case?
I would like to see if it can't find the property, or if the referenced property is null?
Oh, I got it working - SerializeReference on Steps, rather than on the class that has a AbilityStepList
In the above example AbilityStep is an abstract class - how can I add implementations of it to a reorderablelist that draws it?
what kind of extention do i need to make a ui like this and make it work in edit mode?
(image taken from another engine)
Works. Thank you! Now I can write scripts for the editor to make my compile cycles faster saving hours of work each day.
Look in the pinned messages
which one?
I guess I will break it down for you really quick.
Unity has two UI systems which you can use to create editor windows and inspectors.
Immediate Mode GUI (IMGUI)
This is the original way of make UI, it uses methods to draw the UI each frame much like an Update method in a component.
UI Toolkit (formerly UIElements)
This is the newer way and what will be used more and more as time goes on, it is a retained mode GUI (if you know what that means). It is based/inspired by web design so it uses USS and UXML files to define the structure and style of the UI.
sounds like IMGUI is more for me this time
Alrighty, then in the pinned messages look for "IMGUI Resources" 🙂
Is there a (using UnityEditor;) function that lets me know if the project code base has changed since last compile?
Like... I want to know if it can be refreshed or not
What do you mean? Unless you disabled the option Unity should automatically recompile any time the code changes
Right. Thats what I did. Now I can change code and bounce between editor several times and not have to needlessly recompile every time
it saves about an hour of dev time a day.
Never mind, found a work around
When I try to open Amount here, it crashes with this description:
0x00007ff7aaf0714f (Unity) GetFieldIdentifierForEnum
0x00007ff7abe7399f (Unity) SerializedObject::GetPopupMenuData
0x00007ff7abe74de0 (Unity) SerializedProperty::GetSerializedPropertyType
0x00007ff7aa5f16ec (Unity) SerializedProperty_CUSTOM_GetSerializedPropertyTypeInternal
0x000001375b699ab1 (Mono JIT Code) (wrapper managed-to-native)```
+ a lot longer callstack. Anyone have an idea what the problem might be?
Hi everyone, I'm kind of recreating the editor's mask field, and I'm using the EditorStyles.popup.Draw, but it causes this to happen
~Any ideas?~ Found it, I only needed to do EditorGUI.LabelStuff only when event is repaint
How can I edit the values shown in the inspector for a managed plugin .dll with a script?
I want to change the scripting defines of some DLLs with a script
Found it, PluginImporter
Hi, is there a command or the like to select previous asset, essentially a command that functions like a back button?
So I'm inspecting a material then click on a prefab. Is there a built in command to get back to the material I was originally inspecting?
No but there extensions that do that mikilo's NG tools have one iirc
Had a question earlier that I deleted, I'll try to rephrase it: We're making an Isometric game using Tilemaps and I'm having issues with sorting layers so that the player is properly rendered in front of/behind objects like walls and pillars that they can be expected to both be behind and in front of
Instances like this, I can stand behind this wall but I want it to render properly when you're in front of it too
right now, that looks like this
Would there be a way to dynamically solve this in code? Like, checking whether or not the player is in front of or behind specific parts of the Tilemap? I know you're able to do that when referring specifically to singular objects with singular Sprites but since the Tilemap object isnt just a single square thats not going to work
Found this in an old forum thread https://forum.unity.com/threads/isometric-tilemap-sorting-issues.554914/#post-3692299
Hello folks,
first of all hearing that you are adding isometric tilemaps was great news.
When I use different Tiles, they seem to be sorted in a...
That if I put everything on the same layer, itll dynamically sort itself out
is this the only way to solve it? Feels like itd lead to issues later
is it possible to create a property drawer for an editor class and not a monobehaviour?
would i need to perhaps serialize the editor window class. I'm using a custom editor that I want to display something in, which is what the property drawer would be for displaying; a property in the custom editor window.
Should I perhaps create a serialized container class for stuff I want to be display in the property draw?
is there way to search for all animator controller in the AssetDatabase?
kinda like "t:Script"
what about FindAssets?
that's what I've been using for search
I just want to use the filter mode
you should be able to use the filter to search for classes of the animationcontroller
yeah, the docs don't give much info on how to use the filters
yes, that's why I asked lmao XD
here, check this post out, think this is what you are after https://answers.unity.com/questions/1387307/unityeditor-script-retrieve-all-the-animatorcontro.html
Unity is the ultimate game development platform. Use Unity to build high-quality 3D and 2D games, deploy them across mobile, desktop, VR/AR, consoles or the Web, and connect with loyal and enthusiastic players and customers.
@valid wharfDid that work?
code-advanced is probably a better channel
thanks
What do you mean?
@gloomy chasmi'm trying to have a docked previewRenderUtility window at the bottom of my editor, but don't know how to dock it, so considered making a property drawer to display it. Ie, the Cube window in the image below would show a previewRenderUtility window of what's in the Fbx Model field
that's a cut & paste, I don't know how to make the docked cube window thing at the bottom attach to my editor. This is what I want it to be.
I have the previewRenderUtility code to display what I want, but it's in it's own window
this is what have
Anyone know how to add an Apply and Revert buttons to the inspector of a ScriptedImporter, I have booleans in the Editor Window but I have to Right-click > Reimport every time, instead of doing an Apply like an FBX importer.
yes
https://docs.unity3d.com/ScriptReference/AssetImporters.AssetImporterEditor-needsApplyRevert.html
https://docs.unity3d.com/ScriptReference/AssetImporters.AssetImporterEditor.ApplyRevertGUI.html
https://docs.unity3d.com/ScriptReference/AssetImporters.AssetImporterEditor.OnApplyRevertGUI.html
https://docs.unity3d.com/ScriptReference/AssetImporters.AssetImporterEditor.ApplyButton.html
https://docs.unity3d.com/ScriptReference/AssetImporters.AssetImporterEditor.CanApply.html
https://docs.unity3d.com/ScriptReference/AssetImporters.AssetImporterEditor.Apply.html
https://docs.unity3d.com/ScriptReference/AssetImporters.AssetImporterEditor.RevertButton.html
https://docs.unity3d.com/ScriptReference/AssetImporters.AssetImporterEditor.ResetValues.html
https://docs.unity3d.com/ScriptReference/Editor.ShouldHideOpenButton.html
there's all the relevant API methods
i threw a couple extra just for good measure
Much appreciated
@patent pebble sadly, even after adding a protected override bool needsApplyRevert => true; and in the protected override void OnInspectorGUI() { } I add the ApplyRevertGUI(); call, neither button shows.
that's for static methods. I specified I'm looking for a way to call local methods. but thatnks anyways
OnEnable is called right after an editor instance is loaded
Discovered recently that an EditorWindow invokes OnFocus before OnEnable on initialization
Oh cool
Heyllo people, How may I display an int value in the custom editor of a ScriptableObject ?
Hey did you get this working? I was dealing with this today. The solution is to set the custom sorting axis for your camera to (0, 1, 0). I believe for a tilemap you need to set it to render individually instead of batch mode.
You'll also need to make sure the pivot point of your sprites is at bottom center as that's the position that is considered when sorting.
@terse marsh
How to run code on Update in editor only?
Basically, I'm making my own custom renderer for niche cases and I need to create a preview in scene view to adjust colliders/scale/positions
Which is pepega hard without any view.
So I simply want to run some code on Update
but only for editor
EditorApplication.Update?
ExecuteAlways/ExecuteInEditor?
hmm, maybe it is
yeeep that is it
thank you
hmmm
what about isolated view in Prefab editor?
for some reason in prefab editor my code is not running
I do it in update()
I have tried to make a custom unity inspector for a thing I made and I am overriding the regular rendering to have it drawn as a grid of toggles(images actually but still toggles) but seems like any changes I make don't get saved to the disk. only in memory
so I have a Scriptable object containing an array of booleans and not sure how I am supposed to modify it so it gets saved
Use SerializedObjects instead of direct object access
something like?
var myThing = (MyObjectType) serializedObject.targetObject;
it gets my data, I modify it but how do I save it?
serializedObject.ApplyModifiedProperties(); doesn't seem to do anything
and I do Markdity on the target object
sorry but idk how to use it
that's why there's google
I don't have good google skills
you better learn then
If you google Unity Serialized Object, you probably find an example of eactly what you want
var array = ((UnitRange) serializedObject.targetObject).grid;
array[3] = true;
EditorUtility.SetDirty(_property.serializedObject.targetObject);
_property.serializedObject.ApplyModifiedProperties();
that's rougly what I do rn
seems like it's saving the stuff but only when I hit save on the scene
Kinda works but kinda sucks I need to hit ctrl save after hitting the save button in my editor
Hi everyone, quick question, I am currently using EditorGUI.ToggleLeft, is it possible to make it have this state?
Or what sort of toggle should I use/should I cheese it by drawing that on top of the inactive toggle
EditorGUI.showMixedValue = true;
bool value = EditorGUILayout.Toggle (...);
EditorGUI.showMixedValue = false;```
❤️
Hello so I am working on an Editor Themes asset that lets you change the default look of unity. However I have a bit of trouble changing the color of buttons. I can change almost anything using an uss just buttons don't work ```css
.button
{
background-color: #000000;
}
I'm trying to setup a progress bar but this only goes to 2/5 th of the loading bar, the rest after "Iter_2" stays in the same place. Any ideas why?
EditorUtility.DisplayProgressBar("ProgressBarTest", "Iter_1", 1f / 5f);
Thread.Sleep(1000);
EditorUtility.DisplayProgressBar("ProgressBarTest", "Iter_2", 2f / 5f);
Thread.Sleep(1000);
EditorUtility.DisplayProgressBar("ProgressBarTest", "Iter_3", 3f / 5f);
Thread.Sleep(1000);
EditorUtility.DisplayProgressBar("ProgressBarTest", "Iter_4", 4f / 5f);
Thread.Sleep(1000);
EditorUtility.DisplayProgressBar("ProgressBarTest", "Iter_5", 5f / 5f);
Thread.Sleep(1000);
EditorUtility.ClearProgressBar();
Thread.sleep is not a good way to test that, wouldn't surprise me if that's causing issues
updated the script to use x / 100f based values, after the reload it worked correctly, second time it got stuck again. So. yeah probably thread sleep
Hi everyone,
One my project growth, I need to better manage my project's assets. One solution i'm exploring is having two project : One for asset integration, and one for the project. To setup a functional pipeline using this method, I would like to develop a tool able to export UnityPackage from the "Asset only project" and automatically import it in the real game project. This will allow us to just add what we use in our project, but also have a nice way to update content without directly modifying source file.
But I need for this tool a script able to run a script from another project :
Export Package From "Asset project" -> Import Package in "Game Project". I've never seen a script able to communicate with another unity instance.
So my question is : Do you know if this is possible ? If yes, how would you do something like this ?
This is an experimental reflexion, and maybe there are some better way to handle this issue. So if you have any recommandation i would be happy to hear them.
Thank you !
Hey folks,
Can anybody here firstly put up with my venting on how much I hate the fuzzy undefined behaviour of serialising unity assets and secondly please help me with fixing said flaky undefined behaviour. I'm going mad with deadline-looming but unitys-making-no-effing-sense crunchitis here.
Hey, just go through and explain, then we'll see if we can be of any help ^^
Sure, I'm creating materials and setting properties - essentially creating a copy of a material but using a slightly different shader with similar parameters.
If I create the materials one by one, it works OK but if I create them altogether it sometimes misbehaves and all the input textures to the material are set to 'none'.
I print out the contents of the material after creation each time and the values look fine but seeing it in unity: nothing.
I'm saving the asset, I'm calling 'AssetDatabase.Refresh();' like some sort of ritual against bad spirits but still this weird empty material behaviour.
yup
The trouble is, I have no idea when unity is doing anything and no control over it either.
Can I see the code your are using?
it's all a black box and that black box isn't doing what I expect it to
sure, one sec
public Material CreateMaterialCopy(Material sourceMaterial, string newMaterialPath, Shader newShader)
{
if (newShader != null)
{
var mat = new Material(newShader);
var dir = Directory.GetParent(newMaterialPath).FullName;
EnsureDirectory(dir);
AssetDatabase.CreateAsset(mat, newMaterialPath);
AssetDatabase.Refresh();
Debug.Log("Creating material: " + newMaterialPath);
var dirName = Path.GetDirectoryName(newMaterialPath);
var sourceShader = sourceMaterial.shader;
int propCount = newShader.GetPropertyCount();
AssetDatabase.Refresh();
for (var i = 0; i< gTextureMergeSpecs.Length; ++i)
{
var mspec = gTextureMergeSpecs[i];
if (mat.HasProperty(mspec.materialPropName))
{
var fname = dirName + "/" + mspec.mergedFileName;
AssetDatabase.Refresh();
Texture newTexture = CreateMergedTextureFromMaterial(sourceMaterial, fname, mspec.subChannelMapNames, false);
mat.SetTexture(mspec.materialPropName, newTexture);
AssetDatabase.Refresh();
}
} ```
AssetDatabase.Refresh();
//yield return new WaitForSeconds(2);
for (var i = 0; i < propCount; ++i)
{
var propName = newShader.GetPropertyName(i);
var sourcePropIdx = sourceShader.FindPropertyIndex(propName);
if (sourcePropIdx != -1)
{
CopyMaterialProperty(sourceMaterial, sourcePropIdx, mat, i);
}
}
//do this last, attempting to give asset database time to catch up
AssetDatabase.Refresh();
for (var i = 0; i < gTextureMergeSpecs.Length; ++i)
{
var mspec = gTextureMergeSpecs[i];
if (mat.HasProperty(mspec.materialPropName))
{
var fname = dirName + "/" + mspec.mergedFileName;
Texture newTexture = (Texture2D)AssetDatabase.LoadAssetAtPath(fname, typeof(Texture2D));
if (newTexture != null)
mat.SetTexture(mspec.materialPropName, newTexture);
else
Debug.Log("failed to set merged textured:" + mspec.materialPropName);
}
}
AssetDatabase.Refresh();
EditorUtility.SetDirty(mat);
Debug.Log(PrintMaterialContents(mat));
AssetDatabase.Refresh();
return mat;
}
else
{
return new Material(sourceMaterial);
}
}
gimme a second to read that
You may want to put that CreateAsset at the end of your code.
I'm not 100% sure that CreateAsset links your attribute "mat" to the newly created asset.
From memory, I think you create the asset, and then you load it to deal with the actual asset (or you create the asset at the end).
You can safely discard most of those AssetDatabase Refresh ^.^ but I don't think they will cause any harm.
Sorry, it's a bit long and there's some things in there that are hacky desperations around simply not understanding why the thing is doing what it's doing
Sure, no problem.
like ideally the second iteration through the 'gTextureMergeSpec' stuff shouldn't be necessary but that was me thinking that perhaps some late processing on the textures was resetting them, causing them to be nulled in the material later? No idea, it's all a black box.
Try to load your material after creating it, instead of keeping the initial "mat" reference.
I think it's your best bet.
From my own experience, when you start handling material assets, the usual problem is how to avoid them from saving things permanently, no the other way around 😁
ha, well it could do with being clearer. Sometimes with this I feel less like I'm programming, more like I'm doing weird incantations and goat sacrifices to get the machine god to behave itself (n.b. have not actually hurt any goats)
Also and this one is in case you are super tired, if for some reason the code goes through the "else" but you are super convinced that it doesn't, it obviously won't save anything.
yeah, that's also a possibility, been doing late nights on this sprint. Holidays next week and they want it all working.
Yeah Asset management in Unity is a bit related to dark voodoo, but it's not supposed to be blocking since the API is really small.
I'd rather a REST style callback thingy when things are done.
As long as you modify an asset, it should be fairly easy, so you should probably make 2-3 calls to assess what kind of instance you are handling.
ohh, that sounds interesting - what are the different types of instance?
btw, that worked! Thank you - I should have guessed, like I said I had that idea with textures earlier but somehow didn't think to apply that lesson to materials.
Ah great!
Well there are in-memory instances and asset instances, and that's about it.
One is just a temporary variable, and the other is linked to the disk.
Meshes, materials, etc. can be found in both types, depending of what you are doing.
Ok, that's good to know. I knew that in memory assets were kinda temporary but must remember to reload them once saved.
Yeah in the documentation it's not explained.
There are a fairly large number of holes on technicalities in Unity doc.
If they only added that in the doc, it would suddenly make a lot of sense ^.^
I'm guessing that if you tried to check the asset path of "mat" (before loading), you would have noticed that the path was empty 🤔
I'm not sure how to distinguish assets from instances except by knowing that they are 😁 but there must be a way.
It would really help if they pointed just that little thing out, wouldn't it?
@bright nova @keen coral
Right-o, it seems like yall got it figured out, but I will go over a few things to try and make things clearer in the future.
Doing something like New Material(), new Texture(), and CreateInstance<ScriptableObject>() creates an instance of the class in memory.
You use AssetDatabase.CreateAsset(..) to serialize that instance in to a new file on disk.
AssetDatabase.Refresh() is used to update the UnityEngine.Object assets in the project from the serialized files.
AssetDatabase.SaveAssets() saves/serializes any changed UnityEngine.Object to file if they are dirty.
You use EditorUtility.SetDirty(..) to mark a UnityEngine.Object as dirty so that it will be saved.
Assets cannot contain (serialize) references to non-asset UnityEngine.Object as the way that it serializes the reference is using the GUID of the asset, of course non instances don't have a asset GUID.
Also you can use AssetDatabase.Contains(..) to know if an object is an asset or not.
Hey sorry I'm new here so feel free to let me know if this is asked wrong but I'm trying to override the way that a class is shown in inspector and haven't had any luck online. The goal is to show a class, for example a FancyInt differently when it is shown in inspector.
public class FanycInt : Monobehaviour
{
public int fancyInt; // We'll do cool stuff to this later.
}
I can write a custom inspector so that when you add a FancyInt component to an object it show differently, but what I want is for the FancyInt to show up differently when another class is using it, for example
public class FancyIntContainer : Monobehavior
{
public FancyInt myFancyInt = new FancyInt(); // I want to use a custom inspector for this!
}
```
I hope that makes sense, thanks in advance!
You mean you want a FancyInt field to show something besides the normal object field?
Yes
You want a PropertyDrawer https://docs.unity3d.com/ScriptReference/PropertyDrawer.html
Ah, awesome, didn't know how to look this up properly, thanks!
The USS class name for a button is .unity-button
Is this channel only about ui stuff? I want to do something when a scene gets opened in the editor (load another scene). I want to know if its possible and if so how to do it.
I have still not managed to find a solution to this? Anyone have experience with it? Opening a struct on my custom property drawer crashes the system.
You got some code to show?
Sure, I can try doing a minimum. Is there a good place to put it?
Hastebin or something similar
https://www.toptal.com/developers/hastebin/ugumepuvez.csharp <- Here. Note that the two "Damage" classes are in different namespaces normally
Hastebin is a free web-based pastebin service for storing and sharing text and code snippets with anyone. Get started now.
Forgot to include the actual class being drawn:
[Serializable]
public class AbilityStepList
{
[SerializeReference]
public List<AbilityStep> Steps;
}```
Okay, so I will just go over the things I see since I don't see anything obviously wrong off the bat.
You have a struct Damage and class Damage : AbilityStep this makes it very confusing when looking at the code and much harder to follow. I would rename the class to something like DamageStep for clarity.
Your field naming is also inconsistent which again makes it harder to follow what is going on (plus just looks messy).
You add an ability using direct access to the instance instead of using SerializedProperty. This will make it so it won't support prefab overrides or undo also the change may not be saved since it doesn't dirty the object.
This would be the proper way to do it.
property.arraySize++;
property.GetArrayElementAtIndex(property.arraySize - 1).managedReferenceValue = new Abilities.Steps.Damage();
I was looking for a long time for a way to do add them 😛 Might change it to that.
I know the field names are a bit messy, but I have started not cleaning up my code too much before it works - helps me avoid endless refactoring.
Apart from crashing though, it seems to work fine? I can't figure out why it crashes when I try to set the amount in my damage
Try commenting out damangeLines and Stats in struct Damage, see if it still crashes
Comment out DamageType type in DamageLine
I am pretty sure that is it given the log you posted
Yup, it works when that one is not there
So, what is DamageType? Where is it defined?
Same namespace as the Damage and DamageLines
public enum DamageType
{
Magic,
Physical
}
It's just an enum
Heyo, had a couple of questions. I'm trying to create a selector that uses a popup. don't know how to send the values back to the serialized propery, I tried using a callback when OnClosed but said the property had already been disposed of.
I'll add some info in case someone knows how to do this. Unity seems to do this using a reference to the GUIView and events but this is not accessible. any idea on how to do something similar?
Send an event to the parent Window
@analog grove
window.SendEvent(new Event() { commandName = "mypopup", button = 123 });
Any idea why unity on macos and linux lacks the full PATH environment value of my system?
On windows you get this: C:\Python310\Scripts;C:\Python310;C:\Program Files\PlasticSCM5\server;C:\Program Files\PlasticSCM5\client;C:\Windows\system32;...
Everything defined under the windows' PATH settings are available
On macOS this is all that gets returned by
Environment.GetEnvironmentVariable("PATH")
PATH = /usr/bin:/bin:/usr/sbin:/sbin
Define "lack"
so i've copied this editor script from here (https://docs.unity3d.com/ScriptReference/PrefabUtility.html) to create prefab for me automatically without needing to drag each mesh into the Project folder manually but the resulting prefab created using this tool have a different icon (blue box with grey side). i believe it is a prefab variant(?) and i was wondering if it is possible to create the prefab with the fully blue box instead?
Looks pretty normal to me..?
Things that are the default such as /usr/local/bin not available in Unity.
macOS defines its PATH var from /etc/paths
Probably SaveAsPrefabAsset instead of SaveAsPrefabAssetAndConnect
nothing user installed can be accessed via Process.Start with the Unity provided PATH
tried it, still the same
That's not the Unity provided PATH, that's how osx works
a prefab and prefab variant are pretty much the same right?
Also, you can start user installed apps but they should be available from the commandline as well, which is generally what /usr/local/bin//usr/bin is used for
Variants inherit properties from the parent Prefab, they can also override specific properties but most will be the same as the parent
ehakan@mbp ~ % cat /etc/paths
/usr/local/bin
/usr/bin
/bin
/usr/sbin
/sbin
That's my issue, the PATH should have /usr/local/bin if it actually used the macOS defaults
i see
What does echo $path return?
/usr/local/opt/openjdk@11/bin:/Users/ehakan/grpc:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/share/dotnet:~/.dotnet/tools:/Library/Apple/usr/bin:/Library/Frameworks/Mono.framework/Versions/Current/Commands:/Applications/Wireshark.app/Contents/MacOS:/Users/ehakan/.cargo/bin
how can i make it a prefab instead of a prefab variant though?
I only defined the first two items in my .zshrc, the rest are "system"
kinda ocd about the different icons in my prefabs folder
as in it just gets embedded with every terminal instance
My path doesn't have /usr/local/bin by default, my shell is adding it
Try copying the gameobject (using Instantiate) before doing SaveAsPrefabAsset, not sure tbh I haven't used that api much
alright will try
Thanks for the heads up. I found out about /usr/libexec/path_helper, it's apparently what builds the PATH value for shells, invoked in /etc/profile. Bodged this together
public static void LoadMacOSDefaultShellPaths()
{
using (var process = new Process())
{
process.StartInfo.UseShellExecute = false;
process.StartInfo.FileName = "/usr/libexec/path_helper";
process.StartInfo.Arguments = "-c";
process.StartInfo.RedirectStandardOutput = true;
process.Start();
var stdout = process.StandardOutput.ReadToEnd();
process.WaitForExit(30000);
if (!process.HasExited)
{
Debug.LogError($"'/usr/libexec/path_helper -c' timed out, killing the process");
process.Kill();
return;
}
if (process.ExitCode != 0)
{
Debug.LogError($"'/usr/libexec/path_helper -c` failed with exit code {process.ExitCode}");
}
Debug.Log($"/usr/libexec/path_helper output = {stdout}");
// assert if the output is of expected format 'setenv PATH "...."'
var args = stdout.Split(' ');
if (args.Length != 3)
{
throw new Exception("Outputs incorrect");
}
var paths = args[2]
.TrimStart(new char[] {'"'})
.TrimEnd(new char[] {';'})
.TrimEnd(new char[] {'"'});
Environment.SetEnvironmentVariable("PATH", paths);
}
}
Hi! how can i do a "CreateAssetMenu" that creates a class inheriting from another class of mine? (ie i've got an ActionBase class, and i want a button in assets/create/New Action to create a new action script inheriting for ActionBase by default?
The little things)
CreateAssetMenu is just a MenuItem that creates a SO for you, so you can just create your own static method with MenuItem that makes an SO at some location
oooh okok :)
Thanks!
I'm not sure what exact source is but there's probably a bunch of examples online
It won't give the exact same functionality but it's similar
Very interesting, thanks for letting me know!
don't worry, i figured :)
Anyway, can i enter like... "Renaming" state for a selected object...? lol
ProjectWindowUtil.CreateAsset(asset, assetPath);
I should've etold you about this one before probably
this seem pretty convenient 
thanks!
what if i want to load all the scriptables inside a folder (that i've got the path too)?
AssetDatabase.LoadMainAssetAtPath doesn't seem to be working
Working to do what?
to load all the scriptables inside a folder (that i've got the path to)
It only loads one asset, and it needs to be the full asset path
Assets can have sub-assets, that is what it refers to when it says "MainAsset"
yeah, like sprites right
so what if i want to load all the scriptables inside a folder (that i've got the path to)?
You use Directory.EnumerateFiles and load each one at a time
note that all System.IO methods take a full path and not one relative to the project. Likewise, all of Unity's AssetDatabase methods require a path relative to the project
bruh
But i can get the unity path to asset with someething right? Like assetdatabase.ProjectPath?
what?
What what?
You can use Application.dataPath to get the system path to the Assets folder
Methods in System.IO does not require a full path, they can take any path
if I ask for Directory.GetFiles('.') it works
But you can't do like Directory.GetFiles("MyProject/Assets"), right?
You can't, because the current Directory is set on the projecct path, so it would accept "Assets", "Library", "Temp", etc.
You are making me doubt, but I am 99% sure it is
Well now you are making me doubt too because I was like 98% sure...
The thing is, System.IO is .NET, not Unity
And now that I am think about it, I'm 100% sure
it takes whatever you give it
be it absolute, relative, network
hmmm so any solution?
Was it a prefab already?
i assume it is? it's a mesh
Then yes it will be a prefab variant. That is expected
That way if the mesh changes it will update as well
how can i make it an original prefab though?
hmmm
when i drag the mesh into the folder, i get an option to either make it an orginal prefab or a prefab variant
how does unity make it into an original prefab from there?
instead of a variant
I don't do much with the prefab API, but my guess would be to use UnpackPrefabInstance first
https://docs.unity3d.com/ScriptReference/PrefabUtility.UnpackPrefabInstance.html
I should say that unless you have a specific reason for doing this, the recommendation is to make it a variant of the model instead
alright
one more thing, is it a must for the editor script to inherit from Editor? i remember watching some videos regarding creating custom tools and some of their script(s) doesn't inherit from Editor at all
Nope, not at all. You only inherit from Editor if you want to create a custom inspector (change the way a component or scriptable object is drawn in the inspector)
i see i see
cause currently i am inheriting from Editor but the script itself isn't for a custom inspector, rather it is for a menu item instead
Yep, no need for it then
what if i'm inheriting from Editor just so i can use DestroyImmediate?
right now once i create the prefab(s), i want to delete the selected gameobject(s) from the scene
No need, DestoryImmediate is a static method
Object.DestoryImmediate(yourObjectInstance);
https://pastebin.com/tAwaLeae 0.48 KB
//I can't save my scene particle effects into the project if I do this. It unlinks the Particle->Renderer->Material to null
//How would I be able to save my scene particle effect into my project properly if I want to change the material on runtime?
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.
I think I need to write an editor extension to make new materials maybe on the fly?
A better question is: If I instantiated something in UNITY play, how do I save the result as an asset into my Project Assets?
iirc it should be the same as during edit mode. Just AssetDatabase.CreateAsset(..)
However I could be wrong on this one, I don't remember for sure
yup
https://docs.unity3d.com/ScriptReference/PrefabUtility.html for game onbjects
AssetDatabase.CreateAsset for non game objects
this is awezome!
heyo, just a quick question, is there a better way to get the window in which the propertydrawer is being drawn on, other than getting the focused window?
There is if you want to use some reflection. UnityEditor.GUIView has a static currentView property.
I know about that one but it's internal, guessing that's why i need Reflection. Is it okey to use for packages??
...what?
lol sorry, wrong copy paste xD edited
It is 'okay'. Just be aware that in a future version it might change because it is internal.
With that said, that one should be very save unless they do a massive rewrite of the internal window system
oh okey, yeah i can just have a failsafe and it should be okey. Guess I'll learn some reflection then
Go learn go learn little padawan
Thanks ill try
hi! how do i know if an .asset exists at some path?
do i need to do like a try catch maybe?
cuz i just tried this:
ScriptableCharacterList CharList = ScriptableObject.CreateInstance<ScriptableCharacterList>();
try {
list = AssetDatabase.LoadAssetAtPath<ScriptableCharacterList>("Assets/SCOLAssets/CharacterScriptables/CharacterList.asset");
} catch {
AssetDatabase.CreateAsset(CharList,"Assets/SCOLAssets/CharacterScriptables/CharacterList.asset");
list = AssetDatabase.LoadAssetAtPath<ScriptableCharacterList>("Assets/SCOLAssets/CharacterScriptables/CharacterList.asset");
}```
And somehow it's not creating anything
(my class doing this is editor only and static)
(well, the class itself isn't static, but all the other things in it are (including this "list" variable))
Help me i feel like i'm doing totally illegal things
ScriptableCharacterList CharList = ScriptableObject.CreateInstance<ScriptableCharacterList>();
try {
//If the list already exists, we just say it's THE list
ScriptableCharacterList.Instance = AssetDatabase.LoadAssetAtPath<ScriptableCharacterList>("Assets/SCOLAssets/CharacterList.asset");
} catch {
//If it doesn't, create it... And tell it's THE list
AssetDatabase.CreateAsset(CharList,"Assets/SCOLAssets/CharacterList.asset");
ScriptableCharacterList.Instance = AssetDatabase.LoadAssetAtPath<ScriptableCharacterList>("Assets/SCOLAssets/CharacterList.asset");
}```
(That is trying to turn a scriptable object into a singleton  )
How can access the "Validate References" field of a .dll through an editor script? I get the PluginImporter for the asset but I'm not sure on how to set the "validate references" field?
You might have to do Assetdatabase.refresh
oh, yeah
when i createAsset(), right?
After it
I think I've just deserialized the json in the past
yup, thanks! i'll try that
is it possible to get serialized property on MonoBehaviour OnValidate method?
I had a bug overriding OnInpectorGUI and wanted to use another way to access my ExposedReference
but I solved
how can I change the color of the unity button? ```css
.unity-button
{
background-color: #000000;
}
SerializedObjectNotCreatableException: Object at index 0 is null
happen on line _assetProperty = this.serializedObject.FindProperty("asset");
of this script every time i enter in playmode
public class TableReferenceEditor : UnityEditor.Editor
{
private SerializedProperty _assetProperty;
private SerializedObject _assetObject;
private void OnEnable()
{
if (serializedObject != null)
{
_assetProperty = this.serializedObject.FindProperty("asset");
SetAssetSo();
}
}
there is a workaround?
SerializedObjectNotCreatableException Error in Unity ( Solved ) | Serialized Object Not Creatable
For Advance Unity Tutorials and Live sessions you can Join Our Channel.
http://bit.ly/2N54fgc
👇👇👇👇👇👇👇👇
Learn Unity Game Development with deep concept with US -
https://www.youtube.com/channel/UCXKkwWoBY_sK6LtIFFmB46Q
👇👇👇👇👇👇👇👇
Ask any question on...
is it possible to fire event on collection change?
I mean when add and remove item from an array
in a CustomEditor
Hey guys! I'm creating an editor tool that will create a bunch of assets using AssetDatabase.CreateAsset and also prefabs. Problem is that operation is taking way too long... I've tried using AssetDatabase.DisallowAutoRefresh(); but to no avail... Is there anything else I can do?
AssetDatabase.CreateAsset(material, Path.Combine(meshPath, $"{filter.gameObject.name}.mat"));
AssetDatabase.CreateAsset(filter.mesh, Path.Combine(meshPath, $"{filter.gameObject.name}.asset"));
var partPath = AssetDatabase.GenerateUniqueAssetPath(Path.Combine(meshPath, $"{filter.gameObject.name}.prefab"));
PrefabUtility.SaveAsPrefabAssetAndConnect(filter.gameObject, partPath, InteractionMode.UserAction);
Found a solution... AssetDatabase.StartAssetEditing(); and AssetDatabase.StopAssetEditing(); will do the trick
Hey can someone help me? I've never written anything for the editor, so I'm a little lost on where to begin.
I'm trying to write some code that will let me change the colors for: selected polygon colliders, awake polygon colliders, selected box colliders, awake box colliders
I want these 4 things to be different colors so I can quickly tell what I have selected, and what the other colliders in my scene window are without clicking through the hierarchy
I can enable always show colliders in the project settings, but the problem with that is, everything is the same color, even colliders I have selected, so I cant tell what it is I'm editing
I'm currently trying to create an instance of a custom editor script via CreateEditor(object, type). However, this function only seems to create the base "Editor" class, and trying to cast it to my custom editor type fails. I've double checked all the necessary attributes and inheritance setup, but have had no luck. Has anyone else encountered this problem before?
is it possible to add custom game objects context menu item?
[MenuItem("GameObject/HelloWorld", false, 10)]
public static void CreateTextArea()
{
GameObject go = new GameObject("Name");
}
alright based
Guys I need your help. I have an assignment to get a job.
I need to setup a connection with this thing:
https://github.com/PokemonTCG/pokemon-tcg-sdk-csharp
an just make a game with it.
My Visual studio 2019 whenever i try to install the package:
Could not install package 'PokemonTcgSdk 1.1.1'. You are trying to install this package into a project that targets '.NETFramework,Version=v4.7.1', but the package does not contain any assembly references or content files that are compatible with that framework. For more information, contact the package author.
So I downloaded the 1.1.0 version
My new error is that now that I have the new classes etc when I try to test em in Unity I get this error: (Only in Unity not in the VS console)
Assets/GameManager.cs(4,7): error CS0246: The type or namespace name 'PokemonTcgSdk' could not be found (are you missing a using directive or an assembly reference?)
I suspect that it is the SDK version but I cant locate where to select the one I use plus I think my VS is buggy all along.
P.s I use Mac
Help please
I really don't know how everything works on mac, i'm using endeavourOs and I had some similar problems when installing from different repos, f.e. vsCode installed from flathub wouldn't be able to locate .Net. from aur. This is probably unrelated, just trying to help.
hi people, I've been trying to figure out how this is done but I'm not really finding a way. I basically want to make a search bar. The code works, but I would like to make it 1. prettier and 2. a bit more functional by having a search icon and when text is present have a cross to delete, sort of like the hierarchy tab. Does anyone know how to add these icons to the text field?
Hi, is there a way to step thru the code the unity editor executes at certain times? I'm specifically try to go through the asset (model/fbx specifically) import process to get a better idea how to customize I. I find the unity docs concerning it to be pretty vague on a lot of things, at least to a unity young'en like myself
so... I have very little property drawer experience, but I was working on a SmartEnum implementation for Unity with a property. Recently was playing with it and realized that it didn't work in the case that fieldinfo was a List.
{
//Begin Property
EditorGUI.BeginProperty(position, label, property);
//Get Current Value
var smartEnum = (SmartEnum)fieldInfo.GetValue(property.serializedObject.targetObject);
//Get All Other Possible Values
var enumList = SmartEnum.GetValues(smartEnum);
//Get Current Index
var i = enumList.IndexOf(enumList.FirstOrDefault(x => x.Equals(smartEnum)));
i = (i < 0) ? 0 : i;
//Make Possible Values into List
string[] options = enumList.Select(x => x.ToString()).ToArray();
//Do a Popup and Get Selection
var j = EditorGUI.Popup(position, property.displayName, i, options);
//Set Value to Current Selection
fieldInfo.SetValue(property.serializedObject.targetObject, enumList[j]);
//End Property
EditorGUI.EndProperty();
}
Was wondering if anyone could give me some ideas or help on making this Array or List Compatible?
What exactly is not working?
It is not Array Compatible, when I make a List<SmartEnum> it breaks
The Specified Cast at
var smartEnum = (SmartEnum)fieldInfo.GetValue(property.serializedObject.targetObject);```
is invalid
it is a List<SmartEnum>
That is the problem. I want it to work within Lists.
(or other serializable array types)
oh shit, I think I figured it out
was [CustomPropertyDrawer(typeof(SmartEnum), true)], that true shouldn't be there
Wait nvm, that just breaks the styling
Hi,
i have a script that introduces own fields in the inspector, by using [SerializeField] private Material glowMaterial;
The inspector then takes "glowMaterial" word and forms the field name of it, resulting in "Glow Material".
How could i set the field name in the inspector to a different name, i.e. "Material" only?
This will break alot. If you have a SmartEnum in another class that is a field of a UnityEngine.Object, or as you see is in a list
I am not sure what the alternative ought to be, that is the issue and getting information on this stuff is archaic
You're 'not supposed to'. I have an implementation on github of how to get the value. You can just grab and use it if you want
https://github.com/MechWarrior99/Bewildered-Core/blob/main/Editor/Extentions/SerializedPropertyValueExtensions.cs
Basically you have to split the path of the property and get the value of the field of each property in the path
nice, going to add it as a package dependency, as it is lightweight enough
btw, do you support https://github.com/mob-sakai/UpmGitExtension#usage ?
I will say, idk what the structure of SmartEnum is, but I don't think you need to do it the way you are
A SmartEnum is a pattern for Enums, wherein it looks like this:
{
public static readonly TestEnum One = new TestEnum(nameof(One), 1);
public static readonly TestEnum Two = new TestEnum(nameof(Two), 2);
public static readonly TestEnum Three = new TestEnum(nameof(Three), 3);
private TestEnum(string name, int value) : base(name, value)
{
}
}```
It allows for certain benefits. Such as Injectability, attaching values, and preventing extension
Not explicitly, from reading it, it seems like it should just work?
until unity enforces its own standard for git packages, this seems to be one of the most popular versions to do versioning...
Ugh, Unity devs, if you can hear me, please just integrate whatever this guy did into your package system by default.
I could be wrong, but I don't think this will work
The reason being that Unity serializes everything as a value and not a reference.
So doing myTestEnumField == TestEnum.One would be false
I think
I overwrite the == function
SmartEnum is direvative of IEquatable<SmartEnum>
I just check if value is equal
Oh, got it
It would be best if you could recreate the assignment logic using SerializedProperty as assigning values using FieldInfo has a number of drawbacks.
Doesn't dirty the object(may not save unless something else changes), doesn't support undo, doesn't support prefab overrides.
You can use the [InspectorName("Material")] attribute.
Edit: My bad it seems this is only for enums. Sorry
Unity is Unity, there is a ton of stuff that I wish it had built in so I wouldn't have to hack to get around it.
And of course, there is the whole problem of developing a solution and then someone out there rediscovers your problem and can't solve it, because you aren't at the top of search results
anyway, none of this is relevant to this channel so I am going to stop
thx for help
Thank you for getting back to my question! I tried using this but maybe i am using it wrong? I did it like this:
[SerializeField] [InspectorName("Material")] private Material glowtMaterial;
Looks like there isn't a way. Either custom editor, or just rename the field.
After googling more on your answer, i found this: https://docs.unity3d.com/ScriptReference/InspectorNameAttribute.html
This looks to be the solution, but i do not understand the implementation
It turns out it only works for enums, not fields.
ohh ok 😕
Ok atleast i now know there is no way to achieve this, i was stuck on this for an hour about and finally can move on. But i think i will place this as feature request at unity's
@gloomy chasm Thank you for your help ✌️
I'm having issues with handling selective click events in a property drawer
I'm making a PropertyDrawer that is an object field, but it has extra height for drawing other fields below.
I want to consume the event selectively if I click on the area that is not the object field
as you see in the GIF, the object field's context menu appears when clicking in any area of the entire drawer (that doesn't have another field)
so I basically want to consume the event and not show the context menu when I right click on the area highlighted in red