public void SetThumbnail()
{
var prefabSObject = (LayeredCharacterBehaviour)sProperty.serializedObject.targetObject;
using (var prefabSerializedObject = new SerializedObject(prefabSObject.gameObject))
{
var iconProperty = prefabSerializedObject.FindProperty("m_Icon");
var rtex = prefabSObject.Render(100);
iconProperty.serializedObject.
rtex.Release();
}
}
#↕️┃editor-extensions
1 messages · Page 90 of 1
iconProperty.serializedObject.* is where I'm stuck
I can't call any methods against the target object because it's null
Firstly do a debug.log on sProperty.serializedObject.targetObject to see what it is.
Secondly, you don't do anythng with iconProperty.serializedObject
you have the property, now you set the value of the property like you would any other property.
iconProperty.objectValue = myTexture (not exact name but it will get you close.)
It's a LayeredCharacterBehaviour
Ok. This is going to be a bit more complicated than I thought. The render method assumes that the prefab has been instantiated/imported into a scene.
Is there a way to get the object's preview that appears in the scene view?
How do you create a array of strings for a custom inspector? I know how to create an array of Sprites & GameObjects (Thanks to this tutorial video: https://youtu.be/RImM7XYdeAc) but I can't figure out how to create one for a string. I feel like the answer is staring me right in the face but I wasn't able to find it. Any help would be greatly appreciated!
(EXPLAINED IN DETAIL) Create YOUR OWN custom inspector, lists, and multiple variables per line and much more! with Unity in C#
Please if anyone can help me, I am completely lost here.
the way this person is doing it is really unnecessary
all you need to do to draw anything is to use SerializedProperty.
SerializedProperty stringArray;
void OnEnable () {
stringArray = serializedObject.FindProperty("stringArrayVar");
}
void OnInspectorGUI () {
serializedObject.Update();
EditorGUILayout.PropertyField(stringArray);
serializedObject.ApplyModifiedProperties();
}```
^pseudocode, I have not tested it
Oh my geez thank you! I knew I had to of been overthinking it or doing something wrong. This is so much better!
EditorGuiLayout.PropertyField(property); doesn't take into accout custom PropertyAttribute added to this property. How to draw property field so its drawn as PropertyAttribute defines?
You don't, or you use reflection to get the attribute yourself.
I'm confused, if you have a property drawer or decorator added to a property it should draw fine when using a property field
That's half the point
the name of one of my scripts is RainersTextMeshEditor, cause this script edits the text mesh.
Then I decided to create a custom Editor for the Inspector to inspect that first script.
Can u guess the name of the Editor Script? 😁
Hint: my naming skills are incredible
Answer: ||RainersTextMeshEditorEditor||
after creating a editor for a script how can i support multi object editing?
[CanEditMultipleObjects]
here me knows the answer 🙋♂️
😦
this does shows the script variables in inspector but when i press a button which is made by GUILayout.button it only runs for the first selected object
I assume because you are only calling it on target and not targets 🙂
AdvancedDropdown is too powerful! I overrides the UnityEventDrawer to have the methods searchable!
Be humbled by the strength of my mighty wizardy powers!!
I got searching by control label to work in the inspector for IMGUI! 😄
@onyx harness
Clearly it is an early prototype, and kind of laggy right now. But the point is that it works!!!
Oh now I understand what you meant, it works for CustomEditor?
Should do as long as they use EditorGUI.PropertyFields.
I think I can change the checks I am doing so it works for most GUI controls, not just PropertyFields.
Oh good, so... You look for drawn controls and overdraw?
Basically yeah. I get IMGUI Instructions which provide both the label and the rect. Then I just add VisualElements that cover the controls that don't contain the search string.
Like 75+% of the code is reflection/using reflected members xD
@gloomy chasm very fine very gut
is there another way to write something like if (enumDirectoryIndex == default) for if a variable of an int hasn't been set yet? ! and null don't work of course in this situation, but, I'm wondering if the default will ever give me issues after setting the SO dirty
There is no such thing as 'hasn't been set yet'. Unity serialize everything* to to a value type, and even if that wasn't the case, ints are value types so will always be the default value if not explicitly set.
enumDirectoryIndex == default is the same as enumDIrectoryIndex == 0. It just gets whatever the default value is of the type.
oh, perfect, thanks for letting me know
I'm going to set the default value to -1 then
- UnityEngine.Object fields are serialized to a reference type along with fields with the
[SerializeReference]attribute.
default returns the default value for the type just so you know.
yeah, that's what I wanted to make sure, so that if I have a default value hardcoded into something, it will result in that default value even after a setdirty, and that the setdirty isn't the new default
is there anyway I can use EditorApplication.hierarchyChanged to only react if it's a folder that was added or deleted?
No, that is only for the scene hierarchy.
This is what you want https://docs.unity3d.com/ScriptReference/AssetPostprocessor.OnPostprocessAllAssets.html
yeah, I just saw that while I wasking haha
thanks!
oh I think its If you perform a bulk operation on several individual assets instead of a folder containing those assets, this function will be called once per asset with each individual asset as the only item in the various arrays.
There are a number of differences beyond the fact that OnPostAllAssets gives you info about what assets changed, it is also called less often. I think only on save/import. I don't remember specifically. I just put debug.logs in both and see when they are triggered 😛
yeah, I'm doing that atm! I think I can also do a type check on the returned path where I can do something if that type is a defaultasset and a validfolder if I'm understanding this correctly
Iirc there are 4 separate callbacks/messages/events that are call at various points when an asset changes (not including both pre and post process)
got it all setup, this works beautifully. Thank you
Hey! I'm not sure if this is the right place to ask about this, but I cannot get intellisense to work at all with VS Code
#854851968446365696 see if that helps
I've followed all those steps, and i've watched youtube videos about it
It just doesn't seem to want to work
if you have done everything in these guides and still doesn't work, try restarting your Omnisharp. That is at least how I fix mine not working sometimes. On mac I do command + shift + p and select restart Omnisharp in the commands box
if you use github integration stuff also, make sure you have pushed changes if you are over the allowed amount github lets you push
it will break it also
I'm on windows and there's no command for restarting Omnisharp
And i'm not using github integration either
ctrl + shift + p is the windows shortcut
type restart omnisharp and it will show up
if it doesnt that is your problem
you don't have omnisharp
I see, how would I go about getting omnisharp?
Oh wait, it was saying c# was installed but it wasn't
https://code.visualstudio.com/docs/languages/csharp see if this helps at all
again works fantastic, but, I just like to double check with you on sloppiness of code lol
is what is referenced. I know I could just make changes to the list based off delete and stuff now rather than clear, but, I heard somewhere that clearing lists isn't necessarily a bad thing?
Why are you storing all asset paths?
allowing a person when creating an enum through this method to select where they want to have the enums directory
Why not just use the normal OS save window.
I'll look into what that is, but, what I'm trying to do essentially is allow whatever method people use, through either creating it through the editor window or dragging things around in the project, everything is still referenced, so, if multiple hands on, there isn't confusion on now where something may or may not be etc...
I don't really grasp what the whole architecture of your code is, but from what I can see of it and what you have said, it seems to me that you are trying to be too clever and making it less performative and messier.
I'm not sure exactly what you mean? What I'm doing is more intense, but, I'm trying to create something that people can used, and not just say they are SoL if they break something and instead put as many preventive measures as I can in place
Ok. I'm debugging the code to change the icon using m_Icon, and it looks like prefabSerializedObject.FindProperty(m_Icon) returns a serialized object whose serializedObject.targetObject is not the m_Icon, but UnityEngine.GameObject.
Not too sure if that belongs in here or in one of the code channels, but is there a way to make a specific warning not show up in my Console? 😅
from my understanding, you have to jump through a lot of hoops to do so. Would probably be easier to just fix the warning
Damn, i get a warning for every serialized field on a MonoBehaviour that I don't initialize on declaration
🥴
I made myself the habit to just give every field an initial value, as you suggested, but it's getting really annoying and ugly to do that all the time
I suggested?
idk what you are talking about if you don't mind posting SS of your errors
"just fix the warning" is what I meant with suggested, that's what I've always done in the past, but it's getting annoying and ugly
CS0649, just making empty MonoBehaviour with a [SerializeField] of any Type, without initial value, and it shows up
As in
[SerializeField] private float someValue;
Resulting in a warning
also, have you tried https://docs.unity3d.com/ScriptReference/RuntimeInitializeOnLoadMethodAttribute.html?
trying writing it as
[SerializeField]
private float someValue;
I've never wrote it on the side like that, so idk if that results in an error
It doesn't 😀
Basically, Unity wants me to do
[SerializeField] private float someValue = 0f;
Instead of
[SerializeField] private float someValue;
Thats kinda tedious
You can use #pragma warning disable 649 and #pragma warning restore 649 around the field to disable it for that field/fields.
U are awesome, tyvm, exactly what I needed
I can't even replicate the error so I'm sorry 😦
when I do exactly what you type I get 0 errors lol
Unity trolling me 🤣
It returns a SerializedProperty... you need to do .objectReferenceValue to get/set the value... It may be a good idea to read up on the docs on serialized objects and properties.
Your welcome. You could also just set the fields 😛
Right, but this is supposed to be the result of the property for m_Icon. And when I see it in the debugger it's null. I assign it new Texture2D(512, 512); and it's still null afterwards.
I did so in the past, but it's getting so annoying, and I also need to do it for serialized fields in structs which is not possible 😩
But I tested the pragma and it obviously works perfect, and I prefer writing those 2 lines over initializing 5+ fields :grinning:
Do you apply the change?
Structs shouldn't give the warning...
LOL 5 fields. You can also just do = default; so you don't have to think about the proper type.
They do in my case, I have no idea why I get that warning for anything, it started popping up on a new device, it was fine on my old
I understand that warnings shouldn't be disabled in most cases, but even =default would be annoying for every serialized field in any project :grinning:
To each there own I guess. Just making it a habit when declaring the fields and it makes it not too bad imo.
It's probably because you updated unity version. If you want to ignore that warning permanently you can make a file called csc.rsp and put it in Assets/ in the file add -nowarn:0649
Yea, but still, the struct thing....
Will try it out, tyvm!
This will remove the warning from all scripts. Keep in mind "correct" CS0649 warnings will be removed as well.
Good point, I'll use it for now and will try to fix that warning as soon as possible
Yeah well, it's up to you. Personally I just keep it permanently disabled.
you mean iconProperty.serializedObject.ApplyModifiedProperties()?
I got 156 error logs
public void SetThumbnail()
{
var prefabSObject = ((LayeredCharacterBehaviour)sProperty.serializedObject.targetObject).gameObject.GetComponent<LayeredCharacterBehaviour>();
using (var prefabSerializedObject = new SerializedObject(prefabSObject.gameObject))
{
var iconProperty = prefabSerializedObject.FindProperty("m_Icon");
iconProperty.serializedObject.ApplyModifiedProperties();
var activeRenderTexture = RenderTexture.active;
var rTex = RenderTexture.GetTemporary(512, 512, 16);
RenderTexture.active = rTex;
GL.Clear(true, true, new Color(0.3f, 0.3f, 0.3f, 1.0f));
view = SceneView.lastActiveSceneView;
view.camera.targetTexture = rTex;
view.drawGizmos = false;
// view.camera.rect = new Rect(/* this should be the rect around the character */);
// view.camera.forceIntoRenderTexture = true;
view.camera.Render();
iconProperty.objectReferenceValue = new Texture2D(512, 512);
iconProperty.serializedObject.ApplyModifiedProperties();
var iconTexture = iconProperty.objectReferenceValue as Texture2D;
var iconData = rTex.ToTexture2D();
var iconArray = iconData.GetPixels32();
iconTexture.SetPixels32(iconArray);
iconProperty.serializedObject.ApplyModifiedProperties();
view.drawGizmos = true;
view.camera.targetTexture = null;
RenderTexture.active = activeRenderTexture;
RenderTexture.ReleaseTemporary(rTex);
}
}
ToTexture2D is an extension method provided by Naninovel to get the pixel data on a render texture
and return it as a Texture2D
I did originally have it at one location, but now I have it in several
Just because I don't know what needs to be applied before it will work
can i create this kind of popup using editor? my tool generates scriptable objects i want to show this popup until my tool finishes
private static void HandleHierarchyWindowItemOnGUI(int instance_id, Rect selection_rect)
{
var content = EditorGUIUtility.ObjectContent(EditorUtility.InstanceIDToObject(instance_id), null);
if (content.image != null && !IgnoreIcons.Contains(content.image.name))
{
GUI.DrawTexture(new Rect(selection_rect.xMax - 16, selection_rect.yMin, 16, 16), content.image);
}
}
The method EditorGUIUtility.ObjectContent has begun returning contents with image == null for all my custom icons on game objects in 2020.3.11 (thereabouts), it definitely worked in earlier 2020.3 versions, so... what changed?
The icons are visible in the editor, but I want to do something as I draw the hierarchy.
I also noticed inbuilt icon names changed, from "GameObject Icon" to "d_GameObject Icon", for example.
The default icons (those colored circles etc.) are still being returned.
Missing icon right there, even though it's there in the inspector and sceneview Gizmos. You can also see two default icons (yellow and grey) showing up. I am ignoring all prefab icons etc.
yep that is it thanks
Hello everyone!
Does anyone know if it's possible to edit Unity engine provided DLLs without breaking the license? Or is it against Unity license?
I need to add callbacks to some parts of the engine but I don't want to violate the license.
Thanks
Not allowed.
Thanks for the information, I'll find another way!
Is there an editor API available that does the exact same thing as when double clicking a gameobject in the Hierarchy (so that the scene view is centered on the gameobject by either zooming in or out)?
SceneView.AlignViewToObject
Yeah, I'm trying to modify a prefab's icon. So far no dice.
Is it possible to somehow override the default drawer for UnityEngine.Object fields? I am looking a ScriptAttributeUtility but can't find where they could be calling the drawer for it.
Thanks, will test! 🙂
I would say yes
That is what I was thinking, but as I am looking at the code, it should work to just make a custom property drawer for Object like normal. But it doesn't...
But a PropertyDrawer does not override?
Oh I see, that was foolish of me. So it does override, I just was looking at the inspectors for the Directional Light to see if it worked or not assuming that they had used PropertyField for the fields.
So it does work, sorry and thanks.
All the default inspectors for the older components like the MeshFilter, MeshRender, Light, etc don't use PropertyField so it doesn't even feel like there is a point in making a custom drawers for Object types 😦
is there a way to customize the objectpicker?
I guess maybe through https://docs.unity3d.com/ScriptReference/EditorGUIUtility.GetBuiltinSkin.html?
No, there isn't. Well, I guess you could get the window when it opens and add VisualElements to it.
You can use Harmony to modify it, but that is less than completely legal. But still used quite a bit.
Meh, okay, I guess instead I could imitate what I want after reading some of these docs with popup and EditorGUIUtility.PingObject
What is it that you want?
I was changing the way someone could select a path to EditorGUILayout.ObjectField as a DefaultAsset, but, found that if someone were to select a folder through the ObjectPicker it could be kinda messy. For example, right now if I click on mine, I have lets say 15 Animation folders that show up. If you click on every single one you can see the paths to make sure you select the right one, but, was hoping to remove having to select every one
What I do is make a FolderReference class and make a PropertyDrawer for it and show a treeview of all the folders in the project.
I haven't done anything with PropertyDrawer yet, so I'll look into that!
Oh, that is pretty cool
just checking out the page
So, could you do the [CustomPropertyDrawer(typeof(Object))] and break everything? 😄
Yes
Not everything, just fields that are of type Object 😛
No, just fields. So things like public GameObject _parent; public Texture2D _icon;, but not public int _count; or public Vector3 _direction;
Fields yes, but that's everything that doesn't derive from System.Object or System.Struct
All it really is is components, textures, gameobjects, scriptableobjects, or anything that is an asset. If you look at most serialized fields it is actually a smaller number usually that are one of those types, compared to all other types.
why is my popup way up there?
thought the editorguilayout was suppose to automatically have it popup at the button so you didn't have to mess with rects and stuff
Think that's an os bug and not a unity bug
Ok. I notice that managedReferenceFieldTypename gives me an InvalidOperationException because it is PPtr<Texture2D>
objectReferenceInstanceIDValue is -228968 and objectReferenceValue is null
okay! Well, good to know! Because I've been looking for hours on how to fix it lol and am doing like everything so was really mind boggled
I am having a problem with a custom inspector. I want to have the editor class in the same script as the reference class, but when I try to set a public variable to reference in the editor then both the reference class and the custom inspector show the public variable.
Is there any way that I can hide the reference classes public variables without it breaking the editor class and custom inspector?
I have already tried setting the public variable that's being referenced as private but that just causes serializedObject.FindProperty("testingString"); to fail to find the variable.
anyone have experience writing a custom foldout in UIElements in C# and/or UXML?
What is there to write? There is a Foldout element.
I've been trying to figure out how to place an object field inline with the foldout toggle
Oh yeah, that is not possible iirc
I ended just making my own for whatever my use-case was when I needed that.
Just make an element with a toggle and a VisualElement as children and change the display style of the VE container based on the toggle.
yeahhhh, essentially using the object field in place of the label text in the foldout. Then selecting a scriptable object with the field and populating the foldout with the scriptableobjects properties. Right now I'm not focused on the ScriptableObject part. Just the ui structure
I was running into issues on this because I think Toggle prevents you from adding an object field within it
I think I'm just confused on the hierarchy. Does Toggle serve as a parent to everything else in the foldout?
Nah, it would be like
>CustomFoldout
|>VisualElement #header
||>Toggle #foldout
||>Label #foldoutName
|>VisualElement #contentContainer
||>...contents of foldout go in this element...
Got it. So I'll just replace that #foldoutName Label with an object field..?
Sure. You can even add the foldout uss class name to a specific child of the toggle to get it to look like a foldout (I don't remember which child and which class. Just take a look with the debugger and test out, you will figure it out.)
Heyas,
I've extended the Unity UI Button a bit, and have scripts that inherit from that extension.
GenericButton -> ButtonExtended -> Button (from UnityEditor.UI)
This all works fine, except to show them in the inspector I need to have a custom Editor or the Unity Button part doesn't show (for some reason). The Editor script for GenericButton is as follows:
public class GenericButtonEditor : ButtonEditor {
public override void OnInspectorGUI () {
serializedObject.Update ();
ContentToDisplay ();
serializedObject.ApplyModifiedProperties ();
base.OnInspectorGUI ();
}
private void ContentToDisplay () {
/* content stuff */
}
}```
The editor script for ButtonExtended is identical, except with different logic inside of ContentToDisplay().
The Inspector shows the content for GenericButton and UnityEditor.UI.Button, but not the ButtonExtended. So the middle part of the inheritence is not being called (Debugs in ButtonExtended aren't called either).
Does anyone know why this is, and how to solve it? Thanks in advance.
just in case you did not find a solution jet
https://docs.unity3d.com/ScriptReference/HideInInspector.html
So if you have a GenericButton you want it to show the content from the ButtonEditor stuff too?
Yeah, the ButtonExtended adds some utility to the unity button that's useful in general for my game, and the GenericButton adds some stuff for the setup for a specific set of buttons.
Try calling base.OnInspectorGUI() at the top...?
I feel like I know why it isn't working for you, but I can think of the reason...
It should work though...
Didn't change anything, except for the order in which the GenericButton and unity Button appear in the inspector. :c
MechWarrior99: So I'm kinda stuck. I'm still working on this preview thumbnail icon and I get a supposedly valid property, but property.type is PPtr<Texture2D> and property.objectReferenceValue is null. This is the code I have so far:
public void SetThumbnail()
{
var prefabSObject = ((LayeredCharacterBehaviour)sProperty.serializedObject.targetObject).gameObject.GetComponent<LayeredCharacterBehaviour>();
using (var prefabSerializedObject = new SerializedObject(prefabSObject.gameObject))
{
var iconProperty = prefabSerializedObject.FindProperty("m_Icon");
iconProperty.serializedObject.ApplyModifiedProperties();
iconProperty.serializedObject.forceChildVisibility = true;
var activeRenderTexture = RenderTexture.active;
var rTex = RenderTexture.GetTemporary(512, 512, 16);
RenderTexture.active = rTex;
GL.Clear(true, true, new Color(0.3f, 0.3f, 0.3f, 1.0f));
view = SceneView.lastActiveSceneView;
view.camera.targetTexture = rTex;
view.drawGizmos = false;
view.camera.Render();
// iconProperty.objectReferenceValue = new Texture2D(512, 512);
// iconProperty.serializedObject.ApplyModifiedProperties();
var iconTexture = iconProperty.objectReferenceValue as Texture2D;
var iconData = rTex.ToTexture2D();
var iconArray = iconData.GetPixels32();
iconTexture.SetPixels32(iconArray);
iconProperty.serializedObject.ApplyModifiedProperties();
view.drawGizmos = true;
view.camera.targetTexture = null;
RenderTexture.active = activeRenderTexture;
RenderTexture.ReleaseTemporary(rTex);
}
}
I'm asking you because I don't know anywhere else to look up this information
setting the objectReferenceValue = new Texture2D(512, 512); doesn't work at all.
Never mind; figured it out. I had one of the type names reversed. 🙄 You'd figure I'd notice that after an hour of staring at the code. But no.
Sometimes the code needs a fresh set of eyes. I stopped working on a tool I was building for a couple weeks because I felt burned out trying to figure it out. And then I was able to notice things wrong with my code that I didn't see a couple weeks before
I'm wondering if I need to do that with my code above but I feel like the code itself isn't wrong per se, in like some way that I'll figure out by stepping away for a week or two. But rather that there's something about the underlying API that I don't know or understand
So far, I can get it to work in terms of generating the preview, but all it does is put a tiny version of that preview in the center of the canvas.
It does not change the icon
When I create a new project via unity, I get this warning in the console.
Hello, I use VS Code for programming. Since some time VS Code doesn't know Unity methods anymore. And because of that Unity can't read the fields in the scripts. This error message appears in VS Code. Please help me!
hello, so I am using a special uploader for a game, that is open source. And I want to modify it so it checks if the android platform and macos platform are installed. Is there a way for me to do that or get a list of all installed platforms ?
Hey folks, I'm learning custom editors so I'll be sending a few questions as I learn here - first question:
How does one use the EditorStyles.toolbarDropDown style? It makes it look clean but I can't figure out how to make it functional.
It seems it's working but I have to click in a very specific spot rather than anywhere on the toolbar. Do I need to manually set the clickable rect?
I have to click on the left border specifically
Why aren't you just using EditorGUILayout.Foldout? (may be in GUILayout, not EditorGUILayout, not too sure right now)
*edit, my bad, Foldout is obviously not the same as a Dropdown. Take a look into EditorGUILayout.DropdownButton, EditorWindow.ShowAsDropDown, GenericMenu.DropDown, one of them might help
The Styles are just another argument you can use for you controls to override the default style, for example the Foldout Control takes an optional GUIStyle as its last argument, you could test what happens if you use the Style that you've mentioned above in there
How do I get constant Handles size for Label and Lines
I tried HandleUtility.GetHandleSize
but it give bigger numbers when zoomed out, thus only making them bigger.
What's your code?
Uhh I've moved on at this point, working with reorderablelist
If the reorderable list uses custom objects, how would I designate how they're drawn?
Do I need a custom editor for that object?
I don't really know what I'm doing, I just went with what looked nice
There's a draw element callback, you can also use a custom editor/property drawer for the object
nice
should work
I'm struggling to get anything going with this callback. I know I have a rect but I'm not sure where to pass that in for my fields. I'm just trying to print the index for starters
_list.drawElementCallback += (rect, index, active, focused) =>
{
GUILayout.BeginArea(rect);
EditorGUILayout.LabelField(index.ToString());
GUILayout.EndArea();
};```
I'm trying this atm
Try GUI.Label(rect, index.ToString()) without the Begin/EndArea calls
Can you show the full code of your editor script?
[CustomEditor(typeof(StateScriptable))]
public class StateEditor : UnityEditor.Editor
{
private ReorderableList _list;
public void OnEnable()
{
var state = (StateScriptable) target;
_list = new ReorderableList(serializedObject, serializedObject.FindProperty("Transitions"),
true, true, true, true);
_list.drawElementCallback += (rect, index, active, focused) =>
{
GUILayout.BeginArea(rect);
GUI.Label(rect, index.ToString());
GUILayout.EndArea();
};
}
public override void OnInspectorGUI()
{
serializedObject.Update();
_list.DoLayoutList();
serializedObject.ApplyModifiedProperties();
}
}```
oh
sec
i misread before
working now
Great 😀
What was the issue?
without the Begin/EndArea calls
Missed that
Though without that I'm not entirely sure how to add new fields
And how the list knows the size of the rect
If I add more things to each element
elementHeight
Got it
Is there a property to make the = centered somehow?
I wish there were better docs on this
I dont think so
Same
Still lost on adding multiple things inside the rect given
You got to calculate your own rects for things
So the rect they give you is the total area
got it
Then separate it by line using EditorGUIUtility.SingleLineHeight
var grid = new Rect[3,2];
for (var x = 0; x < 3; x++)
{
for(var y = 0; y < 2; y++)
{
grid[x, y] = new Rect(
rect.x + rect.width / 3 * x,
rect.y + EditorGUIUtility.singleLineHeight * y,
rect.width / 3,
EditorGUIUtility.singleLineHeight
);
}
}
GUI.Label(grid[0, 0], index.ToString());
GUI.Label(grid[1, 0], index.ToString());
GUI.Label(grid[2, 0], index.ToString());
GUI.Label(grid[0, 1], index.ToString());
GUI.Label(grid[1, 1], index.ToString());
GUI.Label(grid[2, 1], index.ToString());```
Got this little thing going
Good job
I'm struggling to access the list elements now
I see there's GetArrayElementAtIndex but either I'm messing up or it doesn't work on lists
So given my reorderable list _transitions, using the serializedProperty of a List<Transition> Transitions, I'm trying to access the properties of elements of Transitions
_transitions.serializedProperty.GetArrayElementAtIndex(index).FindPropertyRelative("To")
((Transition)GetArrayElementAtIndex(index).objectValue).yourPropertymight work, but not sure, just pseudo code that came to my mind
I'm not seeing where to use FindProperty there
Transition is just a class, not derived from anything
does it need to inherit from something to be serializable and worked with?
I'm still trying to get the serializableProperty to pass to EditorGUI.PropertyField
Aaah ok, but you could just use the concrete field for that property and it should still update the serializedObject properly
It needs a monoscript input
Oooh ok
But I can't access the serializedProperty/object to even set the value
if I can get to the property it should work fine
You're doing something related to States and Transitions, correct?
Yeah I'm writing a state machine
I'm also taking it as an exercise on custom editors
The goal for this list is a list of Transitions where each one has a MonoScript To and then another monoscript and dropdown to select a method for the condition
So I assume your Transition takes the State it should transition to as a script? Couldn't you do it with Types/Reflection instead?
Oh my bad, it actually takes a StateScriptable
For To
Which just so happens to be what I'm writing the editor for
[CreateAssetMenu(fileName = "State", menuName = "FSM/State", order = 1)]
public class StateScriptable : ScriptableObject
{
public MonoScript Mono;
public Type Type => _type ??= Mono.GetClass();
private Type _type;
public List<Transition> Transitions = new List<Transition>();
}```
public class Transition
{
public delegate bool TransitionDelegate(StateMachine machine, StateScriptable state);
public StateScriptable To;
public TransitionDelegate[] ShouldTransition = {};
}```
Mhmm, but if the SO itself is the state (does look like that), what is the Mono Script for?
The behaviour
Yeah
The goal is to have the end user not need to override anything
They can just throw in their already functional scripts
And any functionality like OnStateEntered can just be done in Start/Awake
Ok, I understand, sounds like a good idea
So if I can just get access to the To serializableProperty then I'm fine
But idk how to get there
So is transition marked as serializable?
Well that's why it's not working
Not sure why I had that
It's showing up as this
I saw it before but wasn't sure what was going on
It doesn't seem to accept a StateScriptable
Looks like your rect is not properly sized
Ah I see
one sec I'll show the area around it too
Because I'm using propertyfield, it added the header
It still looks incorrectly sized, the picker should be on the right of the box
I forget if there's other things that cause it but I'm pretty sure it's just a very small rect
EditorGUI.ObjectField(grid[1, 0], transition.FindPropertyRelative("To").objectReferenceValue, typeof(MonoScript), false);
var grid = new Rect[3,2];
var cols = new float[3] {0.2f, 0.4f, 0.4f};
for (var x = 0; x < 3; x++)
{
for(var y = 0; y < 2; y++)
{
grid[x, y] = new Rect(
rect.x + cols.Take(x).DefaultIfEmpty(0f).Aggregate((cur, active) => cur + active) * rect.width,
rect.y + EditorGUIUtility.singleLineHeight * y,
rect.width * cols[x],
EditorGUIUtility.singleLineHeight
);
}
}```
Played around with this a bit
Shouldn't be evenly spaced
Not sure how to approach selecting a method but I'm sure I'll figure it out at a later point
Thanks for all the help folks!
You'll for sure find a solution, looking forward to seeing the finished system in action 😀
Looking at adding a mono script field and string field to the transition
Then they drag the script the transition logic is in
and select the method from a dropdown
Actually even better
I could pull a method from the monoscript Mono in StateScriptable
That way they could be instance methods in the script it's transitioning from
I just spend almost 2 hours try to figure out why all of the children in my VisualElement container were moving to the same last set position... this is in the container VisualElement... it is the simple things sometimes...
void SetPosition(VisualElement childElement, Vector3 pos)
{
transform.position = pos;
}
I was just setting the container position instead of the child;s position....
Alright I got it working - the editor has a To field which takes the state the transition goes to, and a dropdown which lets you select a method of a given signature from the current state's monobehaviour:
It saves the method as a string which is then used with SendMessage
As SendMessage doesn't use return values, I opted for a class which stores just a boolean
public class Transitioner
{
public void Transition() => DoTransition = true;
public bool DoTransition { get; private set; }
}```
So you can write your logic and if it should transition, call c.Transition()
public class IdleState : MonoBehaviour
{
public Rigidbody2D rb;
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
public void IsFalling(StateMachine.Transitioner c)
{
if(rb.velocity.y < 0) c.Transition();
}
}```
So it ends up like that
Next step is adding some UnityEvents for things the user might want (for example StateUpdated to notify the gamecontroller)
At first I wanted to do reflection and delegates, but I was running into too much trouble with binding them to a target and serialization
And this project isn't intended to be perfect so I just sucked it up and went with the slow SendMessage
Definitely an interesting solution, nice that you got it working so far
Yeah there's a lot of stuff I'm not happy about but it's been a great learning experience
It bugs me that the transition conditions can't return bool
Yea, that's a bit unlucky for that kind of thing, but I'm sure there's some sort of workaround for that, just can't image it right now
I might be able to do some kind of wrapper for it
You could create a separate class for the Transition and assign it a Func<bool> the same way as you did with the method right now, and if that one is true you invoke the actual transition method, if thats possible and/or makes any sense at all.
Right now the thing that should basically just be a condition check does the actual transition, would be better if you could separate that two responsibilities
But pretty sure you're already trying, go on, nice work so far!
Yeah the problem is not being able to know anything about the methods themselves
Through reflection all I can get is a methodinfo
Yea true, but basically it should be a method without parameters that returns a bool
Yeah I had that initially
But I couldn't serialize it
Or make a delegate out of it
So I thought of storing the name, then making the delegate at runtime
But I don't have access to an instance to bind it to
Final test successful - goes between falling and rising states
Switching if the vertical velocity gets too high
Func<bool> could work
Just had a realization
Type eventType = Type.GetType(node.EventName);
if (eventType != null)
{
if (eventType.IsSubclassOf(typeof(GameEvent)))
{
var constructors = eventType.GetConstructors();
var main = constructors[0];
foreach(var param in main.GetParameters())
{
//Draw param.
EditorGUILayout.PropertyField(new )//what do here
}
}
else
{
EditorGUILayout.LabelField($"Class of type {node.EventName} does not inherit from GameEvent!", errorStyle);
}
}
else
{
EditorGUILayout.LabelField($"Class of type {node.EventName} does not exist. Make sure it's typed correctly!",errorStyle);
}
how can I draw a property field of a class's variable/field that's been got via reflection?
The problem is that PropertyField requires a serializedproperty
how do I get a serialized property from just a class type
You don't
Figure out which one you need and draw it
I need all of them.
That's the point of what I'm doing. I'm getting a class from a string and then drawing all of it it's public fields in the inspector.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor.UI;
#if UNITY_EDITOR
using UnityEditor;
#endif
public class DA_TestingScript : MonoBehaviour
{
enum ItemType { TabA, TabB, TabC }
[SerializeField] ItemType currentMenu; // Setup Custom Inspector
bool showTabA;
bool showTabB;
bool showTabC;
[HideInInspector] public string[] testingString = new string[0];
#region Editor
#if UNITY_EDITOR
[CustomEditor(typeof(DA_TestingScript))]
public class DA_TestingScriptEditor : Editor
{
SerializedProperty stringArray;
void OnEnable()
{
stringArray = serializedObject.FindProperty("testingString");
}
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
DA_TestingScript menuControl = (DA_TestingScript)target; // Set the current script to the target class
if (menuControl.currentMenu == ItemType.TabA)
{
EditorGUILayout.LabelField("Tab A");
serializedObject.Update();
EditorGUILayout.PropertyField(stringArray);
serializedObject.ApplyModifiedProperties();
}
if (menuControl.currentMenu == ItemType.TabB)
{
EditorGUILayout.LabelField("Tab B");
}
if (menuControl.currentMenu == ItemType.TabC)
{
EditorGUILayout.LabelField("Tab C");
}
}
}
#endif
#endregion
}
I am having issues with showing variables in a custom inspector. I need to hide testingString but the variable needs to be public because the editor class references it for the custom inspector. I tried using [HideInInspector] but that causes it to not draw in the custom inspector but it does hide the original varaible.
this is for my custom node-based dialogue editor. I want a node that can run an arbitrary event and also be able to define that events parameters when you type in the correct name. Then, when my iterator for the node tree finds this node, it will run that event with the defined parameters.
I never talked about PropertyField, I said manually, implying IntField, Float, Toggle etc.
You just can't get a SerializedProperty in your context
so use something like a switch to draw the different types?
HUZAH! I found what I needed. (also sorry @digital spoke & @onyx harness for splitting the chat)
its fine
alright thanks
How can I support something like a ScriptableObject variable inside the event?
ah kk thanks
can an editor script override a getter/setter? Sorry, google keeps giving me results for getters/setters I'm not looking for so not wording my search correctly
getter/setter? you mean a property?
ObjectField requires an Object or a SerializedProperty as a argument. How can I get that from a type?
EditorGUILayout.ObjectFieldp(/*what put here*/,param.ParameterType);
How do you get an integer?
Maybe? So, if I have a field with a getter with things that works in a build, I want to use things in editor that are better if in editor. I'm trying to avoid doing #if UNITY_EDITOR in the middle of that code just for organization reasons and keep it in the editor script itself.
Well the thing about an integer is that I can just use IntField. An ObjectField requires an Object. I can't convert Type to Object
IntField requires an int, ObjectField requires an Object
How do you convert a Type to Int?
the object is the class that holds the field I'm trying to draw, is it not
while the int is just the variable.
so basically wondering if I can do public string Example {get {//code return example;}} and in editor script something like public override string Example... which doesn't work, but didn't know if another way
well, I mean, instead I did it with a method
but got me wondering
I missed something I guess, I thought you were talking about variables (fields) inside the event?
Nope you cant override like that
To override you need a relation with a base class.
Which you haven't
switch (param.ParameterType.ToString())
{
case "XNode.NodeGraph":
//Can't use eventType, can't use param
//EditorGUILayout.ObjectField(/*WHAT PUT HERE*/,param.ParameterType);
break;
case "System.Int32":
EditorGUILayout.IntField((int)param.DefaultValue);
break;
default:
break;
}
What is param.DefaultValue?
You need to implement String
It might help you understand your issue better
Sorry sorry I know what is a ParameterInfo
Implement, Int, then Float, then String
It should open your eyes on how to deal with Object
switch (param.ParameterType.ToString())
{
case "Dialogue.DialogueGraph":
EditorGUILayout.LabelField(param.Name);
objSource = EditorGUILayout.ObjectField(objSource,param.ParameterType,true);
break;
case "System.Int32":
EditorGUILayout.LabelField(param.Name);
EditorGUILayout.IntField((int)param.DefaultValue);
break;
default:
break;
}
Had to define an Object variable to use as the parameter
now it seems to work perfectly
How are you going to deal with the Integer?
Same pattern, define an Integer variable to use as the parameter
This is why I told you to implement the easiest ones first, Object would become obvious when done
the way this is supposed to work is that it will store the values I've put into the fields and then the node tree iterator will use them in the events constructor
What am I supposed to do with this information? 😄
any editor will be acting on an instance i believe
so if you're in a custom editor, you should have access to serializedProperty which is the SerializableProperty you're editing
okay, thanks once again for feedback! Appreciate it
is it bad to put a variable in OnEnable to is literally to just make sure a static is initialized? Like, rather than using OnLoadAttributes?
for example, just have in it
void OnEnable()
{
if (!instanceExample) ExampleClass example = InstanceExample;
}
What sort of sorcery is it that makes it so that you cannot use "GetInvocationList()" on EditorApplication.ProjectWindowItemCallback?
public delegate void ProjectWindowItemCallback(string guid, Rect selectionRect);
idk if you are including the proper things?
the proper params
right, so if it's a delegate, theoretically, you should be able to do EditorApplication.ProjectWindowItemCallback.GetInvocationList(), but it's not valid
I assume to initialize the static instance... yes.. yes it is. You can use [InitializeOnLoad] and a static constructor. But Why are you wanting to force the instance... it shouldn't make a different. If it does then you may be doing something wrong.
It doesn't, but, something I was just curious about. Thanks!
It says ProjectWindowItemCallback is a type, but you can do EditorApplication.ProjectWindowItemCallback += someMethod;
No you can't, it is a type...
you want EditorApplication.projectWindowItemOnGUI
You can only do that on the events
is what you subscribe to
as an example
not the HierachyWindowItemCallback
Small correction, you can only do that on delegates, not just events.
oh my bad. I just read it under the catagories in the scripting api haha
All good, just wanted to make things clearer since events are an actually thing.
I guess, it's in reverse, like, it's under the events catagories, but, the delegates catagory is the actual event happening
?
An event is basically just a way to say that "Hey, this delegate can only be invoked from this class, and you can only add and remove listeners, not set it's value. This delegate is a thing that happens"
gotcha! Thanks for clarifying that better. Although I think I understand events better now. The wording still kinda confuses me
Alright, it's fine. I found "RenderStaticPreview" which might be exactly what I need
In a custom inspector how do you add a unity event?
public Action somethingHappened; // Normal delegate/callback/thing
public event Action somethingHappened // Event;
Never mind I figured it out. I can just call a Unity Event the same way I call my arrays. For anyone curios (or future me when I inevitably forget) here is the code.
In the main script:
using UnityEngine;
using UnityEngine.Events;
public class DA_Menu_Control : MonoBehaviour
{
public UnityEvent onBack;
}
In the Editor script:
using UnityEngine;
[CustomEditor(typeof(DA_Menu_Control))]
public class DASDK_Menu_Control : Editor
{
SerializedProperty onBack;
void OnEnable()
{
onBack = serializedObject.FindProperty("onBack");
}
public override void OnInspectorGUI()
{
//base.OnInspectorGUI();
EditorGUILayout.PropertyField(onBack);
}
}
Hey, I'd like to make a Handle Tool similar to the Position/Rotation/Scale Handles, basically a Handle that I can select globally and that works on whatever my selected GameObject(s) are without the need of having a MonoBehaviour attached to them.
I know how to use Handles, how to get the Selection etc, but I have absolutely no idea how I'd make this Handle a global thing that doesn't require each GameObject to have a MonoBehaviour attached.
Can I just make a custom Editor for a Transform and utilize OnSceneGUI in there?
Would be great if somebody is able to push me in just the correct direction
*edit, it's possible to override the Transform Editor, but it's messing up the style, but that's not much of an issue, should be pretty easy to replicate the default styling
Perhaps you're looking for this https://docs.unity3d.com/ScriptReference/EditorTools.EditorTool.html
Awesome, exactly what I was looking for 😀
EditorUtility.SaveFilePanel() is marked as deprecated, but it doesn't mention what it's been replaced by.
Actually I just want to create an asset, and don't really need it to use the native file picker. perhaps there's a better approach for something like this
Right. But I need a way to prompt the user for a path and name. I figured there might be some control or utility that integrates with the editor, since SaveFilePanel has been deprecated.
It'd be create if it would just create the asset in the current project view folder and highlight the default name to allow it to be renamed.
sort of like when you create a new asset through the assetmenu
Is it deprecated? Where does it say this?
yeah I couldn't find anything about it in the docs, but it has a [deprecated] flag in my editor
Doesn't in mine
Please don't use ableist slurs; it's a fine mistake to make, we all have 'em.
Right, sorry
what should i use for unity (Vs code or Visual Studio or Sublime Text)
Notepad++
Mikilo ._.
No cross-posting please. #archived-code-general
ok
Real programmers use butterflies
How do you destroy a subasset in a way that supports undo/redo?
isn't this Undo.DestroyObjectImmediate expected to work?
Is there a way to get the y value for the next field/control to be placed in an editor window?
DrawTexturePreview expects a Rect but currently I'm not tracking or setting the position of elements
I tried that but it didn't work it seemed. But I just tested on it's own in a controlled area and it works. part of what was throwing me off was that it sub-asset didn't show back up after undo, but that is because I didn't save assets. It is working as expected now, thank you!
GUILayoutUtility
Perfect. Thank you
Any ideas on why my custom editor isnt saving data when restarting?
https://pastebin.com/KSarRJGj
Pastebin
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.
Do you mean when you restart unity?
Wow I had no idea you could just reference the target directly. I thought you had to use SerializedProperty objects and bind them via FindProperty
This looks so much simpler. Any downsides to this approach?
I've noticed that it happens on play as well
But yes restarting unity
Heres the data structure : https://pastebin.com/XDmuJc6P
Pastebin
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.
Yes, a lot. You have to manually support undo, and it doesn't support prefab overriding values.
Lmao just realized I left in the debugs.. woops lol
Well there is your problem... you don't have any fields that can be serialized...
Of course nothing will be saved if you don't have anything that can be saved.
Could you elaborate on that? I'm not sure how an object with ints and an array of ints cant be serialized?
Those are all primitives as far as I'm aware
Unity doesn't serialize private fields unless they have the [SerializeField] attribute.
Whats the significance of [NonSerialized] then? I figured that it would serialize by default
that's probably to not automatically serialize a public value
Well.. lessons learned lol
thanks
I'll try that
No its still erased for some reason
Still stuck trying to figure out how to create this node.
I want to make a node in my node editor where I can type the name of a GameEvent (a custom class for my custom event manager) and, if it's a valid gameevent class, display the class's constructor and it's arguments as assignable fields.
However, in the video you will see that anything that I put into the fields will be erased during a recompile (see how the dialogue field becomes none) . I'm using a dictionary to store the stuff that have been assigned to the fields. I've tried multiple serialize-able dictionary addons and they've given the exact same result
Does anyone know how I can solve this issue?
public should default be serialized
To force a field to not serialize. This is also handy when working with Dictionaries and other types that Unity doesn't serialize in order to insure that it stores no data. A thing to note, the [NonSerialized] attribute is in the System namespace, not the UnityEngien namespace.
You shouldn't have public fields, that is considered a bad practice in C#.
I'm just letting them know. I personally use public for any values that are can be used anywhere else and would only have getter/setter attached
also, here's how I get the parameters/arguments of the constructor and display them on the node https://hastebin.com/cuxijaqepe.http
if anyone could help that would really be appreciated
I've heard that before, but what's the reason exactly?
is there any difference between a public field and a property with just a basic {get; set;} ?
I FIXED IT!
It's not, it's about everyone being on the same page type of thing. If you set something as public, that allows other people who view your code to assume potentially that that field is suppose to be altered.
Thanks all
but isn't that exactly the point of access modifiers to begin with?
I don't understand how properties are any different from fields in this context, if they are accessed the same
Setters and getters can manipulate the get/set to fit the data or whatever as well
So if you need to transform something, a getter could be useful
If you want a convenient setter or overloads of setters they can be useful
Getters are good for data you want to be accessed, but obviously not altered. Then you can do [SerializeField, HideInInspector] so that if someone really wants to change it, they actually have to go directly to the source
Right, properties are very useful indeed. I just don't understand the difference between a public field and a simple property (with no addition get/set logic)
Getters are good for more than that, but, just off this basic stuff we talking about hehe
There are a number of reasons. Firstly the get/set accessors tell the end user how they can and cannot interact with any given property. They also let you change the internals of how that value is gotten/set without breaking anything.
Imagine you have some computed values or side effects of a setter. Like you have a browser window and someone sets the width. You could place some logic in the setter or a hook there to resize the window when its set.
From everything I can find. It's about sharing your code with others. In a perfect world, the public field is a shorter way of serializing the field and adding a get/setter, but, think about how we talk to people IRL and how people misinterpret things. That public can be construed to mean other things
Another reason is from the C# docs
"Data that your class exposes to client code should be provided through methods, properties, and indexers. By using these constructs for indirect access to internal fields, you can guard against invalid input values."
I understand properties. My question was why public fields are bad practice.
so leaving it private (the default declaration is private, so either add or don't. I personally don't add private to almost anything hehe) and adding getters/setts allows better communication, if you will
I guess because it makes the accessibility difficult to manage. I try to only use public fields on data structures and such
i think i get it now though. If i later wanted to introduce a more complicated pattern for getting/setting the field, I wouldn't break any other code
Yep
but again, it's one of those, imo what I consider annoyances in programming, things that doesn't have any direct improvement on lets say performance of the code, and is all about how you say it
It also forces you to think a bit more about what you actually want other classes to be able to edit. It is like a piece of plywood vs an actual door with a knob, both work, but one is nicer and cleaner to use 😉
not performance of code, but i guess performance of development/maintenance
So did you fix your serialization problem?
Oh yeah, sorry. I just took over the chat.
Thanks for the explanation guys
It's also important, imo, to create a similar flow throughout your code. So, if you use public, make sure to use it similarly everywhere. Don't make it confusing to other people who may look at your code to wonder why something is public, then there is getter/setters over here etc...
I assume the problem is where you are storing the data or how you are setting the data rather than what you are storing it in.
Right. consistent patterns let people make assumptions about different things, just by glancing over basic structure.
This should be a valid property right... why is my alpha not working...?
I actually use public a lot when I'm testing stuff just to make writing it out easier, then switch it over to a private with getters and setters hehe
The Unity docs say it should work...
does https://docs.unity3d.com/ScriptReference/Color-ctor.html help? I remember a few weeks ago doing something with rgba not working and changing it to this worked
but I know you doing different things than what I was
Thanks, but this is for USS.
yeah, I figured from your SS that it would be different 😦 sorryt
https://docs.unity3d.com/Manual/UIE-USS-CustomProperties.html I think that is just for RBGA
RGB can go to 255 it looks like
which I guess makes since since the A is for alpha
Yeah RGB are all 255, but alpha is up to 1.
If I generate a texture in a custom editor, do I have to save it as an asset before I can update the field of the associated ScriptableObject?
IIRC yes
I thought RGB was 0-1.0 because they were all floats?
UnityEngine.Color is, but not the USS property type.
I tried recreating the foldout structure in UXML yesterday but couldn't figure out how to include UI-Toolkits built-in controls.
I was using base class of Visual Element rather than Foldout or Toggle because using those built-in classes wouldn't allow me to edit their children (where I would insert an object field).
Also the way the built-in Foldout is structured is a bit different than what you had suggested.
Is there a way I can inherit the functionality of the built-in controls and retain control of what goes in those VisualElements?
I've gotten to this point in recreating it all but of course this doesn't function like the built-in controls
Completely untested, but this should help 🙂 https://paste.mod.gg/vajulomabi.cpp
So where should I store it?
A dictionary seems the most logical choice, because I need to save not only the thing assigned to the field, but the name of the parameter too, so I know which is which
A list with a tuple would also work but I'm not sure if that's a better way
I mean what object are you storing it in? A scriptableobject? Is it an editor or an asset? Did you make sure that what ever serializable dictionary field you are using has the [serializefield] attribute?
Did you mark the dictionary class as [Serializable]
i mean yeah
[Serializable]
public class StringStringDictionary : SerializableDictionary<string, string> { }
[Serializable]
public class StringBoolDictionary : SerializableDictionary<string, bool> { }
[Serializable]
public class StringObjDictionary : SerializableDictionary<string, UnityEngine.Object> { }
[Serializable]
public class StringIntDictionary : SerializableDictionary<string, int> { }
//To store object parameters
StringObjDictionary tempObjs=new StringObjDictionary();
//To store int parameters
StringIntDictionary tempInts=new StringIntDictionary();
//You get the idea.
StringStringDictionary tempStrings=new StringStringDictionary();
StringBoolDictionary tempBools=new StringBoolDictionary();
If I have a ScriptableObject with a texture field, how exactly would I modify and save changes to it?
I'm not exactly sure what to assign to SerializedProperty.objectReferenceValue
I've tried a few different things, but it seems I'm only editing the in-memory representation. It never actually updates the field
Nope the fields are not marked with the [SerializeField] attribute
Unity doesn't serialize private fields that don't have that attribute.
but that doesn't matter though
i dont want to serialize them as fields
they're just for storing data
Well then they are not going to keep their data on editor reload if you don't serialize the data. And if you are not serializing them then what is the point of having the serializable dictionaries....?
and as a quick test, using serializefield still doesn't work
I can tell you that without [SerializeField] it will 100% never work.
What class are the fields in?
they're not fields
... they are very clearly fields... StringObjDictionary tempObjs=new StringObjDictionary(); this is a field...
that's a variable
Like.. in a method?
I don't get what you are doing. But I can tell you this, if you want editor data to save between domain reloads, then the data must be in a serialized field that is defined in a ScriptableObject (both Editor and EditorWindow are ScriptableObjects fyi)
but a field is something that's supposed to be displayed on an inspector, is it not?
no... no it is not at all...
A field is a term in C# https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/fields
but either way, it still doesn't work like this.
[SerializeField]
StringObjDictionary tempObjs=new StringObjDictionary();
[SerializeField]
StringIntDictionary tempInts=new StringIntDictionary();
[SerializeField]
StringStringDictionary tempStrings=new StringStringDictionary();
[SerializeField]
StringBoolDictionary tempBools=new StringBoolDictionary();
so 
you may want to look up OdinSerializer which is free and open source. This page explains how serializing dictionaries works, both with unity and with odin's unity class extensions
https://odininspector.com/tutorials/serialize-anything/serializing-dictionaries
Odin Inspector
Is it possible to make a CustomEditor for all components that implement an interface? It seems to not be working for me.
That isn't the problem in this case I suspect.
It is not.
Sad
I've used that as-well as like 5 different other serializeable dictionary assets. All of them had the same result
That is because the dictionary is not the problem. Can you show the class that they are in?
they're in a XNode nodeeditor script. Essentially functions the same as a custom inspector a script. Uses Unity immediate gui stuff etc
https://pastebin.com/1VjLamWT here's the entire script
Pastebin
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.
Can you even save a simple int?
I'm sorry for bumping my previous question, but is it possible to update a texture on a SerializedObject?
I've generated a texture in a custom editor, but I can't figure out how to update the texture of the associated ScriptableObject
And someone answered you
Hi yes
Right, then i asked again a bit later because i still wasn't able to make it work.. I tried creating the asset, but I'm still not sure how so safe modifications to it
Do I just overwrite whichever asset the texture is pointing to? I can't seem to find anything on updating assets
Well, then show what you're doing
Use serialized properties or just set it and call set dirty or recordundo
Well.. my code is an absolute mess right now, as i reached the point where i just started changing things around blindly
but here's the basics i guess:
public override void OnInspectorGUI() {
serializedObject.Update();
EditorGUILayout.PropertyField(textures);
TextureSheet = serializedObject.FindProperty("TextureSheet");
if(GUILayout.Button("Update Sheet")) {
try {
TextureSheet.objectReferenceValue = UpdateSheet();
} catch(System.Exception ex){
EditorUtility.DisplayDialog("error", "couldnt update sheet "+ex.Message, "okay");
}
}
Texture2D tobj = (Texture2D)TextureSheet.objectReferenceValue;
if (tobj != null) {
Rect r =GUILayoutUtility.GetAspectRect(tobj.width / tobj.height);
EditorGUI.DrawPreviewTexture(r, tobj);
}
EditorUtility.SetDirty(target);
serializedObject.ApplyModifiedProperties();
}
Where UpdateSheet() returns the generated Texture2D object
I also tried creating an asset from the generated texture before assigning it, but I'm guessing i need to pass the newly created asset then, and not the Texture2D object?
Well well, not too bad not too bad, but you chose to not put the most important method: UpdateSheet()
right, ofc. my bad
private Texture2D UpdateSheet() {
int count = textures.arraySize;
int rows = 1 + (count-1) / maxColumns;
int columns = count >= maxColumns ? maxColumns : count;
int width = columns * textureSize;
int height = rows * textureSize;
Texture2D sheet = new Texture2D(width, height);
int c = 0;
int r = 0;
foreach(SerializedProperty serialized in textures) {
Texture2D tex = (Texture2D)serialized.objectReferenceValue;
sheet.SetPixels(
c * tex.width,
r * tex.height,
tex.width,
tex.height,
tex.GetPixels());
c++;
if(c >= maxColumns) {
c = 0;
r++;
}
}
sheet.Apply();
return sheet;
}
It's not very elegant, i know.
It basically just takes a list of textures and packs them together, then return the newly created texture
I think you need to make it an asset.
Right, but then what do I pass to the object reference when updating then? Do i just ignore the serialized property and update the asset that it's referencing then?
I've been searching for a toy example for something like that, but apparently this is not a very common thing to do
Also, the AssetDatabase has methods for creating assets, but doesn't seem to have one for updating them. If i just overwrite/recreate it, wont the ScriptableObject lose it's reference to it?
i cant save anything. everything gets reset after recompile
the dictionaries get erased
I know i know
apart from trying more serializable dictionary assets, idk what else to do
Not trying to save persistent data in an Editor
so I should try to put the data in the target script (StateEvent)
yeah
Editor is temporal, Node is persistent
yep that fixed it LMAO
i moved the dictionaries into StateEvent and out of StateEventEditor
thanks @onyx harness
Actually, if i just need to load the texture once, would it be a better option to just generate and assign it at runtime instead? Seems like it would simplify everything a lot, although it'd be ideal to have it pre-baked from the editor
Got my own question. Is there a good with without using serializedObject.hasModifiedProperties to tell if a object has been changed since the custom editor opened? Best I got is getting DirtyCount on open and then comparing it, but that doesn't play nice with undo or if the assets are saved while the editor is open.
I can make it work, but it just will be more work and not as nice.
I'm not sure on the direct method, however, I have been using EditorGUI.BeginChangeCheck(); and if (EditorGUI.EndChangeCheck()) to solve my problem for what you are talking about. If you find some info please let me know
Then a setdirty/save assets basically
Yeah thanks, I'm using UITK for this though. Otherwise that would work.
one day I'll remember that lol
can you use something along the lines of
void MyDelegate(ContextualMenuPopulateEvent event)
{
// Modify event.menu
event.menu.AppendAction("Properties", DisplayProperties, DropdownMenu.MenuAction.AlwaysEnabled);
}
? Not necessarily that exactly
a callback for the ContextualMenuManipulator
And that would do...?
You could raise the event whenever you change something?
Not practice in this case because it can be extended with user content. And there are multiple levels of elements I would have to do that for.
ahh okay
public class EventInfo { ... }
[SerializeField] public List<EventInfo> AvailableEvents = new List<EventInfo>();```
Working on a custom inspector. When I have a SerializedProperty pointing to "AvailableEvents " is there any easy way to get or set that data working with the actual type rather than doing it all via SerializedProperty s?
Having to get the array element at X, then having to use FindPropertyRelative to get it's sub properties.. then if one of them is a collection, repeating that whole process again... its just ridiculous.
End goal is to use a EditorGUILayout.MaskField populated with all the options that could exist, then serialize info about only the options that were chosen.
But that means I need to be able to compare all the possible elements, and their values, against the current collection, to build the mask..
There is target, and you can also iterate over properties, fyi.
Oh right. I guess I can use the base object when trying to get values directly.
Weird that I cant go from a SerializedProperty to a System.Object though like you can with string with "SerializedProperty.stringValue" (Unless I am missing something)
It's because those are all base types and have a C++ representation. At least I think that is the reason.
Why is it when I generate a texture, I get a washed out texture that is semi-transparent?
This should make the icons disappear:
Rect smallerRect = new Rect(selectionRect) { width = selectionRect.height };
smallerRect.height *= 0.85f;
smallerRect.width *= 0.85f;
Texture2D background = new Texture2D((int)smallerRect.width, (int)smallerRect.height);
backgroundColor = (new Color32(51, 51, 51, 255)).Times(background.width * background.height);
// Snip
background.SetPixels32(backgroundColor);
background.alphaIsTransparency = false;
GUI.DrawTexture(smallerRect, background);
But instead I get this:
.Times is just an extension method I wrote for arrays that generates an array of specified length that all contains the data it's called against
I got the idea from Ruby
Because I got sick of having to write the new array and then a for loop
I got the same result just writing the array manually
It should look like this:
n/m I forgot to .Apply()
making progress yayy
i'm new to c#, could someone tell me how i could convert a string to a float?
float.Parse("50.5");
This also should go in #💻┃code-beginner
I have an editor tool that needs to keep a ScriptableObject reference during play mode change. Any Idea how to handle that?
I tried using a GameObject container with HideFlags.DontSaveInBuild | HideFlags.DontSaveInEditor. But if it does not safe in editor it does not survive plamode change and otherwise it gets saved to the scene
How do I fix this problem with 2d-extras? I just downloaded it but its giving me error
i just commented out the if statements that use them for now, i hope it doesnt break too bad
I'm trying to get my custom window to pop up in the main view (beside scene/game) but it doesn't seem to be working as I'd expect:
GetWindow<FSMMachineWindow>("State Machine", true, typeof(SceneView));
Am I using the wrong type?
I can't use GameView cause it's internal
Without reflection
What is happening? Because yes that works.
it pops up on my second monitor not docked to anything
Can you show the rest of the code related to opening it?
That's it
Alright works now with nothing changed
Funny - I saw the same story on a lot of forums I was searching through
hey folks, is there any way to add modify this Script field that appears on every single component? I want to add an Edit button to reduce the number of clicks to open a script.
I'm assuming it's something to do with Custom Property Drawers?? but I've never written one, so not really sure where to start looking. any help appreciated. thanks! 🙂
you know a double click of the field will open it up for editing?
that is true, but also, ideally, I'd like a function that opens it without pinging the asset in the Project tab
because I find that leads to more clicks, as I need to navigate back to whatever folder I had open in the Project
I believe it doesn't ping if you double click (at least on windows)
it does 😦
sorry, just tried - you're right
You would need to make a custom editor for the Components type and one for the ScriptableObject type. And then redo all of the fields your self.
Which means iterating through them and making a PrpertyField for each serializedProperty.
this doesn't help you with making an edit btn but fyi I mapped my forward/back btns on my mouse to undo/redo for Unity and it e.g. allows you to quickly navigate the project window back (in general it's useful to abuse undo/redo for navigation I find)
does that mean I'd need to create a custom editor for every single type of script I have in my project?
thank you, that's good to know 🙂 I currently don't have those mouse buttons mapped to anything in Unity 😄
Nope, just from MonoBehaviour and set it to be inherited.
thank you for the pointers. got soooome progress here
now... any idea how to find the script asset corresponding to the attached component instance?
there is the serialized property m_Script.
how do you access that?
(sorry for all the questions, and thanks for the help)
ah! got it!
You'll likely already have access to either a so or a sp
oh? how would I know?
Well it is an editor right, Editor has a property called serializedObject and also one called target 🙂
ohh I see. yeah, if I comment out that first line it's still fine 🙂
Damn... Just got my first editor extension to a somewhat working state (just a simple tool for a voxel engine to manage textures and block types)
It's an incredibly powerful feature, and it has amazing potential, but it really makes it clear how important time management can be.
I made this little thing mostly to get a familiar with the API, but also because i thought it would be a convenient tool to have.
I could have created a ton of texturepacks/blocksets by hand, in the time i spend making this tool
of course I'm a still a rookie, and I spend a fair amount of time reading docs and learning the system, but i suppose it also applies to experienced developers. at least to some extent
there's a sort of interesting cost/benefit problem there
Good old programmer mantra: "Why spend 10 minutes doing something when I can spend 6 hours making something to do it for me." 😛
Think I finally have this in a place where I like it thanks to all you guys
Well, if you are happy with it. This may interest you to replace those warning labels https://docs.unity3d.com/ScriptReference/EditorGUILayout.HelpBox.html
@opaque zenith ^
Yes! Thanks you! I'll post an updated version with that soon. I posted the completed thing to my brothers atm and hoping they go to town on it and report to me any bugs back
Also a few GUILayout.Space() would help with readability.
yeah. I didn't take advantage of any of that yet. I'm creating another extension that will use this, and I want prettier, so, when I start adding these things to that I'm hoping to fix this up a little prettier
Ah, got it. I don't think those warnings are needed since I think it is implied that moving scripts triggers a recompile, and they just add more clutter/noise to the UI making it harder to parse.
true. Sometimes for some reason I try to add all these annoying little things thinking, "what if a monkey gets it's hands on it", when in reality, IDK why that would be
@opaque zenith YAGNI - You Aint Gonna Need It
I want to write a test that checks that my Sprite instances are not SVGs (as imported by vectorgraphics package). But confusingly the imported assets are always of type Sprite, regardless of import settings. they just don't render if assigned to a GUI Image component. Does anyone know how I might, given a reference to a Sprite asset, determine if it contains raster or vector data?
oh nvm, I can force it to use Texture instead of Sprite via RawImage. Good enough.
I have bug where AssetDatabase.LoadMainAssetAtPath returns null. Even when I'm explicitely pointing to the fbx I want to load.
can anyone help me?
basically I'm trying to turn an fbx into a prefab.
I tried following this answer
var modelRootGO = (GameObject)AssetDatabase.LoadMainAssetAtPath("Assets/MyModel.fbx");
var instanceRoot = PrefabUtility.InstantiatePrefab(modelRootGo);
var variantRoot = PrefabUtility.SaveAsPrefabAsset(instanceRoot, "Assets/MyModel_Variant.prefab");
But LoadMainAssetAtPath returns null.
Doesn't LoadAsset work?
Nope
What if you do Object instead of GameObject, what does it give you then?
Null
Sounds like it doesn't actually exist at that path
it does exist. since i can see it directly in my editor. And I've restarted unity serveral times to refresh it's asset db.
What if you do FindAssets("t:model") and convert the GUIDs to paths, is the path the same as the one you're passing?
No flipped /?
what the... why? why is it not stored in the AssetDB?
no i had to FindAsset without the extension
why OnDrawGizmos stoppd working?\
nope
And that path is the same as you're using with LoadMainAssetAtPath?
yep
Weird, no idea then
That sounds like it should just work
You can try to get the main asset type and see what it is but if Object doesn't work then I don't have high hopes
ah progress. new error Can't save persistent object as a Prefab asset
Something I can search for
I'm making my own asset preview/thumbnail generation system, and I am trying to figure out how to handle the memory usage.
I could create a limited size cache/pool, but I can have multiple windows open at once requiring more than 2k previews total. And at that point is there much of a reason to have a pool? But I need some way to prevent the memory from just growing infinity with each new asset. Any ideas?
At that point you need to stop showing icons and your cache needs to be shared between all your windows
Yeah, it would be shared for sure. I was thinking I could write the textures to the Temp folder for reuse without having to be in memory, idk if it is just faster than making a new textures, I think it would be though.
Of course it is faster
If you are already working on real test cases of +2k, loading from disk should clearly be noticeable
But I wouldnt put it in Temp, as this one will get erased
You don't want to redo the whole cache after each restart
only when the assets might be modified
Yeah, that was the idea. No need to take up extra space on the users computer. So just erase the files when unity closes.
Yeah, Library is the way
But creating them is really expensive, so you should off load that as much as possible
To give an idea what I am doing, I am basically making something with like the Project Browser, so you could click on a folder and see a lot of thumbnails at once.
If I full screen the window I can see about 1000 assets at once.
Exactly for that that I would use Library or similar
It might be expensive
How fast do you generate 1k at once?
10 a frame.
Any more and it starts lagging the editor.
lol 10 a frame, and you were thinking to redo the whole process after a restart
Someone could potentially have 10k+ assets, so storing that many thumbnails seems a bit much...
Do the math
Do you prefer to make them suffer or the disk to suffer?
How much weigh one thumbnail typically?
Several kb
10, 50, 100kB? 100 * 10k = 1 000 000kB = 1000MB for 10k assets
Oh, yeah... That isn't bad at all huh...
In my opinion, I would think like "shit, I might have do generate 1GB of thumbnails after each restart"
10/frame, around 50~100 frames/s
Well to be fair you would only generate them as you need them, not all at once.
Naaah put a cache limit on your administration panel, show the users how much you currently use, and cap it if you want
So... 1GB down to 10MB typically?
In your case, you are doing a tool for users, and they will very much likely prefer to have them instantly, instead of having to wait
This is what it looks like when generating them fresh, it isn't the fastest thing, but it isn't too bad I think.
(38 x 23 = 874 total thumbnails on screen)
Do the same, but from disk now 🙂
any performance tips for editor? Was thinking of figuring a way to utilize jobs but like 95% of the editor isn't blittable and probably won't run on other threads
So, it works but I have two problems. 1. it makes the generation slow being I am writing to disk as well when I generate them. And 2. I load them in to memory so I still have the problem of figuring out how to manage the memory.
- You can postpone the writing.
- Like unloading?
True.
Yeah, I need to handle unloading them otherwise the memory blooms. But I'm not sure how to figure out when to unload a texture.
Bloom how? With 10MB or 1GB? 🙂
Well like if I create 2k Texture2Ds the memory usage of unity goes up by about 1GB.
The problem is, your browser allows to display 1k images
One page scroll and you are already having 2k images
So does unity with the project browser.
Maybe your thumbnail are too big?
How does Unity behave on 1k?
If you prefer to unload textures as soon as it disappears, you can give it a try huh
No harm to try
The memory usage only increased by about 150MB for just 1k textures.
So... turns out bringing the texture size down from 256 to 128 makes a very large difference in memory usage.
You mean divide by 4 🙂
Yeah...
From what I can tell unity also dose something where they destroy the textures once they have not been used for a few frames.
I assume they are destroying them at least, maybe the textures are assets and the just unload them, but I don't think so.
The textures files are like 3KB... this seems manageable.
Yes please manage manage 🦝
How would one get the default size of the titlebar on a window?
Or some other way of getting the rect of a window beneath the titlebar
I'm currently passing this to my window callback:
new Rect(0, EditorGUIUtility.singleLineHeight, Rect.width, Rect.height - EditorGUIUtility.singleLineHeight)
But I read that singleLineHeight has nothing to do with it, but rather the GUIStyle top border
Its 21 pixels.
Is there a variable I could use on this? I'll hardcode it if I have to but would prefer not to
Not one that would be easy to access that I remember.
alright, thanks!
is there any difference between when I EditorUtility.SetDirty(Instance); and EditorUtility.SetDirty(this); in reference to the the static class? It doesn't seem to be any difference, but, figured I should check
Beyond that SetDirty(this) won't work in a static ~~class ~~ method I think. this returns the instance of the class that it is in. And since it is a singleton there is only one instance. So both Instance and this refer to the same instance.
I got my previews working! It is silky smooth and almost no memory footprint!
Well.. it does seem I need to work on my preview generator configuration a bit... https://i.imgur.com/3yEYHIN.gif
This is not 1000
Does anyone know how to generate TMP atlases procedurally?
I would like to update the hex character string based on ascii used in our project.
omg wtf... the generation code is just inlined into the window rendering logic.
🤦
so here is my code https://hatebin.com/rrqdnwurzy, and here is the results for populate data
but here is the editor display....im sure its wrong, since here my tube is 8, so i miss the last tube here....i did try to coded
for (int j = 0; j <= ballPerTube; j++) but this give index out of bounds....so what should i do so the editor are show alll of the tube inside TubeData[]
hey guys
long time ago you guys helped me out with inspector stuff
and you guys are great
but i made somethign and i want to show you because i think i did pretty good
feel free to send anthrax just dont ban thankx
Nice disco
i basically just allocs epislepsy onGUI
I have en editorWindow, which has some buttons which use images. I setup the buttons with this code cs void OnEnable(){ activeLight = Resources.Load<Texture2D>("Icons/ActiveLight"); activeLight = Helpers.ResizeTexture(activeLight, lightSize.x, lightSize.y) activeButton = new GUIContent("Active", activeLight, "Active"); } void OnGui() { if (GUILayout.Button(activeButton)) DoStuff(); }
My issue is, that when I go to the avatar configuration (configure humanoid char for example) the activeButton.Image becomes null
is that cause your changing contextuals
can you elaborate on that please? The nature of my app means that I must switch to the avatar config and my editor be ok
regardless of the Unity window I'm in, I don't understand why it's setting the image to null, the unity window should be outside of the scope of my editor code, but it still affects my code
The other variables within my editor are fine, it's only the Texture2D stuff that gets destroyed
all you posted is init
OnGui()
{
if (GUILayout.Button(activeButton))
DoStuff();
}```
that's really all there is, I don't see how OnGui affects this though, so didn't post it
the images are in Assets/Resources/Icons
Actually, i made a mistake, it's not Init where the code is called, it's in OnEnable
The Resize function just resizes the image to the correct size, so that I can resize it dynamically rather than change the actual image size if I want a different size
For reference, here's resizecs public static Texture2D ResizeTexture(Texture2D texture2D, int targetX, int targetY) { RenderTexture rt = new RenderTexture(targetX, targetY, 24); RenderTexture.active = rt; Graphics.Blit(texture2D, rt); Texture2D result = new Texture2D(targetX, targetY); result.ReadPixels(new Rect(0, 0, targetX, targetY), 0, 0); result.Apply(); return result; }
Maybe it's serializing and deserializing it but since activeLight is not a texture saved to disk it can't restore it
Try removing the resize and seeing what it does then
that does fix it
So yeah the problem is that your texture can't be restored since it just exists in memory
Not sure why OnEnable is not called again though
#↕️┃editor-extensions message still looking for answer for this question
The pedant in me, asks, why do all my other vars not reset, as they are all volatile, and Texture2D should be no different to any other varaible
Texture2d is not serializable, only the GUID of it is
Since it only exists in memory there's no GUID only an instance
Unity probably recreates the window and secretly serialized and deserializes everything
But since the texture is only in memory it can't restore it
Any ideas why OnEnable isn't being called, i'm pretty sure it used to be called
I guess it's because unity is secretly destroying and recreating it
Unity does some weird shit to try to make editor windows persist at times
I think i'll just have to hard set the size, thank you for the assist
@naive loom if DrawDisplay is being called before PopulateData, it'll null ref exception, as you will be trying to access an array that hasn't been initialized, and if the PopulateData is not being called because of the exception....
You lack any null error checking to stop any code executing if the vars are null
if I use an array, before I access that array, I always use a check to see if the array exists and is not null
@waxen sandal Is there a better way that I can load images, other than place them in the Resources folder and use Resources.Load<Texture2D>() perhaps?
assetdatabase.loadasset
Thanks, but anyway i just realize its my inpector view problem, so i need to make it larger then i see the last data which ithink missing, but now im adding min widht for it, and its workinh as expected
@waxen sandal that still won't allow me to resize though will it
the problem that I have is that when I resize the actual image, the icon appears low quality
I can change the width height of a regular button, using cs if (GUILayout.Button(activeButton, ButtonStyle, GUILayout.MaxWidth(maxWidth), GUILayout.Height(32)))
however, with a toolbar, using cs GUILayout.Toolbar(toolbarOption, toolbarContent, ToolbarButtonStyle, GUILayout.Width(25)); results in the button image being super small
ok, nvm, i solved this issue.
hey folks, is there anywhere I can see a list of UnityEditor types?
for example...
UnityEditor.TransformInspector
UnityEditor.RectTransformEditor
etc
I found the first one in a script online, and the second one through trial and error. I'm trying to extend more editors but just fumbling in the dark trying to guess their names.
the unity Github repo might have some information, but I fear that there is a lot to sift through and nothing concrete on a list of the different editors
Lets say I have my editor project in the folder "Assets/Plugins/MyEditor" is there a way I can reliably get that directory if someone decides to move it somewhere else?
for example, using a reference to cs AssetDatabase.LoadAssetAtPath<Texture2D>("Assets/Plugins/ConfigurationTool/Images/ActiveLight.png"); if someone moves that directory, that hard path is going to be invalid and the asset won't load any more
found a full list here! https://pastebin.com/Kq3T8aMw
from this article: http://www.li0rtal.com/extending-unity-inspectors/
😄
Pastebin
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.
Use relative paths to the root of your plugin (e.g. some config file you can find easily)
so, something like, create an SO then just search for that SO when the editor is booted up?
Yeah
Use the CS Reference so you can poke around without guessing https://github.com/Unity-Technologies/UnityCsReference
ah nice one, thank you for the link
There a way to have a control element and not draw procedural?
In my case, I have something that can manipulate both scene objects and scriptable objects so for the purpose of identifying either I'd like to have a panel/group which I can force as the drawn parent and then when looping through these types I can tell X to draw in group A and Y to draw in group B...
Or would I have to do the "page/tab" style and identify/split these objects into their separate draws at identification?
Not UI elements to add
Hi, I can print the size with Debug.Log("Size: " + l.serializedProperty.GetArrayElementAtIndex(l.index).FindPropertyRelative("down").arraySize);
how can I iterate through all the items?
you'd still need to do GetArrayElementAtIndex on your find property relative
It is actually an List<GameObject>
@grim walrus i tried this:
l.serializedProperty.GetArrayElementAtIndex(l.index).FindPropertyRelative("down").GetArrayElementAtIndex(i) as GameObject
didnt work
oh hey!
Debug.Log((l.serializedProperty.GetArrayElementAtIndex(l.index).FindPropertyRelative("down").GetArrayElementAtIndex(i).objectReferenceValue as GameObject).name);
seems to work
yeah that would, GetArrayElementAtIndex just returns a serialized property not the actual value
hello again folks, I'm trying to get some script working that should toggle Inspector's Debug Mode. I was using this script: https://gist.github.com/baba-s/5f7a055d45bd327c385137fa2b501f3d
it worked for a while but broken at some point (possibly after a Unity update??)
"methodInfo.Invoke" (line 29) fails because methodInfo is null
it does not find the methodName "SetDebug". how can I figure out how to fix that?
Find it
how?
Double Check the method signature
I mean before coding
Parent class, method name, flags
found this in the CS reference... looks like it matches??
SetNormal doesn't work either, just tested that too
Yes it seems to match
not really sure where to go from here if I'm honest 😕
GetMethods
OK so I managed to figure out how to use this and got it to log all the method names. there's nothing called SetDebug or SetNormal but there is "SetMode". no idea what that does though, or what parameters it takes 🤷♂️
might have to give up on this, I feel like I'm in over my head
SetMode is probably the one that takes Normal/Debug as a parameter
thank you.. that would be my guess but Invoke's parameters require an object[]. how would I write "InspectorMode.Debug" as an object array?
without the version, I cant tell
oh... the reference is for 2020.2.0 😦
new object[] { InspectorMode.Debug }
IT WORKS!
swap out the explicit for some variable...
You had one for the method name, just switch that one to be InspectorMode.Normal/Debug
yeah, got it. here it is in action (mapped to Ctrl+I for quick toggle)
perfect, thank you for the help @grim walrus
Is there a way to exclude mesh from builds?
dont have them referenced anywhere is one but I'd assume that wouldn't be the desired outcome
if you wanted to do it yourself you'd have to make some elaborate dependency walker for your build processors
I guess a dummy mesh that i use to replace it first, then restore it on PostprocessBuild
Bad idea, or bad design
Only reference it in scenes that are only loaded in the editor, not included in the build?
i have a black screen now lol
public static void DrawLine(Color color, Vector3 start, Vector3 end)
{
var rect = EditorGUILayout.GetControlRect(false, 0f, GUILayout.ExpandHeight(true));
var rt = RenderTexture.GetTemporary((int)rect.width, (int)rect.height, 16, RenderTextureFormat.Default, RenderTextureReadWrite.Default, 4);
rt.Create();
RenderTexture.active = rt;
// now all GL calls will be drawn onto the render texture.
GL.Clear(true, true, Color.clear);
GL.Begin(GL.LINES);
GL.Color(color);
GL.Vertex(start);
GL.Vertex(end);
// Then draw this texture inside the window
GUI.DrawTexture(rect, rt);
RenderTexture.ReleaseTemporary(rt);
GL.End();
}```
@short tiger
@acoustic egret I wouldn't expect this inside a static method called DrawLine
The render texture stuff should only happen once per frame
You setup the texture before the draw commands
And when you're finished drawing everything into the texture, you draw that texture in the editor window
Same thing
So you want a single line inside each viewport?
Here's what I'm doing:
var rect = EditorGUILayout.GetControlRect(false, 0f, GUILayout.ExpandHeight(true));
var rt = RenderTexture.GetTemporary((int)rect.width, (int)rect.height, 16, RenderTextureFormat.Default, RenderTextureReadWrite.Default, 4);
rt.Create();
RenderTexture.active = rt;
GL.Clear(true, true, Color.clear);
if (SelectionEvent.Instance != null)
{
EditorUtils.DrawArrow(Color.red, SelectionEvent.Instance.From.Rect.center, Event.current.mousePosition);
}
foreach (var state in StateMachine.Nodes)
{
foreach (var t in state.Transitions)
{
EditorUtils.DrawArrow(new Color(0.3f, 0.3f, 0.3f), state.Rect.center, t.Rect.center);
if (t.To) EditorUtils.DrawArrow(new Color(0.3f, 0.3f, 0.3f), t.Rect.center, t.To.Rect.center);
}
}
GUI.DrawTexture(rect, rt);
RenderTexture.ReleaseTemporary(rt);```
This portion of the function draws all the lines each frame
So if selecting a thing, it draws an arrow (just line for now) between the selection and cursor
Then it draws lines between nodes
So basically just draws a bunch of lines
So this is for a node graph?
public static void DrawArrow(Color color, Vector3 start, Vector3 end)
{
DrawLine(color, start, new Vector3(start.x, end.y));
DrawLine(color, new Vector3(start.x, end.y), end);
}```
Correct
public static void DrawLine(Color color, Vector3 start, Vector3 end)
{
GL.Begin(GL.LINES);
GL.Color(color);
GL.Vertex(start);
GL.Vertex(end);
GL.End();
}```
Wouldn't you want the nodes also anti aliased?
I'm using GUI.Window for those
works fine
I just want pretty lines D:
This is the alternative but I still need arrow indications of direction
Then my approach isn't good.
no worries, thanks anyway
From your first screenshot, it looked like you wanted to draw arbitrary shapes/meshes antialiased
But if it's just lines and triangles, it makes more sense to use shaders that calculate their own anti aliasing
Why? Im working with Mirror which mixes server and client workflow in the same project
https://forum.unity.com/threads/headless-server-dont-include-textures-in-build.968280/#post-6403695
Theres an asset that does this but as quoted in the forum post, it might be doing a lot of writes to do this and so not good for my ssd
I was gonna do what this asset does but not rewrite/reimport.
To avoid that, maybe re-reference all the mesh/texture with another a dummy, while keeping reference but not as UE.Object, maybe just array of their guid. Then restore the refs when done
there are supposed to be textures here.
there are not.
unity is saying the variable has not been defined, when it should have been.
this is being called in OnGUI():
EditorGUI.DrawPreviewTexture(new Rect(0, 0, 128, 128), previewTexture);
this is being called on Start():
previewTexture = new Texture2D(512, 512);
this is the class member declaration of previewTexture
public Texture2D previewTexture;
also how can i make the texture just display in the block layout instead of needing to set its absolute position?
also why is there like, GUI, GUILayout, EditorGUI, EditorGUILayout, and why do they all work for EditorWindows?? its so confusing 😭
this is the error mesage btw
Lol, you are correct. This isn't 1000 either because I haven't implemented cache resizing yet, right now the cache is set to 500. This is as fast as it is possible to be afaik. Though as you can see even when scrolling pretty quickly you can't see hardly see them being loaded(Talking about the first scroll up).
The bottleneck to making it faster is File.ReadAllBytes, so not too much I can do about that. I capted it at 55 reads max per update, so not to lag too bad.
https://streamable.com/jhumo7
Besides resizing the cache to support multiple windows. I want to try to figure out a way to set a max number of files, but I haven't been able to think of a way yet.
Man, I'm not even doing reflection or anything! This is like the third time I have made this error, and I'm not even exactly sure what line of the code is causing it!
So. I know I can get the camera that the SceneView uses, and I know I can generate a render from the camera, but the problem is that that render includes the blank blue background of the prefab scene, is there a way to only get the objects with a transparent background?
I figured that out but now I'm wondering, is there a way to create a temporary SceneView that doesn't appear on screen in the editor?
EditorSceneManger.CreatePreviewScene
There is also PreviewRenderUtility which may help/do what you want.
Ok. Thanks!
I found a way to show a thumbnail over the icon in the editor, and it works, but I still have to generate the preview, and my options are use the camera and scene view to generate it which is WAY easier, or manually copy over each sprite's texture into a temporary texture and then use that to generate the thumbnail which is yuck
Even just because the thumbnail is square and my sprites are in a bounds that is vertically rectangular, so I'd have to position it in the center manually and make sure all the layers are positioned correctly and just ugh
It's much easier to change the scene to frame the bounds and then render it to a render texture and then copy the texture data to a Texture2D and give that to the GUI.DrawTexture().
hello , can i hide the MenuItem? i just want to trigger the function by shortcut
@visual stag i need your help ,bro
Don't ping me into your issues, I am not a personal resource, nor is anyone else for that matter
my appoligize
Is there any way to recreate/reuse the PropertyDrawers in Light Inspector (HDRP) GUI? They have a neat drawer for the light color temperature that can swap the measurement unit and has other visual aids, but it would certainly be a huge bother to copy its implementation completely from scratch with my skills.
Any other similar cases are also of general interest: if not this one specifically, are there cases where you have found ways to reuse how builtin Components do some special drawing for some properties?
I have 2 buttons, which contain images & text, however they are not centred properly.
void Init()
{
GUIStyle ButtonStyle = new GUIStyle(GUI.skin.button);
activeLight = AssetDatabase.LoadAssetAtPath<Texture2D>("ActiveLight.png");
sceneActiveButton = new GUIContent("Scene Configuration", activeLight, "Active Scene Configuration");
}
void OnGUI()
{
EditorGUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
GUILayout.Button(sceneActiveButton, ButtonStyle, GUILayout.MaxWidth(150), GUILayout.Height(32));
GUILayout.Button(sceneActiveButton, ButtonStyle, GUILayout.MaxWidth(150), GUILayout.Height(32));
GUILayout.FlexibleSpace();
EditorGUILayout.EndHorizontal();
}```
Any idea why the 2 buttons aren't centred correctly please?
I'm also finding that when i set the MaxWidth to low values, ie 50, the width of the button does not conform to this size. If I set the MaxWidth to 170, the buttons become centred properly.
I think i solved this by adding a MinWidth, meh.
I want some buttons to arrange themselves to occupy the space available, if there width is too small, for them to overflow vertically so instead of a single row, I'd have a 2nd row, anyone have any pointers for where & what I should search for on google for this please?
Can you move an object to a scene that isn't part of a scene already and then move it out of that scene. Like "EditorSceneManager.MoveGameObjectToScene(prefab, null);"?
There is also SceneManager, and I'm not sure, you can look at the docs, and also just try moving GameObject to a null scene and see what happens 😉
The editor underlines "null" in red.
Oh yeah, that is because Scene is a struct.
What is the reason for wanting to do this?
Because I created an empty preview scene with EditorSceneManager.NewPreviewScene(), but now I need to actually put my prefab in there, frame the object in the scene, use the camera to take a snapshot, and then tear everything down.
LOL, I am litterally doing that exact same thing right now.
What you would do is keep a list of all the GO added to the scene, then loop through them and destory them.
Right, but if I destroy them, does that destroy the prefab?
Wait.... are you creating thumbnails like I am?
Because I finally figured out how to override the thumbnails in the editor
Not if you do PrefabUtility.InstantiatePrefab and add the instance to the scene and then destroy that instance 😉
Yup... sort of. I am making thumbnails for objects but with no background.
If you want once I am done later today I can just share it with you. 🙂
I would love that!
I discovered EditorApplication.projectWindowItemOnGUI
And I finally have that working
But now I need to generate the image to put there.
Why are you making custom thumbnails?
Because unity doesn't always do it properly for my prefabs.
In what way?
I just get a blank transparent square with a drop shadow and highlight
especially after cropping the images in the asset database
Uh, what do your prefabs look like?
They look like an anime character
But the face is overlaid on a body and accessories are overlaid on the body as well
It's for a visual novel
Lol, I mean what sort of rendering components are there and what are there rotations 😛
Oh. no rotations, And it's a tree of game objects, the root game object has a script, and the deepest objects have a SpriteRenderer with the layer texture
The script chooses what layers to show by disabling the renderers that are hidden. So when the game script changes the outfit or the face, it disables the currently enabled renderer and enables the appropriate renders to composite the face to the body
The default appearance is what is enabled when the prefab is saved
Preferably one face, one body, and possibly an accessory
Is there a good way to get rid of the border? I can switch to point filter of course, but makes the preview look kind of pixely.
I could draw it with EditorGUI.DrawPreviewTexture and a material, but it then doesn't respect GUI masking.
Anyone know a good location of resources on using visual elements? Want to get off the immediate mode stuff and replace my editor scripts going forward
Unity learn has getting started tutorials along with the unity manual.
anything more specific? Theres a pinned youtube video which is a little too beginner.
The learn has a bit more, guess I'd just have to figure it out from there
How do i make my scriptable object information be shown in the script thats using it?
find and draw its properties
No idea how to work with the editor stuff
Some 5 years ago i found a post that showed how to do it but i lost it
http://answers.unity.com/answers/1035337/view.html oh, is this it?
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.
you could use a property drawer if you wanted... But if you have an editor script for this script you are talking about then you can just find the properties and draw them as part of that editor script
yup i think i found it
oh but now its not showing the properties that were on that class 
base.OnInspectorGUI() 😉
😉
I just did DrawDefaultInspector(); - seems to have worked 😄
any difference?
Literally none