#↕️┃editor-extensions

1 messages · Page 4 of 1

whole steppe
#

I have a couple of AnimationClips that I'd like to apply a AnimationCompression on, I tried doing that like so:```cs
foreach (AnimationClip clip in Selection.GetFiltered<AnimationClip>(SelectionMode.DeepAssets))
{
ModelImporter importer = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(clip)) as ModelImporter;

importer.animationCompression = ModelImporterAnimationCompression.Optimal;

importer.SaveAndReimport();

}```However, it's failing due to the importer being null... not sure what exactly is happening. How to properly perform an AnimationCompression when I don't have an actual model but only the AnimationClips?

indigo pilot
#

Can I register multiple objects to undo with this? Undo.RegisterCreatedObjectUndo

#

Do I have to register all of the created object? Or can I just register the parent?

#

Creating multiple object in a parent.

gloomy chasm
gloomy chasm
warped sequoia
#

hi guys, all my components are disabled and i dont know why, any ideas ?

gloomy chasm
warped sequoia
gloomy chasm
warped sequoia
#

yeah my bad aha

#

thanks a lot

jagged mirage
#

thank you though =)

gloomy chasm
misty igloo
#

anyone know how to have a method fire after a package is imported and before a package is removed?

gloomy chasm
misty igloo
#

awesome thanks mech as always!

gloomy chasm
#

Sure thing! 😄

wooden wigeon
#

Are there any cheap solutions for unity real time collaboration its a small project not looking for me than like 2 people and unity reflect just seems really expensive.

lime arrow
#

Hi all, is there a way I can make a button create a miniature component (couple of text boxes, dropdowns etc.) when i click a button?

I am writing a plugin for a member of my team that will allow them to build dialogue for the game from within the engine

#

the types are "Text" and "Choice", and i basically want it to add loads of fields when you click "Add"

#

but this would need to be able to be dynamic, if that makes sense?

#

more importantly, how do i make a label appear after a button is pressed?

indigo pilot
lime arrow
#

thank you, i got it working a different way now

indigo pilot
lime arrow
#

thank youu

#

i've found out about repaint which is helping me with some of the stuff now as well

fluid wolf
#

How would you make an custom inspector support dragging objects onto it?

#

Like assets

misty igloo
grand matrix
wheat brook
#

I installed "Debugger for Unity" by deitry, but when I press Run and Debug I dont see the option to create Unity configuration. Anybody encountered the same problem?

wheat brook
indigo pilot
#

What's the easiest way to save editor fields per object?

#

Nvm just found out its so easy with EditorJSONUtility

gloomy chasm
indigo pilot
#
    public partial class TileBuilderEditor : UnityEditor.Editor
    {
        [SerializeField] private bool _tileInfoFoldout = true;
        [SerializeField] private bool _settingsFoldout = false;
    }
#
        private void OnEnable()
        {
            EditorJsonUtility.FromJsonOverwrite(EditorPrefs.GetString(typeof(TileBuilderEditor).ToString()), this);
        }

        private void OnDisable()
        {
            EditorPrefs.SetString(typeof(TileBuilderEditor).ToString(), EditorJsonUtility.ToJson(this));
        }
#

I just tried this just now, and it worked really well

#

:)

gloomy chasm
indigo pilot
#

Saving those foldouts

#

So it stays open/close next time I open the same object

gloomy chasm
#

Like between editor sessions?

indigo pilot
#

Yeah

gloomy chasm
#

If it is fine to only stay during the session (like how most editor state things work) then you can use either SessionState or inherit from ScriptableSingleton. And if you want to save between sessions then you can add the [FilePath] attribute to the ScriptableSingleton.

indigo pilot
#

Ooh, I'll take a look at those as well

gloomy chasm
#

But don't do what you are doing. That will save for all unity projects. So if you toggle a bool on one, then open another project, it will also be toggled now.

indigo pilot
#

I see

#

This is per object?

misty igloo
gloomy chasm
indigo pilot
#

Ok I see

indigo pilot
# gloomy chasm If it is fine to only stay during the session (like how most editor state things...
        private void LoadSettings()
        {
            string loadData = SessionState.GetString(string.Format(KEY_FORMAT, SAVE_KEY_NAME, "Settings"), "");

            if (loadData != "")
            {
                _settings = (TileBuilderEditorSettings)JsonUtility.FromJson(loadData, typeof(TileBuilderEditorSettings));
            }            
        }

        private void SaveSettings()
        {
            SessionState.SetString(string.Format(KEY_FORMAT, SAVE_KEY_NAME, "Settings"), JsonUtility.ToJson(_settings));
        }

Like this?

trail dawn
grand matrix
trail dawn
#

Resource is for sharing just that. Specifically anything for learning, or not specifically an asset (which would be #502171717544968212)

tepid roost
#

Anyone familiar with the UnityEditor.Experimental.GraphView got things working about 90% how i need them, but oddly i can not figure out how to have a node type that can not be deleted

#

aside from just making it non selectable

gloomy chasm
tepid roost
#

oh, cool was my next thought, so as long as i remove it from the graphViewChange.elementsToRemove before it returns i am good then

gloomy chasm
#

Think so. But it has almost been like 2 years since I did much with the API

tepid roost
#

will find out in a sec

#

seems to do the job

#

but i also need to make sure i do not lose my edges attached to it as well

#

now will see if it only works mutating it in place, or its fine with me just shoving a new list into it

gloomy chasm
#

it has to be the same list because it is the list that is referenced

tepid roost
#

it depends on how its being accessed later on, directly from a list reference, or via the graphViewChange

#

oh

#

you are correct

gloomy chasm
#

Nope

tepid roost
#

graphViewChange is a value type

gloomy chasm
#

Yeah

tepid roost
#

yeah has to be the lists

#

little annoying since need to do it in too passes, one to find the stuff to ignore, and one to remove so i do not edit the collection i am currently iterating but still easy enough

gloomy chasm
#

Reverse loop

#

Or Linq

tepid roost
#

think i am best of caching it anyways, since i would only want to prevent the deletion of the edge coming off my root node, if its caused by a root node deletion

gloomy chasm
#

(super pseudo-code-y)

tepid roost
#

other thing you might know off hand that, is how you translate a mousePosition to a GraphView position

#

ah found it

#

var pos = viewTransform.matrix.inverse.MultiplyPoint(evt.localMousePosition);

gloomy chasm
wraith needle
#

Guys is there a way to make an object snap into certain angles like 0, 90, 180, 270 degrees?

#

like if i move it to x position it will snap into one that's 90 degrees compared to the previous point

wraith needle
#

Is there a way to get to know when i click / hold my mouse button?

real spindle
#

What Handles or GUI functions should I use to display a scalable Rect, similiar to in the Sprite Editor?

#

Something like BoxBoundsHandle but 2D 🤔

gloomy chasm
real spindle
gloomy chasm
gloomy chasm
real spindle
visual stag
#

If you're asking how to do something similar to a built-in thing just look at the source and you more likely than not have your answer

tepid roost
#

is a github page that has a lot of sources for things like this

#

but also rider and i am sure other editors can step into the C# parts of the unity source for you with its go to def command

visual stag
#

And every package contains their own source

indigo pilot
#

For some reason, this code always leave 1 child alive in editor.

for(int i = transform.childCount - 1; i >= 0; i--)
{
    Object.DestroyImmediate(transform.GetChild(i).gameObject);
}

Anyone knows why?

#

But if I do this..

List<Transform> childrens = parent.Cast<Transform>().ToList();

foreach (Transform child in childrens)
{
    Object.DestroyImmediate(child.gameObject);
}

It cleans up perfectly.

#

But I don't want to create a list every time I want to destroy all childrens

#

Its so strange @@

#
while (parent.childCount > 0)
{
    Object.DestroyImmediate(parent.GetChild(0).gameObject);
}

This worked too, and no list :)

distant atlas
#

Anyone know how to draw this style of choosing? I want to have it for the add button of a reorderable list

#

Right now I just use GenericMenu so it doesn't look as good

wraith needle
#

Guys which type of handles or GUI should i use to draw something like the squares between each axis?

indigo pilot
#
private void DrawTestSO(TileBuilder tileBuilder)
{
    SerializedProperty prop = serializedObject.FindProperty("TestSO");
    _settings.TestSOFoldout = EditorGUILayout.PropertyField(prop, true);

    if (_settings.TestSOFoldout)
    {
        // How to draw the contents of the scriptable object?
    }

    serializedObject.ApplyModifiedProperties();
}

How to draw the content of a scriptable object?

#
SerializedProperty prop = serializedObject.FindProperty("TestSO");
_settings.TestSOFoldout = EditorGUILayout.PropertyField(prop, true);

if (_settings.TestSOFoldout)
{
    // What do I even fill for the ref?
    UnityEditor.Editor.CreateCachedEditor(prop.objectReferenceValue, prop.objectReferenceValue.GetType(), ref ?);
}

serializedObject.ApplyModifiedProperties();
#

What I fill for previous editor field?

#

213 people are following this question

#

And its only created yesterday

#

So nobody knows how to use this?

distant atlas
#

that only displays it in a read-only manner

indigo pilot
distant atlas
#

oh wait that one makes a lot of errors, apparently this is the correct way to do it

var op = new SerializedObject(prop.objectReferenceValue);
op.Update();
var iter = op.GetIterator();
iter.Next(true);
do
{
  EditorGUILayout.PropertyField(iter, true);
} while (iter.NextVisible(false));
op.ApplyModifiedProperties();
indigo pilot
#

Ohh

distant atlas
indigo pilot
#

I can just apply modified property on that

#

Thanks!

#

Yes figured out at the same time :)

#

Though, that do expose some unwanted fields. I'll try filter it out.

distant atlas
#

this ought to skip them. inside the do while loop:

if (iter.propertyPath == "m_ObjectHideFlags" || iter.propertyPath == "m_Script")
{
    continue;
}
gloomy chasm
indigo pilot
#

Changing these does not work.

gloomy chasm
tough cairn
#

is there a way to rename nested scriptable objects ?

gloomy chasm
tough cairn
# gloomy chasm You mean in editor? Don't think so. In code you just change it's name like any o...
public override void OnInspectorGUI() {
  using( var scope = new UnityEditor.EditorGUI.ChangeCheckScope() ) {
    var script = ( ScriptableObject ) target;
    var name = UnityEditor.EditorGUILayout.TextField( script.name );
    if( scope.changed ) {
      UnityEditor.Undo.RecordObject( script , "rename" );
      script.name = name;
      UnityEditor.AssetDatabase.SaveAssetIfDirty( target );
      //var path = UnityEditor.AssetDatabase.GetAssetPath( script );
      //UnityEditor.AssetDatabase.ForceReserializeAssets( new string[] { path } );
      //serializedObject.FindProperty("name").stringValue = name;
      //serializedObject.ApplyModifiedProperties();
  }
}

thanks seems to do the trick , however i need to browse into a different folder and back where* the SO is located before i can see the icon label changed in the Project window , tried to force reserialize but doesn't seem to help

tough cairn
indigo pilot
#
EditorGUILayout.LabelField("Tool Set Settings", EditorStyles.boldLabel);
_toolSet = serializedObject.FindProperty("ToolSet");

EditorGUI.BeginChangeCheck();

EditorGUILayout.PropertyField(_toolSet, true);

serializedObject.ApplyModifiedProperties();

if (EditorGUI.EndChangeCheck())
{
  InitializeToolBrushNames();
}

Help me, ToolSet is a Scriptable Object. This seems to work if I manually change from the inspector.
But does not behave properly with undo/redo.

When set to none, its set to none.
When undo, its set to previous ref.
When redo, its not set to none. (Still same ref)

#

Its such a strange behaviour :c

#

Nvm, it worked now after I deleted the custom editor for the SO for some reason..? @@

tough cairn
#

ok i figured it out :

UnityEditor.Undo.RecordObject( script, "rename" );
script.name = targetName;
UnityEditor.AssetDatabase.SaveAssetIfDirty( target );
UnityEditor.ProjectWindowUtil.ShowCreatedAsset( target );
gloomy chasm
tough cairn
#

yea i wanted to do a manual repaint at first

#

but then i randomly found this method when scrolling through the suggestions pop up context and it seemed to work

gloomy chasm
#

Yeah, if it works than great! There was another level I could dig down in to the class that actually handles showing the assets, but it is complex and didn't care that much to look haha
(Don't forget to add a comment for future you for why you use that method 😉 )

whole steppe
#

Any idea why this is not working?

[MenuItem("Test/Run")]
static IEnumerator RunTest()
{
    Debug.Log("Test!");

    yield return null;
}```
whole steppe
short venture
whole steppe
#

Dang it, I thought I can finally do async operations withing an editor script!

short venture
#
[MenuItem("Test/Run")]
void RunTest() { StartCoroutine(DoRunTest()); }
static IEnumerator DoRunTest()
{
    Debug.Log("Test!");

    yield return null;
}

If you must

whole steppe
#

So this means if I run this

Resources.LoadAsync()```In a coroutine, it wouldn't be considered as an async operation?
short venture
#

No, Coroutines run on the main thread, they are, in real terms just extensions of the Update methods

whole steppe
short venture
whole steppe
short venture
whole steppe
#

Ok cool, now this is what I see:

#

Is it normal?

#

Oh! It's not supposed to be static!

#

Right?

#

Gosh I'm lost!

#

If it's not static then it won't appear on the Menu Items!

#

yikes!

short venture
#

make it a singleton to get around that

#

what are you trying to do that you need a coroutine/async method anyway?

whole steppe
#

Load a bunch of AnimationClips into an array to do some stuff with them, however they're mocap-ed therefore very heavy to load, normal loading would take like 2mins each time I'd like to load them! There can be and there's better ways to do that, I just don't know of...

short venture
whole steppe
#

Because I'm getting a NullReferenceException...

short venture
whole steppe
#

Alright!

whole steppe
#

With that said, thanks a lot for tying to help!

short venture
whole steppe
#

Okay, never-mind, it's always returning null on line 79 for some reason, I'll just do it the old way...

short venture
whole steppe
short venture
severe lance
#

What's the best way to prevent the user messing with transform values in the scene for when I just need them for raycasting purposes? The parent should be the only thing that's editable, so hiding the children in the hierarchy would be ideal.

#

Hiding the transform component from the inspector and forcing the tools to disable when selected is possible, but it's pretty wonky I got these dead gameobjects on the scene hierarchy

#

nm, im dumb. There's actually a hide flag for it too

whole steppe
severe lance
#

Yeah, exactly. I for some reason thought that was for the inspector, but there's a inspector one too.

whole steppe
#

I guess we're not calling it a day lol! It still says no despite the fact it's receiving the correct asset path... pay attention to the file extension you blind fak

short venture
whole steppe
#

doing just that rn!

whole steppe
#

OKAY!!! Now it all makes sense!! I just didn't quite understand how coroutines work...
It seems that I have to yield return the Object in question to the IEnumberator and then check if it's been successfully loaded to next make use of it...
So something like this:

#
[MenuItem("Tools/Async Load")]
private static void StartAsycnLoad() => new GameObject(nameof(GeneralEditor))
    .AddComponent<GeneralEditor>().StartCoroutine(AsycnLoad());
private static IEnumerator AsycnLoad()
{
    foreach (string guid in AssetDatabase.FindAssets($"t:{nameof(AnimationClip)}", new[] { "Assets/Resources/AnimationClips" }))
    {
        string pathInResources = AssetDatabase.GUIDToAssetPath(guid).Replace("Assets/Resources/", string.Empty).Replace(".anim", string.Empty);

        ResourceRequest loadedObject = Resources.LoadAsync<AnimationClip>(pathInResources);

        yield return loadedObject;

        while (!loadedObject.isDone)
        {
            yield return null;
        }
            
        Debug.Log(loadedObject.asset.name);
    }
        
    DestroyImmediate(GameObject.Find(nameof(GeneralEditor)));

    yield return null;
}```
#

With that said, thank you a bunch! As much as I'd like to use your solution, I sadly can't for 2 obvious reasons:

  1. Can't run the Editor when its place where it should be, (e.i., Editor Folder => https://docs.unity3d.com/Manual/SpecialFolders.html) because its now a MonoBehaviour
  2. Can't inherit from any Editor class... due to how class inheritance work.
    Still thank uuuu!!
waxen sandal
#

Have you looked at the editor coroutines package?

#

Also, your thing probably breaks if you reload the assembly mid process (i.e. going into play mode)

peak bloom
peak bloom
whole steppe
waxen sandal
#

Right okay

severe lance
#

For undo operations, such as deleting gameobjects and removing their entry of a dictionary, would I require keeping track of these entries after deletion or is it possible for Unity to handle it?

waxen sandal
#

Unity has the Undo class for most of that

#

But it needs to be serializable

severe lance
#

Ah, shoot.

waxen sandal
#

So deleting gameobjects works but not the dictionary thing

severe lance
#

That's good at least. Didn't feel like creating that whole system of previous entries.

hushed oar
#

Hey guys, I can't find the right search terms to get documentation on how to replicate Volume style editors:

#

Could anyone help me? Specifically, adding different "classes" or "modules" into a component in the editor

gloomy chasm
hushed oar
#

Oof, does Odin do something like that?

gloomy chasm
#

No idea, not the Odin server 😉

#

It really isn't too bad to do tbh though

hushed oar
#

Fair enough :p Architecturally speaking, it's just a list of classes that derive from the same base class or interface. The tricky part is the UI to select which class to add to the list

#

In the volume, the button "Add override" shows a list of different types that can be added to the volume

gloomy chasm
#

Nah, that is pretty easy too. You use TypeCache.GetTypesDerivedFrom<ModuleBase>() to get all the types, loop over them adding them to a dropdown, and when selected you just create a instance of the type and add it to the list

hushed oar
#

And Unity supports serializing a list of derived types?

gloomy chasm
#

If you add the [SerializeReference] attribute to the field

hushed oar
#

Ha yes, you got it! Thanks for the guidance 🙂

gloomy chasm
#

Sure thing!

#

I would probably recommend using UIToolkit for the UI as it will be easier to style like the Volume's UI.

hushed oar
#

Will look into it, thank you!

vapid prism
#

How can I clear all changes on a SerializedObject? It seems that dirty state persists even if a user Undos (ctrl z) whatever change they did. This can be reverted by calling EditorUtility.ClearDirty() but it only modifies the flag. I have a system that tracks modifications and highlights them, but since the dirty flag isn't reset my system thinks it's still dirty, and explicitly calling clear doesn't clear changes.

timid coyote
#

Can I draw a horizontal line in a PropertyDrawer, like you can do with EditorGUILayout.LabelField(string.Empty, GUI.skin.horizontalSlider); in a custom editor?

boreal carbon
timid coyote
gloomy chasm
#

Changes from when?

timid coyote
vapid prism
#

I.e the user modifies any field and hits ctrl z

#

Object is now dirty (but there are no actual changes)

gloomy chasm
#

I don't think there is a way. The best you can do is probably read the file and get the state from that. You can use LoadAndForget() for that. You create a SerializedObject from the one you loaded and iterate over the SerializedProperties, copying the values to your current one. Then unload the thing you loaded.

#

With all that said, you are most likely trying to do something that you shouldn't 😛

vapid prism
#

It's assets, sorry should have clarified. But the issue is essentially that an asset will keep the dirty flag even if all changes have been undo. Since my system reads the dirty flag its showing the asset as modified, when in reality all changes have been undo

gloomy chasm
#

So clear the dirt flag...?

vapid prism
#

Yeah that's the step I'm not sure if there's a way. I'd have to clear the flag once there's no more undo states, otherwise there may be some changes missed. Maybe thats a better question actually, can I somehow see if there are recorded undo states for a certain asset?

#

Else I'm not sure when I could safely clear the dirty flag

rugged urchin
#

is there a way to know which Display is currently under the editor mouse, when there are two game views with distinct camera displays?

#

without clicking (and giving focus to) the editor window?

rugged urchin
gloomy chasm
rugged urchin
#

okay this is pretty similar

#

to some ancient code i wrote years ago

#
            var mouseOverWindow = EditorWindow.mouseOverWindow;
            var assembly = typeof(EditorWindow).Assembly;
            var type = assembly.GetType("UnityEditor.GameView");

            var displayId = 0;
            if (type.IsInstanceOfType(mouseOverWindow))
            {
                var displayField = type.GetField("m_TargetDisplay", BindingFlags.NonPublic | BindingFlags.Instance);
                if (displayField == null)
                {
                    return;
                }
                displayId = (int) displayField.GetValue(mouseOverWindow);
            }

@gloomy chasm does this look right to you?

#

i've been using focusedWindow instead of mouseOverWindow facepalm

gloomy chasm
gloomy chasm
rugged urchin
#

i think Display has some useful methods

#

the position reported by the editor only changes when the window is focused

gloomy chasm
rugged urchin
#

input system also has some built in processors

vapid prism
gloomy chasm
gloomy chasm
rugged urchin
#

when i am using Input System only

gloomy chasm
rugged urchin
#

editor only

gloomy chasm
#

How are you using the input system in editor...?

rugged urchin
#

like i don't want to touch the Input. class

gloomy chasm
#

Can you show some code or something because I don't understand what you are doing

rugged urchin
#

the end-user of the utility creates two game views, each assigned to a different display, corresponding to the player's camera

#

i create Mouse devices for each player and pair them (standard input system stuff). i take the editor mouse state, and i queue its event for a given simulated player mouse only if the mouse state is over the corresponding player's display

#

let's say i click on game view with display 1. the position reported by input system and Input.mousePosition are with respect to that game view, not the whole editor

#

if i move my mouse over to game view with display 2, the coordinates still with respect to game view display 1

#

once i click into game view 2, the coordinates will change to be relative to display 2

gloomy chasm
#

Are you talking about in play mode?

rugged urchin
#

yes

#

so how would i get (1) the real mouse position, in whatever is the coordinate system unity is using before conversion, then (2) convert it immediately into the editor window's coordinates, which appeasr to be ScreenToGUI

#

i can also maybe get the game views' coordinates relative to each other, and do the conversion myself until the user "clicks" and focuses on the other display

gloomy chasm
#

It is a bit ugly, but you can manually convert the position from Input.mousePosition in the game view to the editor window by doing mousePosition.y -= 21 that should be the position in the editor window space

rugged urchin
#

i still need the real mouse position during play mode, instead of the adjusted one

#

i'm not sure how to get the un-adjusted one from input system or legacy input during play mode

gloomy chasm
#

You mean the position of the mouse in the display space?

rugged urchin
#

I don't have Input.mousePosition

#

the editor mouse position from input system?

gloomy chasm
rugged urchin
#

that's correct

#

Input is fully disabled

gloomy chasm
#

I am so confused at this point where you are getting the mouse position from and where you are trying to get it to hahaha

rugged urchin
#

that's pretty much it

#

play mode doesn't matter

#

mouse is always attached

#

anyway, it returns the same value as Input.mousePosition in play mode

#

editorMouse.position.ReadValue() == Input.mousePosition in play mode

gloomy chasm
#

Yeah that makes sense

#

Why not use Event.current.mousePosition?

rugged urchin
#

they're all the same

#

the issue is the value returned there is already transformed into the game view's coordinates

#

but when you move the mouse from Display 1 game view to Display 2 game view, those values are still in display 1 game view's coordinates until you clikc on display 2

#

does that make sense?

#

because it just uses the focused window instead of the mouse over window for the coordinates

#

period full stop

#

i don't know the wisdom of that

#

GUIToScreenPoint doesn't accept an editor window

#

okay i have a good workaround

#

i am focusing whichever game view is hovered over

sly lily
#

Was it ever figured out why Plastic SCM randomly marks assets (usually prefabs) as Changed in the Pending Changes section, when there were no actual changes made to them?

thorn raptor
#

Hey guys, does anybody know how to stop EditorGUILayout.TextArea with ExpandHeight true from filling the area when inside a horizontal scope? it usually only expands when text is in it, but when I put it inside a horizontal scope it expands to match the height of the other content within the scope, but i'd prefer if it didn't do this and still shrunk to fit the text

#

Also bonus question, is there an easy way to render like phantom text in textareas when they're empty? like "enter text here..." type stuff

#

ideally greyer than text is by default so you can differentiate it

#

i wanna save space in the UI while still explaining what a box's function is, since when there is text in it you will be able to figure out its purpose contextually

limpid pebble
#

I wonder how does unity cloud build trigger unity to build?

#

Like which method it executes and what parameters it passes in.

gloomy chasm
gloomy chasm
limpid pebble
gloomy chasm
limpid pebble
#

Trying to intercept the command and build dots project on UnityCloud

#

FYI: in dots 0.51 you need to build using buildPlatform package instead unity's build settings

gloomy chasm
limpid pebble
#

something like the exact commands it sends to unity batch mode

#

Something like this

thorn raptor
gloomy chasm
limpid pebble
#

well we searched "LTB:" and its not even in the log

gloomy chasm
limpid pebble
#

All good buddy, just did

whole steppe
gloomy chasm
#

I am tired atm, so there is probably better ways. But this should get you what you want

tough cairn
tough cairn
#

heh

#

a punny

#

🙂

wise elk
#

what is this???

frank gale
#

Has anyone experienced this huge lag when you click the middle button of the mouse in scene view?
This might only occur after you have worked a while ago.

#

Here's the deep profile stack trace I managed to obtain.

#

Uhmmm, may be I should ask that in code advanced

eternal girder
#

is there a way to append to this settings menu for editor windows?

whole steppe
#

vertx without ping just in case... I think I now have a general idea about combine a mask performing a logical or https://help.vertx.xyz/programming/physics/bitmasks which I was still confused about since last time...
I think I start to understand things when I make use of them at some point...

In my example, I combined 2 types of HideFlags, HideInHierarchy and HideInInspector like so => HideFlags.HideInHierarchy | HideFlags.HideInInspector.

Only then that I got a basic understanding of the logic, thanks to you for pointing it out in the first place.

barren moat
#

How can I make a gizmo in the scene that allows for drag and drop positioning (like a translate gizmo, or polygon editor node)?

#

all g I found it!

#

Handles.TransformHandle

#

"gizmo" was a bad search term

#

(thank you for starting to reply @visual stag 🙏)

barren moat
#

How should I go about pushing my modifications into the undo stack when using a handle like this? If I do it on ever call to TransformHandle I fear that it will create many many undo states, but it's not obvious to me how I would be able to detect the frame in which drag starts and stops.

#

Ha, actually it just works somehow. 🤷

#

Guess unity handles this magically

tepid roost
#

anyone familiar with styling GraphViews?

#

i have one, that is started style and thigns are looking how i want them to, but now i can no longer drag out wires from input and output ports

tepid roost
#

looks like it was because i overriden the flex direction of the Port any one know of a work around

tepid roost
#

its like the part you can drag from is hard coded

timid coyote
#

Does the DecoratorDrawer work with an attribute that targets classes?

gloomy chasm
timid coyote
#

like this, I implemented it, but I'm overriding the OnInspectorGUI of MonoBehaviour, but instead i just want to use DecoratorDrawer that doesnt intervenes with the fields

gloomy chasm
#

Ah, you want decorator drawers on a full class. Nope, no can do without a custom editor.

tepid roost
timid coyote
#

if i dont attach the attribute can i draw the custom editor of the class?, because if i do base.OnInspectorGUI(); will just draw the default unity inspector not the custom one of that class

gloomy chasm
gloomy chasm
normal sage
#

Hey, can I show a color stage's contents in here instead of choosing one?

#

choosing one + contents will be good too

gloomy chasm
normal sage
#

I know it's possible I just can't find the correct search term

gloomy chasm
normal sage
#

in a drawer?

gloomy chasm
# normal sage where puttin' that?

Where ever you want to draw it from 😛
First you create the editor for the SO (You want to cache this and not recreate it each frame)
Second you want to call editor.DrawDefaultEditor() to uh.. draw the editor. This would be in a OnGUI draw method of some sort

normal sage
gloomy chasm
#

ColorStage

barren moat
#

I'm trying to generate a mesh for a polygon collider, but it's taking into account the position of the object that it's attached to, which is doubling its position from the origin:

    [Button]
    void GenerateMesh() {
      if (_mesh) {
        DestroyImmediate(_mesh);
      }
      _mesh = _collider.CreateMesh(
        useBodyPosition: false,
        useBodyRotation: false
      );
      _mesh.hideFlags = HideFlags.DontSaveInEditor | HideFlags.DontSaveInBuild;
      _meshFilter.mesh = _mesh;
    }

My idea to fix this is to move the transform to origin before generating and then back again afterwards like so:

    [Button]
    void GenerateMesh() {
      if (_mesh) {
        DestroyImmediate(_mesh);
      }

      // Move to origin.
      var position = transform.position;
      var rotation = transform.rotation;
      transform.position = Vector3.zero;
      transform.rotation = Quaternion.identity;

      _mesh = _collider.CreateMesh(
        useBodyPosition: false,
        useBodyRotation: false
      );
      _mesh.hideFlags = HideFlags.DontSaveInEditor | HideFlags.DontSaveInBuild;
      _meshFilter.mesh = _mesh;

      // Restore transform.
      transform.position = position;
      transform.rotation = rotation;
    }

However, when I do this the change in transform isn't respected by the function, as if it is using the old transform.position and transform.rotation

#

This video is of the first function

#

(behaviour is the same for both)

#

But if I remove the "restore transform" code I get this behaviour

#

If this were at runtime I'd defer the mesh gen to the next frame, but in editor there are no "frames" so I'm not sure how I can go about getting the collider to respect the position change.

#

Is there a "right way" to do this?

normal sage
#

it doesn't lemme do anything

gloomy chasm
# normal sage I don't understand
[CustomEditor(typeof(FooScriptableObject))]
public class FooEditor : Editor
{
  private Editor _barEditor;

  public override void OnInspectorGUI()
  {
    var barProperty = serializedObject.FindProperty("_bar");

    EditorGUI.BeginChangeCheck();
    EditorGUILayout.PropertyField(barProperty );
    // We do a change check so we can destory the editor, and create a new one for the new object if there is one.
    if (EditorGUI.EndChangeCheck())
    {
      // We know that the object assigned to the BarScriptableObject field just changed, so we can't use the editor we currently have because it is for a different BarScriptableObject (assuming the field was not null before)
      if (_barEditor != null)
        DestoryImmediate(_barEditor);

      // The BarScriptableObject field could have been set to null, which means we of course can't make a editor for it, so we need to check that first.
      // If it was assinged something, than we make an editor for it.
      if (barProperty.objectReferenceValue != null)
        _barEditor = Editor.CreateEditor(barProperty.objectReferenceValue);
    }

    // We draw the editor for the BarScriptableObject if there is one.
    if (_barEditor != null)
      _barEditor.DrawDefaultInspector();
  }

}
#
public class FooScriptableObject: ScriptableObject
{
  [SerializeField] private BarScrptiableObject _bar;
}

public class BarScriptableObject: ScriptableObject
{
  [SerializeField] private float _value;
}
normal sage
#

It's an array

#

not one o them

#

a couple o them

gloomy chasm
#

I'm just showing you how to use it. Not writing it exactly how you would need to do it. Just do this, but for an array instead.

normal sage
#

k k tnx

short tiger
gloomy chasm
normal sage
normal sage
#

(you can ignore me I'm overexcited rn)

normal sage
#

now it only shows color stages 🤦🏻

gloomy chasm
barren moat
# short tiger There is EditorApplication.delayCall which can be considered a one frame delay i...

It ain't pretty but it works:

    [Button]
    void GenerateMesh() {
      if (_mesh) {
        DestroyImmediate(_mesh);
      }

      // Move to origin.
      var position = transform.position;
      var rotation = transform.rotation;
      transform.position = Vector3.zero;
      transform.rotation = Quaternion.identity;

      void Call() {
        _mesh = _collider.CreateMesh(
          useBodyPosition: false,
          useBodyRotation: false
        );
        _mesh.hideFlags = HideFlags.DontSaveInEditor | HideFlags.DontSaveInBuild;
        _meshFilter.mesh = _mesh;

        // Restore transform.
        transform.position = position;
        transform.rotation = rotation;
        UnityEditor.EditorApplication.delayCall -= Call;
      };

      UnityEditor.EditorApplication.delayCall += Call;
    }
normal sage
barren moat
#

Perhaps I'd be better off just creating a new object

gloomy chasm
barren moat
#

At 0,0,0

barren moat
#

All these things seem like nasty hacks

gloomy chasm
normal sage
#

whaaatttt

barren moat
normal sage
# gloomy chasm Idk what your code is so idk what is happening
public override void OnInspectorGUI() {
        var colorStageProperty = serializedObject.FindProperty("colorStages");

        EditorGUI.BeginChangeCheck();
        EditorGUILayout.PropertyField(colorStageProperty);

        if (EditorGUI.EndChangeCheck()) {
            if (colorStageEditor != null) DestroyImmediate(colorStageEditor);

            if (colorStageProperty.objectReferenceValue != null) {
                colorStageEditor = Editor.CreateEditor(colorStageProperty.objectReferenceValue);
            }

            if (colorStageEditor != null) {
                colorStageEditor.DrawDefaultInspector();
            }
        }
    }
gloomy chasm
gloomy chasm
gloomy chasm
# normal sage it always has been

Let me be clear. The code I wrote for you is just an example of how one shows a editor for a field inside of another editor. It is not made to work with your exact setup. I was just demonstrating the APIs and structure you would use. I will edit the code to make that clearer

normal sage
barren moat
#

Since I want to use this at runtime too

gloomy chasm
barren moat
#

You can also use Expand from NaughtyAttributes if you want an SO foldout.

#

That's an SO inspector nested within another SO

barren moat
# gloomy chasm I can think of 2 other options that might be a little less hacky(??) 1. After ge...

Hell yeah dude, divine advice as usual.

    [Button]
    void GenerateMesh() {
      if (_mesh) {
        DestroyImmediate(_mesh);
      }

      GameObject proxyGameObject = null;
      try {
        var proxy = Instantiate(this, Vector3.zero, Quaternion.identity);
        proxyGameObject = proxy.gameObject;
        proxyGameObject.hideFlags = HideFlags.DontSaveInEditor | HideFlags.DontSaveInBuild;

        _mesh = proxy._collider.CreateMesh(
          useBodyPosition: false,
          useBodyRotation: false
        );
        _mesh.hideFlags = HideFlags.DontSaveInEditor | HideFlags.DontSaveInBuild;
        _meshFilter.mesh = _mesh;
      } finally {
        if (proxyGameObject != null) {
          DestroyImmediate(proxyGameObject);
        }
      }
    }
#

❤️

#

Works a treat

barren moat
#

This stuff gets crazy verbose

normal sage
#

is it possible to create a curve variable?
I input float 0.0 to 1.0, and it gives me another float based on my input? like blender's color curve?

normal sage
gloomy chasm
#

It is just a curve

normal sage
#

ok, tnx

#

is there a way to give dropdowns more options than strings?

#

that's real cool

glad pivot
#

is there an option im missing? i cant make a text field use GUIContent. how would i do the same thing?

waxen sandal
#

It's right there

glad pivot
#

oh i using the wrong one. im using GUILayout not EditorGUI

#

uhm. im not able to select it and write text into it

#

im trying to do this

script.DialogueName = EditorGUI.TextField(
                new Rect(20, 120, 500, 20),  
                new GUIContent("Card", "What Special card triggers this dialogue"), 
                script.DialogueName);

i must be doing something wrong

glad pivot
#

ok, now im getting an error that only says "Unsupported type [class]" when the class is serialized. but i need it to be. what could be the problem?

glad pivot
#

I have this class that is causing it

[System.Serializable]
public class Dialogue
{
    [TextArea(5, 20)]
    public string[] text;
    public string TransformName = "Camera";
    public EventReference SFX;
}

and im using this in scriptable objects to create dialogue instances of whatever i want it to be. then i have a editor script that is going to hide/show extra information deepening on different things. but when the dialogue class is serialized it says its not supported. but in the inspector it works just fine

glad pivot
#

looks like i have accidentally resolved the issue

#

nvm its back

#

apparently i get the error when i change the serialized dialogue

vernal belfry
#

how could I modify the original version of a prefab while in playmode?

#

would i need to keep the path to it ?

#

in order to use
GameObject prefabGO = PrefabUtility.LoadPrefabContents(path);
and
PrefabUtility.SaveAsPrefabAsset(prefabGO, s);

#

or is there any other way ?

#

no i think it isnt

whole steppe
#

Hey, I wanted to load the Default-Material through a Mono Script, but I first need to know where it is located, logically I used the AssetDatabase.GetAssetPath()However, it returns an empty string...
Where is this stuff stored? I couldn't find the path it specifies in the following image:

tough cairn
#

is there a way to reference an image as a sprite collection ?

#

i can reference the whole image as a Texture2D , or a single Sprite when i drag and drop it as a "Sprite" input field

vapid prism
whole steppe
#

oh! cool!

tough cairn
#

ok i figured it out :

if( GUILayout.Button("fetch sprites") )
{
    var path = AssetDatabase.GetAssetPath( target );
    path = path.Substring( 0, path.LastIndexOf( "/" ) );
    var files = System.IO.Directory.GetFiles( path );
    
    var list = new List<Sprite>();
    
    foreach( var file in files ) {
        if( System.IO.Path.GetExtension( file ).ToLower() == ".png" ) {
            //var sprites = AssetDatabase.LoadAllAssetsAtPath( file );
            //var sprites = AssetDatabase.FindAssets( "" , new string[] { file } );
            //var sprites = AssetDatabase.GetSubFolders( file );
            var sprites = AssetDatabase.LoadAllAssetRepresentationsAtPath( file );
            //foreach( var sprite in sprites ) Debug.Log( " - " + sprite.ToString( ) );
            if( sprites.Length < 1 ) continue;
            
            list.Add( ( Sprite ) sprites[ 18 ] ); // 19 th 
        }
    }

    var script = ( SpritesData ) target;
    script.sprites = list.ToArray();
}
#

( script is an editor script for a scriptable object OnInspectorGUI . so it will scan the folder for all the textures and extract the 19's sprites from each one )

dark roost
#

Hello everyone! I'm looking for a way to override how a List<T> is displayed in the inspector with a property drawer, but I'm not entirely sure where to start. T in this case is a class with a custom drawer that works very well. What I'd ultimately like to do is add a header row to the top of the list and significantly reduce the real estate taken up by the index column.

If anyone knows of a good example or resource for how to structure a drawer for List<T>, I'd be super indebted.

gloomy chasm
# dark roost Hello everyone! I'm looking for a way to override how a List<T> is displayed in...

It is super duper not possible. Unity doesn't allow drawers for lists or arrays. You have a number of options though.
Create a custom editor and use ReorderableList to show the list as it allows you set the how each item is drawn.
Another option is in the property drawer for the item class, check it's path if it ends in a ], and if it is you change the drawing to however you want it to draw when shown in a list. However if you have some other custom editor where you want to display them differently in the future or in a different spot, this could lead to unexpected (for you) results.

#

There is another option but it involves creating a base default drawer and using ReorderableList and custom attributes and stuff.

#

Probably more than you want to do as it is more of a full system.

dark roost
#

@gloomy chasm Thanks for the response! I don't currently use a custom editor, but that might be the most appropriate course of action for what I am trying to do.

gloomy chasm
whole steppe
#

true!

dark roost
#

UnityEditorInternal.ReorderableList is the new love of my life. @gloomy chasm

#

Sorry, wife.

gloomy chasm
whole steppe
#

omg! nice work!

#

psst. Mech, hallo!

gloomy chasm
#

Hey-o

whole steppe
#

hey, what did u eat today???

gloomy chasm
whole steppe
#

oh shoot, forgot that was a rule...

dark roost
#

@gloomy chasm That was so incredibly easy.

gloomy chasm
whole steppe
whole steppe
gloomy chasm
#

Is there still no way add a serializedproperty array item with proper default values?

whole steppe
# vapid prism You should be able to use `Resources.GetBuiltinResource` in this case

So here's what happened, I wasn't able to load the Default-Material using Resources.GetBuiltinResource(),
however, I found about yet another undocumented method => AssetDatabase.GetBuiltinExtraResource() which this time does load the Default-Material if the extension is provided in the argument. Thanks for pointing it GetBuiltinResource out in the first place!

oblique sky
#

for Undo.PerformUndo() how does making groups to selectively push/pop from the undo stack work?
I figured you would push specific operations you wanted to undo onto a group, and then PerformUndo would take that group as a parameter, but it has no parameters
is there a way to selectively undo operations?

gloomy chasm
# oblique sky for Undo.PerformUndo() how does making groups to selectively push/pop from the u...

No, it is a stack, PerformUndo just pops the top group/operation off of the stack. If you could undo arbitrary operations you could run in to all sorts of nasty conditions.
Like what if you had a stack like

Set "New Object 2" position
Create GameObject "New Object 2"

Then you undo the creation operation. What happens to the Set Position operation that was above it and needed that object? The object that it affected is gone now

oblique sky
#

thanks

agile badger
#

How would one accurately represent a Capsule Collider 2D's shape using Unity Handles?

agile badger
#

Won't really work for me in this case, since I'm doing some hacky stuff to draw Handles in a RenderTexture inside an editor window

#

I essentially need to do it manually

#

I cannot use any form of the handles API that relies on there being an active camera

short tiger
agile badger
#

How would I determine where the arcs actually start though? And what about the Direction field of the Capsule Collider?

#

I'm writing a collision editor so the visuals need to be as accurate as possible

#

....which is also terrifying because I'll also need to (manually) work out if the mouse cursor is inside the capsule

short tiger
#

First thing is to calculate are the two points of this red line. To do that, you need to know which direction is "up" or "down", which depends on the direction of the capsule collider.

gloomy chasm
agile badger
#

Visual diagrams aren't really useful for me 😛

short tiger
agile badger
#

So given an offset (center point of the collider relative to mesh origin point) and extents...

#

would the vertical extent be the length of the two vertical lines?

#

Given that the extents are essentially half the size of the collider

short tiger
#

Where are you getting "extents"? That's not in CapsuleCollider2D, except through bounds.

agile badger
#

It's what my current (very broken) capsule collider representation inside the collision editor uses to determine the size of the collider

short tiger
#

Oh, CapsuleCollider2D is weird. It doesn't even expose a radius because it's automatically calculated from a size property. Very weird, very different from 3D.

agile badger
#

The offset represents the center point of the collider. The extents are used to calculate the bounds of the collider.

short tiger
#

So there is no CapsuleCollider2D? You have your own 2D capsule representation?

agile badger
#

Yeah. The actual Unity colliders are created at runtime by the game

#

Based on data stored in an immutable struct

#

What I'm writing is the tool that lets you edit that source data.

#

Box, circle, and polygon colliders are done. The only remaining piece of the puzzle is the capsule collider

#

The only reason this tool uses its own editor window rather than the Scene View is that the game in question is a 2.5D platformer, and it's very annoying to center the Scene View camera onto the object whose collisions we're trying to edit such that they can be viewed in 3D - plus many other usability issues that my tool aims to fix

short tiger
#

Do you have a preference for how you want to represent the capsule in the source data? I definitely prefer height + radius + direction, but Unity's CapsuleCollider2D uses size + direction. Ultimately you'll have to calculate height and radius to draw the handle.

#

But you'll also have to convert it to size + direction to assign it to CapsuleCollider2D

agile badger
#

Ideally, the immutable data should directly map to what Unity expects

#

My only conditions are that the editor can accurately represent (visually) how the collisions will work in-game, otherwise that's a headache

#

And that I can easily determine that a given Vector2 is inside the collider

#

I don't want to do a simple bounding box check for that second task, because I don't want two colliders right next to each other fighting for mouse selection

short tiger
#

Capsule collision detection is pretty easy, less code than box collision.

#

Circle is easiest, then capsule, then box. Because a capsule is just a line segment with a radius, so you just need to calculate the distance between the point and the line and subtract the radius.

#

@agile badger Do your capsules have rotation? Is that also saved in the immutable data?

agile badger
#

It could if that's something that'd be useful

#

tbh I haven't gotten as far as getting the data to actually save into an asset, because I want to make sure the editor itself works first

short tiger
#

So you're indifferent about whether these capsules in your game will be allowed to have rotation or not?

agile badger
#

Yeah

#

Might be good to add support for it though in case down the line an artist says it'd be useful but it's not there

short tiger
#

You mentioned 2.5D, but these capsules are purely 2D, right? I'm just wondering if this rotation would just be a float or a full Quaternion

agile badger
#

Yes. All physics in the game is purely 2D. The 2.5D comes from the fact that, visually, the game is rendered in 3D, and there are 11 2D physics layers in the game (5 thick and 6 thin)

#

Think like LittleBigPlanet

#

....I have to be very careful about how much detail I actually give because I'm under NDA but

#

I trust the official Unity discord lol

short tiger
#

I'm still figuring out how to convert the size to a height and radius, but getting there

agile badger
#

It's definitely frustrating because Handles rely on SceneView for a lot of situations but like

#

Surely there are uses for them outside of the Scene View

short tiger
#

@agile badger Here's the function required to convert data matching that from a CapsuleCollider2D to the line points:

public static void CalculateCapsuleLine(Vector2 position, float rotation, CapsuleDirection2D direction,
        Vector2 size, out Vector2 start,
        out Vector2 end, out float radius, out float height, out Vector2 worldDirection)
    {
        Vector2 localDirection;

        if (direction == CapsuleDirection2D.Vertical)
        {
            localDirection = Vector2.up;
            radius = size.x * 0.5f;
            height = Mathf.Max(0, size.y - size.x);
        }
        else
        {
            localDirection = Vector2.right;
            radius = size.y * 0.5f;
            height = Mathf.Max(0, size.x - size.y);
        }

        worldDirection = Quaternion.AngleAxis(rotation, Vector3.forward) * localDirection;

        var halfDirection = worldDirection * (height * 0.5f);

        start = position - halfDirection;
        end = position + halfDirection;
    }
#

And here's how that function is used to draw the handles:

CalculateCapsuleLine(capsule.Position, capsule.Rotation, capsule.Direction, capsule.Size, out var start,
    out var end, out var radius, out var height, out var direction);

var cross = Vector2.Perpendicular(direction);
var halfCross = cross * radius;

// Draw the lines on the side.
Handles.DrawLine(start + halfCross, end + halfCross);
Handles.DrawLine(start - halfCross, end - halfCross);

// Draw the arcs on the top and bottom.
Handles.DrawWireArc(start, Vector3.forward, cross, 180, radius);
Handles.DrawWireArc(end, Vector3.forward, -cross, 180, radius);
short tiger
#

I thought DrawLine and DrawWireArc would work under this circumstance. I don't think they depend on the active scene camera.

agile badger
#

They'll work

#

I'ma shamelessly steal and adapt this code now 😛

short tiger
#

The documentation says it will fit the capsule inside the size specified, but that's a lie. When in Vertical direction, if size.x is greater than size.y, it will still increase the radius to fit the width and let the capsule grow bigger than the box defined by size.

#

But fortunately, that means it's easier for us to calculate the radius, because it's always half of size.x. Or half of size.y if in Horizontal direction.

agile badger
#

Yayyyyy! Rendering is working

#

Now onto mouse hover detection

#

Oh god

#

Luckily once mouse hover detection is done, the rest is handled automatically

#

No idea how this'll work with rotation

#

@short tiger I'm horrifyingly bad at math so I have no idea where to begin with doing mouse detection using the values calculated by your code

short tiger
# agile badger <@153952447516114944> I'm horrifyingly bad at math so I have no idea where to be...

This is the math for calculating the distance between a point and a line segment. It's adapted from some other source and I don't understand the math either, but I believe part of it is projecting the point onto the line.

private static float CapsuleDistance(Vector2 pos, Vector2 startPos, Vector2 endPos)
{
    var ps = pos - startPos;
    var es = endPos - startPos;
    var h = Mathf.Clamp01(Vector2.Dot(ps, es) / Vector2.Dot(es, es));
    var diff = ps - es * h;

    return diff.magnitude;
}
#

Subtract this distance with the radius and if it ends up negative, pos is inside the capsule.

#

But like I said, more complicated than a circle check, but less complicated than a box check. No branches.

agile badger
#

You're freakin' awesome

#

Wish I had ya on the Restitched team right about now

#

@short tiger radius - dist or dist - radius? Because my first attempt ended up detecting the mouse as hovering over the capsule when the cursor is outside of it

#

Which is the opposite of what I intended lol

#

But like, if the mouse is actually inside the capsule it thinks it's not hovering over it, so maybe I can flip the condition round to check for positive

short tiger
#

dist - radius

agile badger
#

ah I did radius - dist

#

Annnnd now it's working perfectly!

#

Set up handles for adjusting the position and size of the capsule and it is done!

#

Thank you so much for the help, I really appreciate it!

agile badger
#

Wait, something seems busted

#

If the collider is set to Vertical, and the width is greater than the height, the mouse detection breaks.

#

Haven't tested with Horizontal + y greater than x, but I'd assume the same thing would happen

#

Yep, it does

#

@short tiger After some debugging, CapsuleDistance returns float.NaN in this two scenarios... hmmm... Might have to fall back to a circle check in that case maybe

#

Yep, that did it!

eternal girder
#

I'm really struggling with getting my prefab dragging tool to work. I transition from an editor window to a tool when a component is hovered and LMB is down, and when LMB is depressed, it either drops the instantiated prefab down where the mouse is or doesn't, depending on whether the mouse is over the sceneview or not. But, for some reason my tool doesn't register the first mouseUp (I need to click on the sceneview again for it to work) and none at all if I depress it over another window

#

how do I go about properly receiving the input?

#

oh it'll be hotcontrol wouldn't it

#

second question, how do I change hotcontrol to access mouseUp triggers?

eternal girder
#

I've given up 😦 I can't get it to work

#

Now I'm just looking for EventType.MouseEnteredWindow as a hacky work around

narrow pewter
#

anyone have reliable source of tutorial on how to create custom Editor GUI?

visual island
narrow pewter
#

okay, how can i keep my object referenced after pressing play, currently is just revert back to null when press play

visual island
#

Referenced where?

narrow pewter
#

before Play

#

after play

visual island
#

I mean, where in the code?

narrow pewter
visual island
#

And SpawningObjectGScpt?@narrow pewter

narrow pewter
#
public GameObject vGameObjectToSpawn;
public Vector3 vSpawnPosition;
#

only this

visual island
#

And what's Foo gameobject? Is it in the scene?

narrow pewter
#

just blank game object and yes it's in the scene

visual island
#

Is it getting destroyed on Play?

narrow pewter
#

no

visual island
#

Are you sure?

narrow pewter
#

100%

visual island
#

Okay. Try refactoring vGameObjectToSpawn into a property and adding a debug message in the setter outputting the new value.

gloomy chasm
# narrow pewter https://gdl.space/iyusukeqiz.cs

This is super common. (You would get a ton of results if you googled that your custom editor is not saving)
You need to set the target object to dirty. However the better option is to use SerializedProperty and SerializedObject to set data on an object in the editor.

visual island
#

Oh, that makes sense.

narrow pewter
#

and engrisk is hard men

#

oh

#

"custom editor is not saving"

gloomy chasm
narrow pewter
#

doing same rn

wary jungle
#
Handles.CubeCap(1, pos, Quaternion.identity, t.tileSize);

Example of the line getting the error.

severe lance
#

Does ordering matter for where you draw your EditorGUILayout.PropertyField in OnInspectorGUI() when checking serializedObject.hasModifiedProperties ?

#

Such that I can check if each property field has been modified in one update.

#

Otherwise, how would I go about checking if a cluster of property fields have been modified independently to other clusters.

wary jungle
whole steppe
#

My brain can't take this anymore! please help => https://paste.mod.gg/nofpkuhkejbi/0
It always requires double click to run the EditorUtility.CopySerializedIfDifferent() method...
I'm clearly doing something obviously wrong, I'm just blind!!

whole steppe
#

@severe lance have you tried hasMultipleDifferentValues?

severe lance
#

This stuff is turning out to be a bigger pain then it should

whole steppe
#

fak pain!

severe lance
#

I'm just trying to figure out if drawing the property fields have some ordering to it, because there's a mix of logic and gui element drawing you have to consider

whole steppe
tough cairn
#

how do i get object value from SerializedProperty ?

#

object obj = property.serializedObject.targetObject;

System.Func<float, float> func = null;

if( obj != null )
{
    var funcObj = obj.GetType().GetProperty("function" , BindingFlags.Public | BindingFlags.NonPublic ).GetValue( obj );
    
    func = (System.Func<float, float>) funcObj;
}
#

getting a NullReferenceException: Object reference not set to an instance of an object ( at the " funcObj " line )

#

this is how my class looks :

[System.Serializable] public class Temp { public System.Func<float, float> function = null; }
#

the property is passed inside the OnGUI for a custom property drawer

#

also tried this but its impossible to serialize System.Func<T1,T2> , this methods logs that func prop is null :

System.Func<float, float> func = null;

var func_prop = property.FindPropertyRelative("function");
if (func_prop != null)
{
    var func_val = func_prop.objectReferenceValue;
    if (func_val != null)
    {
        var func_object = (object)func_val;
        if (func_object != null) func = (System.Func<float, float>)func_object;
        else Debug.Log("func object null");
    }
    else Debug.Log("func val null");
}
else Debug.Log("func prop null");
#

ah.... so serializedObject.targetObject is the container class of the Temp class ... now i need a way to find the property name seting

#

string *

tough cairn
#

solved :

System.Func<float, float> func = null;

object obj = property.serializedObject.targetObject;

if (obj != null)
{
    var obj_val = obj.GetType().GetField( property.name, Flags ).GetValue( obj );
    var func_val = obj_val.GetType().GetField( "function" , Flags ).GetValue( obj_val );
    func = (System.Func<float, float>) func_val;
}
#
value.function = func;
...
private float func( float x ) {
    float k = 2.55015f , e = 2.71828f , m = frequency , u = damping, d = 1f - k;
    var e_pow = d + ( k - x - d ) * ( m * 1.1f );
    var f1 = Mathf.Pow( ( 1f - x ) , u ) / 2f;
    return f1 * Mathf.Sin( Mathf.Pow( e , e_pow ) ) + f1;
}
thorn raptor
#

Anyone know why my scriptableobjects keep throwing errors when I change like anything? Specifically, changing the name of the object or any of the code completely break them beyond repair and they throw "object not set to an instance of an object" errors when I try to inspect them. It's really frustrating cos writing them into some sorta document and copying it all in later is a huge pain but I can't write directly into the scriptable objects if they're going to keep breaking like this.

#

I changed it's name, an parameter broke, and now the entire thing has stopped appearing. Changing the name back does nothing. I check the file in a text editor and all the data is still there, but for soem reason it's just not appearing anymore

#

the issue might be with the custom inspector I have but I have literally no clue how changing the file's name could possibly factor into my own logic

#

Is there a specific problem with having an array of lists?

#

do those not serialize properly or something

#

oh TIL Lists can't be serialised properly ig

#

my bad lmao

#

this makes writing this code a lot more of a pain then Sadge

gloomy chasm
gloomy chasm
tough cairn
tough cairn
#

wew thanks , might extend it next time [ bookmark 🔖 ]

#

which method from there would i use in my case ?

#

based on this code snippet [#↕️┃editor-extensions message]
im guessing this one ?

System.Func<float, float> func = SerializedPropertyValueExtensions.GetValue<Temp>( serializedProperty ).func
gloomy chasm
thorn raptor
tough cairn
#

i really like keeping things as modular as possible ( this snipped was added in the end of the file scoped inside my main class )

gloomy chasm
gloomy chasm
tough cairn
#

much appreciated

thorn raptor
#

unfortunately its still not working, i'll get back to you with the problem if I manage to find the time any time soon

gloomy chasm
thorn raptor
#

oh i misread

#

I thought you were saying that jagged arrays work but 2d and 3d dont

#

uh oh idk how to do what I want to do then

#

ill have to rework the system

#

just create a new class that contains the information I need and have a single array of that ig

gloomy chasm
vapid prism
#

For property drawers, can I set a bool in OnGUI and expect it to be ready to use in GetPropertyHeight? Assuming I override CanCache to false

waxen sandal
#

No

visual stag
#

No? It needs the height to give it to OnGUI, it works the opposite way around

waxen sandal
#

Also, GetPropertyHeight is called before

vapid prism
#

Oh I missed that I get the SerializedPropety as part of GetPropertyHeight, I can just run my logic in that method and it'll be fine. Thanks! 🙂

iron mica
#

Does anyone know how to create preferences like this...

waxen sandal
iron mica
#

Thank you So Much @waxen sandal

small sequoia
#

Hey, I added an "Attach" button to the SkinnedMeshRenderer, but the base.OnInspectorGUI draws a different UI from the base look.
Why? What did I miss?

small sequoia
whole steppe
#

Is there a method that gets called when creating an AnimatorStateTransition?
There's a preset that I'd like to apply to each newly created transition...
I wasn't able to set the preset as the default one in the preset manager.

whole steppe
#

How to disable the (VRCAvatarDescriptor) leftover?
I'd like it to disappear when provided with an object just like the other ObjectField does, also, it possible to replace/set an icon for that specific field?

shadow violet
#

Is it possible to create an editor to read a base type of a scriptable object class? For example, I have a class like this:

public class SOBase : ScriptableObject {}
public class PlayerStats : SOBase {}
public class WeaponStats : SOBase {}

Using a custom editor (which should change the inspector when selecting those assets):

[CustomEditor(typeof(SOBase))]
public class SOEditor : Editor
{
public void OnInspectorUpdate() { }
}

Seems to not recognize I have a "SOBase" selected when selecting a "PlayerStats" asset for example (even if I just use ScriptableObject as the type and not use inheritance) - my guess is I have to make it a typeof(PlayerStats) instead, but a custom editor for every single scriptable object seems like a inefficient way to solve this problem, is there no way to have a custom editor for "SOBase" that can recognize any ScriptableObject? Is it better to make a custom editor window that scans every asset in the project with reflection for a base type of "SOBase"? Are there better ways? Ultimately I would like to get a label and a button to show up when selecting "player stats" or "weapon stats" etc

waxen sandal
#

Second parameter of CustomEditorAttribute allows you to use it for derived classes

shadow violet
#

Oh really? Interesting, Ill have to look into that and try again - thanks

#

I did not know this was a thing - that actually seems to solve the problem for my use-case, thanks again :)

glad pivot
brazen tiger
#

i am trying to write a script which will take sprites in a folder and assign it to scriptable object. Just to reduce drag and dropping while making prototypes. The problem is that Getfiles() is returning files as strings. how can I get a sprite file as a sprite from folder? This is my code so far

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

#if UNITY_EDITOR
using UnityEditor;
#endif

public class FileAssigner : MonoBehaviour
{
    public Sprite test;
 
    public void Assign()
    {
        Debug.Log("Function Called");
        foreach (var file in System.IO.Directory.GetFiles("D:\\X\\Y\\Assets\\Helpers")) 
        {
            
            Debug.Log(file.GetType());
        }
    }
}

#if UNITY_EDITOR
[CustomEditor(typeof(FileAssigner))]
public class FileAssignerEditor:Editor
{
    public override void OnInspectorGUI()
    {
        FileAssigner script = (FileAssigner)target;
        base.OnInspectorGUI();
        if (GUILayout.Button("Assign Config"))
        {
            script.Assign();
        }
    }
}
#endif ```
patent venture
#

probably something like (correct me if i'm wrong): ```cs
Sprite sprite = AssetDatabase.LoadAssetAtPath(file, typeof(Sprite)) as Sprite;

short tiger
#

Is there a method for simulating clicking a menu item, one that has been defined with the [MenuItem] attribute?

#

Ah, found it. EditorApplication.ExecuteMenuItem

honest python
#

How would I possibly go around creating a new instance of generic class within custom property drawer?
E.g. how "+" button in List inspector calls (I assume) .Add(newItem), where it first creates newItem based on the generic type of the list.

Specifically, I have a [Serializable] class FixedList<TK, TV> where TK : struct, Enum, which has a fixed number of TK[] _keys and TV[] _values.

For it, I have a custom property drawer that lists the properties. For value types, this works without issues.

For reference types however, I'm not getting anything to show up, just empty space. I'd assume this is because they are null (and that's alright, no constraints on them being non-null).

So I wanted to make a button in place of nulls that would create an instance of TV, but I'm not sure how to accomplish that. Specifically:

  • how to get type of SerializedProperty, of which objectReferenceValue is null
  • how to use the received type to create new() instance of that class
native geode
#

I would say this goes here

#

I have this setup

#

and tried to make custom editor

#

How would I make switch from that enum?

#

can i cast serialized property?

#

I understand I could make Property of field that has public getter and do it that way with target

#

but seems clunky and heard serializedproperty is "right way"

waxen sandal
#

cast the intValue to the enum type

#

just because it's the right way doesn't mean it's not clunky 😛

native geode
#

was searching all things related to enum that intellisense offers

#

this works

#

this displays it properly

waxen sandal
#

Oh, didn't know they added that

native geode
#

does custom editor script must be in Editor folder?

#

this is not in editor folder and works

short tiger
#

You'll get a compile error when you build because it will attempt to include it in the build. Anything in an Editor folder is not included in a build.

native geode
#

got it

native geode
#

and it wont cause errors in build?

short tiger
native geode
#

yeah that seems neater

native birch
#

This might not be the right channel, however i think this channel is most appropriate for this question. I am having problems with running unity on the unity remote 5 app on my iphone 11. The phone is set as "device" in the project settings -> editor. But when i click play it doesnt do anything on my irl phone. Need help

whole steppe
#

Hey, I'd like to exclude an element from an EditorGUILayout.EnumPopup(),
The enum holds an element that's unwanted, and I don't have control over the source code...
How can this be done?

waxen sandal
#

Don't use enum popup but the normal popup that takes strings instead

whole steppe
#

Yea, I just did that! Looks neater too!

nova onyx
#

Would anyone know why a toggle in an editor would be immediately resetting itself to it's original value?

alpine bolt
nova onyx
#

Alright, thank you!

whole steppe
waxen sandal
#

🤦‍♂️

whole steppe
#

I already have one issue though lol, that I will ask fully with code tomorrow

#

But my bool doesn’t get reset I think, I’ll need to debug when I get back

hoary sparrow
#

got a custom struct that looks kinda ugly, it would be really nice if i could show or hide vert0 to vert7 using a little arrow or something, but cant seem to find anything on google, wondering if someone could point me in the right direction?

waxen sandal
#

PropertyDrawer + serializedProperty.isExpanded + editorgui.expander

hoary sparrow
#

thanks for the info!

hoary sparrow
waxen sandal
hoary sparrow
#

thank you!

hoary sparrow
#

thank you!

hoary sparrow
visual stag
#

You mean NativeArray?

hoary sparrow
#

ah yes, sorry for being vague lol

visual stag
#

The serialization system doesn't care about structs v classes

hoary sparrow
#

i dont really know what that means im afraid

#

i just want to be able to have a little arrow that hides and shows some stuff, while still being able to use it in a native array, is this possible?

visual stag
#

The resources already linked are relevant.

hoary sparrow
#

i know, im just not clever im afraid, and i dont know how to get whatever they did to work on a struct instead of a class...

visual stag
hoary sparrow
#

oh, im an idiot, i forgot structs can use : to do stuff, sorry lol, thanks so much!

whole steppe
#

Is there a way to retrieve the active AnimatorController in the Animator window?

whole steppe
sage sedge
#

to get the controller in the animator its myAnimator.RuntimeAnimatorController

#

if thats not what you want, i do not understand your question

whole steppe
sage sedge
#

I'm not sure the animator window has a controller

#

it is the controller

#

hold on, i understand now

whole steppe
#

you talking about this window? because I am

sage sedge
#

Yes

whole steppe
#

yus! what now? I don't have a reference to the controller registered anywhere in the script, how do I get that controller, the one that's active in this window?
do you happen to know?

sage sedge
#

I have been looking on google however i cant see how, initially i thought this was beginner code so this is where my confusion came from 😅

whole steppe
#

I don't blame you, I'm a beginner 🥹

whole steppe
#

Bingo!```cs
// from => https://gist.github.com/forestrf/29c391c7cae0202ea18392b03bb70ac1
private AnimatorController GetCurrentActiveController()
{
Type animatorWindowType = Type.GetType("UnityEditor.Graphs.AnimatorControllerTool, UnityEditor.Graphs");

EditorWindow window = GetWindow(animatorWindowType);

FieldInfo controllerField = animatorWindowType.GetField("m_AnimatorController", BindingFlags.Instance | BindingFlags.NonPublic);

return controllerField.GetValue(window) as AnimatorController;

}```I love reflection!
One day I'll marry it 🥹

real spindle
#

Is there a way to start an EditorCoroutine immediately?
I made this method that starts a coroutine the correct way according to isPlaying and if it's in editor or built game.
The EditorCoroutine is started the next frame though, instead of immediately like when using StartCoroutine. Is there a way to make them behave the same?

    protected void StartCoroutineGeneric(IEnumerator routine)
    {
#if UNITY_EDITOR
        if (!Application.isPlaying)
        {  
            // Not playing, use EditorCoroutine. 
            // Here the coroutine's logs run after the "Pre" and "Post" logs (this is the issue).
            Debug.Log("Pre start EditorCoroutine");
            EditorCoroutineUtility.StartCoroutine(routine, this);
            Debug.Log("Post start EditorCoroutine");
        }
        else
        {
            // In play mode, use normal Coroutine.
            // Here the coroutine's logs run between the "Pre" and "Post" logs, like expected.
            Debug.Log("Pre start Coroutine");
            StartCoroutine(routine);
            Debug.Log("Post start Coroutine");
        }
#endif
#if !UNITY_EDITOR
        StartCoroutine(routine);
#endif
    }
shadow minnow
#

I have experience with programming, but very limited experience writing editor scripts; I have a grid component in my scene that i parent rooms to, and i need it to be visible at all times in editor, and drawn with a specific color. Is there a way i can modify or interface with the gizmo of an existing component?

#

Is this possible to do? Or will i just need to write my own code for drawing this grid

dark roost
#

I'm trying to create a ScrollView inside an EditorWindow with an explicitly-sized interior content area. Consider the following code:

    {
        _scrollPosition = EditorGUILayout.BeginScrollView(_scrollPosition, true, true);
        EditorGUI.DrawPreviewTexture(new Rect(0, 0, _map.backgroundImage.width, _map.backgroundImage.height), _map.backgroundImage);
        EditorGUILayout.EndScrollView();
    }```
Lets say that I wanted the interior part of the scrollview to be 5000 pixels wide, how would I go about setting this up?  The PreviewTexture in this example doesn't expand the edges of the content area at all.  Thanks in advance!
dark roost
#
    {
        using (var scrollView = new EditorGUILayout.ScrollViewScope(_scrollPosition, true, true, GUILayout.Width(Screen.width), GUILayout.Height(Screen.height - 42))) {
            
            _scrollPosition = scrollView.scrollPosition;

            using (var area = new GUILayout.AreaScope(new Rect(0, 0, 5000, 5000), new GUIContent(), new GUIStyle() { fixedWidth = 5000 }))
            {
                EditorGUI.DrawPreviewTexture(new Rect(0, 0, _map.backgroundImage.width * 2, _map.backgroundImage.height * 2), _map.backgroundImage);
            }
        }
    }```
Here's an alternate script which *did not work* - I hope this gives some context into what I'm trying to do.
dark roost
#

Cat climbing on keyboard.

gloomy chasm
dark roost
#

Does GetRect() draw something or does it just return a Rect struct?

gloomy chasm
#
private void DrawMapArea()
    {
        _scrollPosition = EditorGUILayout.BeginScrollView(_scrollPosition, true, true);
      Rect rect = GUILayoutUtility.GetRect(5000, 100);
        EditorGUI.DrawPreviewTexture(new Rect(rect.x, rect.y, _map.backgroundImage.width, _map.backgroundImage.height), _map.backgroundImage);

        EditorGUILayout.EndScrollView();
    }
dark roost
#

If you don't mind my asking, how is that superior to EditorGUI.DrawPreviewTexture(new Rect(0, 0, 5000, _map.backgroundImage.height), _map.backgroundImage); ?

#

In this example, the x/y offsets are known and not important for example's sake. I can see the benefit to GetRect there.

gloomy chasm
#

Because by using GetRect it will tell the layout system something is there so you won't have controls overlapping, and you can have a scrollview content container be the size you want while still drawing with a EditorGUI/GUI method

dark roost
#

So, you're saying that GetRect() reserves those bounds in the background in addition to returning a Rect...

gloomy chasm
#

Yup, just like the docs show and say 🙂

dark roost
#

Reserve layout space
I see!

#

This is a good answer and clears up the behaviour for me very nicely... thanks for that! In the 50 minutes before, I scrapped my UI in favour of a UI Builder solution, which actually is turning out to be the better tool anyway because this thing that I'm trying to build has loads of overlapping components and it's much easier to design.

gloomy chasm
#

Oh, yeah UIToolkit is great!

dark roost
#

Now I have to figure out why my URP shaders are rendering as solid blue in the editorwindow only.... 😄

gloomy chasm
#

That is something you configure in your IDE and not for this channel

dark roost
#

Are you looking for a method written to do that? As in a player types code in your game?

#

Visual Studio? What IDE?

gloomy chasm
gloomy chasm
dark roost
hoary sparrow
#

i have an array in the inspector, that when i press a button i want to have it be 1 longer, unfortunately WhateverArray.Length is read only, is there a workaround?

waxen sandal
#

SerializedProperty.arraySize isn't read only

hoary sparrow
#

ooh fascinating, haven't heard of that, thanks for the info!

hoary sparrow
#

ok from reading a little into these serialized properties there is one question i have: Do i have to manually create the serialized objects, or do gameobjects automatically create one for themselves that i can then grab?

waxen sandal
#

CustomEditor or propertydrawer?

hoary sparrow
#

currently im using a CustomEditor

waxen sandal
#

editors have a serializedObject field (thatyou can use to find the right property)

#

propertydrawers get the serializedproperty passed as parameter

hoary sparrow
#

ok fascinating, ill start hunting then, thanks!

hoary sparrow
waxen sandal
#

What are you doing

hoary sparrow
# waxen sandal What are you doing

trying to make an array longer, this is my code for the custom editor:```cs
#if UNITY_EDITOR
[CustomEditor(typeof(IsoSurfaceExtractor))]
public class IsoSurfaceExtractorEditor : Editor
{
public void OnSceneGUI()
{
//Debug.Log("somethingworking?");
var LO = target as IsoSurfaceExtractor;

    Handles.color = Color.blue;
    for(int i = 0; i < LO.Cells.Length; i++)
    {
        LO.Cells[i].Pos = Handles.PositionHandle(LO.Cells[i].Pos, quaternion.identity);
        var test = Handles.Button(LO.Cells[i].Pos, quaternion.identity, LO.HandleSize, LO.HandleSize * 2, Handles.RectangleHandleCap);
        
        if (test)
        {
            Debug.Log("buttonpressed");
            SerializedProperty SCells = serializedObject.FindProperty("Cells");
            SCells.arraySize++;
            SCells.InsertArrayElementAtIndex(i + 1);
            LO.Cells[i + 1] = LO.Cells[i];
        }
    }
    //LinkedObject.Size = Handles.ScaleHandle(LinkedObject.Size, LinkedObject.transform.position, LinkedObject.transform.rotation, HandleUtility.GetHandleSize(LinkedObject.transform.position) * 1.5f);
}

}
#endif

waxen sandal
#

Don't do i + 1

hoary sparrow
#

ah, i shall try that, do i still need the i+1 on the next line though, or can i also make that just i?

waxen sandal
#

Yeah you do

hoary sparrow
#

ok thanks!

#

hmm now it is giving me index out of ranges for the "LO.Cells[i+1] = LO.Cells[i];" line, hmm

waxen sandal
#

Oh yeah if you're accessing target like that it will fail

#

Use SCells.GetArrayElementAtIndex(i)

#

You cna't really mix and match them wherever

hoary sparrow
#

ah ok thanks!

waxen sandal
#

for(int i = 0; i < LO.Cells.Length; i++)
Also here use SCells.arraySize

hoary sparrow
#

ah ok thanks!

waxen sandal
#

And also when you access the pos and everything else

hoary sparrow
#

ah i see

hoary sparrow
waxen sandal
#

The same as other serializedproperties

hoary sparrow
#

thanks a ton!

hoary sparrow
hoary sparrow
#

so far ive managed to get my code to look like this:```cs
#if UNITY_EDITOR
[CustomEditor(typeof(IsoSurfaceExtractor))]
public class IsoSurfaceExtractorEditor : Editor
{
public void OnSceneGUI()
{
//Debug.Log("somethingworking?");
var LO = target as IsoSurfaceExtractor;
SerializedProperty SCells = serializedObject.FindProperty("Cells");

    Handles.color = Color.blue;

    for(int i = 0; i < SCells.arraySize; i++)
    {
        SCells.GetArrayElementAtIndex(i).vector3Value = Handles.PositionHandle(SCells.GetArrayElementAtIndex(i).vector3Value, quaternion.identity);
        var test = Handles.Button(SCells.GetArrayElementAtIndex(i).vector3Value, quaternion.identity, LO.HandleSize, LO.HandleSize * 2, Handles.RectangleHandleCap);
        
        if (test)
        {
            Debug.Log("buttonpressed");
            
            SCells.arraySize++;
            SCells.InsertArrayElementAtIndex(i);
            SCells.GetArrayElementAtIndex(i+1) = SCells.GetArrayElementAtIndex(i);
        }
    }
}

}
#endif

waxen sandal
#

SCells.GetArrayElementAtIndex(i + 1).vector3Value = SCells.GetArrayElementAtIndex(i).vector3Value;

hoary sparrow
#

hmm, keep getting spammed with this error

waxen sandal
#

Then the type is not vector3

#

But rather something else

hoary sparrow
#

yes, it is a struct, with a vector3 inside it, sorry for not specifying earlier

waxen sandal
#

So you still gotta do findPropertyRelative("FILL IN FIELD NAME").vector3Value

hoary sparrow
#

ok, so you can find properties within properties?

waxen sandal
#

Yes

hoary sparrow
#

ok thanks a ton!

#

aha turns out im stupid, and forgot that im actually using a float3 instead of a vector3, is there some sort of .float3Value?

waxen sandal
#

What's a float3

hoary sparrow
waxen sandal
#

No idea what is in unity.mathematics but chances are you have to find each field manually

#

Aka, find x,y,z using FindPropertyRelative

hoary sparrow
#

ah i shall try that, thanks

hoary sparrow
# waxen sandal Aka, find x,y,z using FindPropertyRelative

ok using what i know about FindPropertyRelative, i tried this:

float3 CurrentPos = new float3(SCells.GetArrayElementAtIndex(i).FindPropertyRelative("x").floatValue, SCells.GetArrayElementAtIndex(i).FindPropertyRelative("y").floatValue, SCells.GetArrayElementAtIndex(i).FindPropertyRelative("z").floatValue);
``` although this does not work, as such im wondering, if you were going to do this to a vector3 how would you do it? (considering how Vector3 is identical in memory to float3, getting xyz should be the same, or very similar)
waxen sandal
#

Is your structure:
struct something { float3 val; }

hoary sparrow
#

yes essentially, it has a few other things inside it, but they aren't too relevant currently i think

waxen sandal
#

SCells.GetArrayElementAtIndex(i)
Gets the struct in your list
.FindPropertyRelative("val")
Gets the float3 field
.FindPropertyRelative("x")
Gets the x field inside the float3

#

SCells.GetArrayElementAtIndex(i).FindPropertyRelative("val").FindPropertyRelative("x")

hoary sparrow
#

ah i see, thanks a ton!

#

ok yas, there are now no errors! The button doesn't actually add anything to the array for some reason though lol

waxen sandal
#

You probably need serializedProperty.Apply

hoary sparrow
#

ah thanks!

obsidian quest
#

Hey guys. I am trying to center a gizmo Handle.Label. I checked google and found some things but I am not satisfied with the result

#

I want to center the text over the object

#

This is my code and I thought the highlighted line would center it but I assume it doesn't do it properly since it doesn't know at that point how long the text is yet?

waxen sandal
#

you can use style.calcwidth to figure out the width (hopefully)

obsidian quest
#

I saw a GUIStyle.CalcMinMaxWidth in the Docs but ... I have no clue what to do with that information or where to add it 🙈

#

I am not a real coder and this is my first time working with gizmos to make my scene more readable :x

waxen sandal
#

So just do left align, set the width to the x of the output

#

And then offset the x coordinate by width/2

obsidian quest
#

the problem wasn't to ge the size of the box. I wasn't sure how to apply that size "GUIStyle.contentOffset" is a thing

#

Now it works

#

Thank you @waxen sandal ❤️

waxen sandal
#

Nice

obsidian quest
#

I still don't think it is 100% perfectly centered but at least it doesn't trigger my inner monk as much anymore

waxen sandal
#

I think it might look slightly off because your sphere is not perfectly spehrical

dark roost
#

Hello! I'm using a custom EditorWindow to edit a Map object which I am initializing as follows:

{
    MapEditorWindow window = GetWindow<MapEditorWindow>("Map Editor");
    window._map = map;
}```

```public void CreateGUI()
{
    // this._map is 'null' inside the object instance
}```
`Open(Map map)` opens the window and `map` is always something non-null here.  However, `_map` is usually null when `CreateGUI()` gets invoked.  Map extends ScriptableObject.  Is there some other way that I am supposed to be referencing my asset in the custom EditorWindow?
waxen sandal
#

You create your GUI in Open instead of CreateGUI

dark roost
waxen sandal
#

Setting up the initial gui

#

You can also create all your UI elements there, and only set values later

#

I don't remember if you can bind things before hand already but probably

#

Maybe you can createinstance the editorwindow and call show later nad it might work like you want it to

dark roost
#

@waxen sandal So, CreateGUI() would be better used if I am populating the GUI via script, you say? If I understand correctly, I really only need to set my root element there then, since I'm using UI Builder for pretty much everything. Does that sound right?

waxen sandal
#

Oh no idea how UI builder works tbh

#

Sounds fine to do that in Open though

limpid mirage
#

Property Attribute - Calling a method when a color field is changed

#

I wrote content in here

#

and discord failed to place it in the thread

#

so I'm rewriting that all now

#

I didn't just post an empty thread...

dark roost
dark roost
#

@waxen sandal Final implementation:

    {
        MapEditorWindow window = GetWindow<MapEditorWindow>("Map Editor");
        window._map = map;
        window.titleContent = new GUIContent(text: "Map Editor");
        window._mapBackgroundTex = map.backgroundImage;

        Debug.Log(map.name);

        window._initialized = window.Initialize();
    }

    private bool Initialize()
    {
        rootVisualElement.Clear();
        _tree.CloneTree(rootVisualElement);
        
        // All other GUI setup goes here
    }```

This is absolutely not what the docs that I found show to do, but it's very responsive now.  Thank you!
glad pivot
#

I have a scriptableObject as a config with settings and etc on it. and one of the settings are a file path. in the scriptableObject it is just
[HideInInspector] public string _Path = "Assets/_ScriptableObjects/";
then i have an editor script for it that draws it because i want it to be drawn after some other elements in the inspector im doing in the editor script.

script._BootScenePath = EditorGUILayout.TextField(script._Path);

the problem is that every time i close the project and open it again _Path is set back to its default value. how can i avoid it being set back to default?

glad pivot
glad pivot
#

wait, now it works. i dont think i did anything shruggie

native geode
#

i have health bar script and its custom editor

#

iam trying to spawn prefab of it in unity editor but iam unable to find and good tutorial

#

so far i managed to find this but it doesnt work really

#

problem is iam not reall sure what iam searching, i tried "spawn prefab in editor" but iam stuck, so if somebody has some good tutorial for this?

#

iam trying to make it into standalone package

waxen sandal
#

What's the error you're getting

native geode
#

There is no error just it doesnt show when i right click in hierarchy

#

i tried to follow this tutorial

waxen sandal
#

The menu item?

#

If you pass the path like that then it's in the top menu bar

#

Or your editor doesn't show?

native geode
#

but why not in

#

oh

waxen sandal
#

I think if you want it in hierarchy you need to start with Assets/

native geode
#

I GOTCHU

#

needed to have GameObject

waxen sandal
#

Ah right

#

I always forget, that was my other guess

native geode
#

maybe you have answer for this too, basically tutorial uses resources folder

Resources.Load<GameObject>("Microlight/SpriteRendererHealthBar")

so basically this, how would i do that but without resources folder?
i want to spawn prefab from this prefab folder

waxen sandal
#

AssetDatabase.LoadassetAtPath

native geode
#

trying it out

native geode
# waxen sandal AssetDatabase.LoadassetAtPath
    [MenuItem("GameObject/Microlight/SpriteRenderer Health Bar")]
    public static void AddSpriteRendererHealthBar() {
        GameObject go = Instantiate((GameObject)AssetDatabase.LoadAssetAtPath("Assets/Plugins/Microlight/Prefabs/SpriteRendererHP", typeof(HealthBar)));
        go.transform.SetParent(Selection.activeGameObject.transform);
    }

Trying various options and nothing works
This is assets folder

#

reports that asset is null

native geode
#

this line made it work

whole steppe
#

I might be out of sanity to ask this, but!

Is there a QuaternionField EditorGUI method to display a quaternion field?
Or do I have to convert it to Vector4 and then use something like this EditorGUILayout.Vector4Field() ?

waxen sandal
#

Quaternions are not meant to be edited manually

#

Unity uses euler angles to have some more sane numbers (and all the problems that come with that)

#

But yeah, if you really want that then vector4 field is probably best

whole steppe
#

so indeed I'm going insane O.o

naive thorn
#

so i have a base class and an inheriting class, im trying to create an editor window for the base class

#

i want to also then display my inheriting class's default inspector on top of my custom editor ive got for my base class

#

im aware of the custom editor's editorForChildClasses field, but that just overwrites the inheriting classes outright

#

for example:

#

the intended outcome is that the scriptableobj first draws the oninspectorgui of my custom editor window, then i draw the default gui for only the non inherited serialized fields (So in the above example, the UnlockableId field is properly drawn, but TestString which is in the inheriting class doesnt show up)

#

any way I can accomplish this?

gloomy chasm
# naive thorn any way I can accomplish this?

A couple of ways. The easiest way is to mark the fields in the base class with [HideInInspector] and then in your editor just draw whatever you want and then do DrawDefaultInspector().

dark roost
#

I'm currently unsure how to propagate changes to a ScriptableObject loaded in a custom EditorWindow back to the asset on disk. I have an EditorWindow that opens up a Map file as such:

    {
        MapEditorWindow window = GetWindow<MapEditorWindow>("Map Editor");
        window._map = map;
        window.titleContent = new GUIContent(text: "Map Editor");

        Debug.Log(map.name);

        window._initialized = window.Initialize(); // Populates the interface
    }```

Within this editor, there is a button that runs the following code:
```private void NewTile()
    {
        Undo.RecordObject(_map, "Added tile node to map");
        _map.CreateTileNode(UnityEngine.Random.Range(-150f,150), UnityEngine.Random.Range(-150f, 150));
        AssetDatabase.SaveAssets();
        DrawMapNodes(); // Just handles interface stuff
    }```

The body of DrawMapNodes() is as follows:
```private void DrawMapNodes()
    {
        Debug.Log($"Drawing {_map.tileNodes.Count} tile nodes");

        foreach(MapTileNode tileNode in _map.tileNodes)
        {
            VisualElement tileNodeVE = _tileNodeTree.CloneTree().Children().First();

            tileNodeVE.style.left = tileNode.position.x + _mapBackgroundVE.resolvedStyle.width * 0.5f;
            tileNodeVE.style.top = tileNode.position.y + _mapBackgroundVE.resolvedStyle.height * 0.5f;

            _mapBackgroundVE.Add(tileNodeVE);
        }
    }```

My problem is that the Map object stored at `_map` appears to gain a new `MapTileNode` and it is appropriately drawn by `DrawMapNodes()`, however the asset on disk doesn't receive any changes.  `NewTile()` currently contains some absolute soup because I was last trying to convince the asset to propagate changes there.  What am I missing / what is the proper way to save changes back to disk?

Thanks ahead!
eager river
#

Working on dialogue system and I am starting to build window editor for creating conversations. I want to do something like Unity's State Machine for animations using UIElements, where you can freely move dialogue boxes. Is there any ready solution or UI class that will make it easier or do I need to code it myself?

dark roost
eager river
dark roost
#

Save ScriptableObject

brisk summit
#

yo, is anyone able to give a hint at what I need to do to return the selected value in my array? I'm wanting to have it so where if you remove it from the list then it also deletes the object from the scene

gloomy chasm
brisk summit
brisk summit
# gloomy chasm Need to do it yourself

aight, thank you

how would I reference my list? it's in another script, and there's an error when I try the following:

       _points = new ReorderableList(serializedObject, _connectedObjects.followPoints);
gloomy chasm
#

You create a SerializedObject for that other object, and get the array property

brisk summit
#

yeah

#

the list is currently public, I assume I need to set [serializefield] before it?

gloomy chasm
#

No, if it is public it is already serialized

#

[SerializeField] is only required on private fields.

brisk summit
#

ah sweet, cheers

how would I create a reference to the list?

gloomy chasm
#

As I said, you would create a SerializedObject for the object container the list, and then use FindProperty to get a SerializedProperty for the list

brisk summit
gloomy chasm
brisk summit
#

hell yeah

#

I have it working I think

#

@gloomy chasm apologies for the ping, would you potentially know any reasons why I can't remove elements from the list? I think it does remove it but fails to update the view

#

nvm got it

thorn raptor
#

it doesnt throw errors anymore because i have a switch case that tries to figure out what class type the object is

#

but its not recognising it as the classes they are meant to be even when I dont modify those classes

thorn raptor
#

okay i think the situation is best summed up as:

  • there is a class, let's call it b, that contains a list of another class, c
  • class c contains a 1D array of a class, a, which classes b and c, as well as some others, all derive from
  • upon script recompiling, everything saves as expected, except all the stuff with classes that derive from a is no longer recognised as the same classes they were before the scripts recompiled. It's implied they're still there, and that the data isn't null, just that for whatever reason the logic stops being able to read it as the classes they were prior.
#

is there some way to get it to show me all the data stored in a class it doesnt recognise

#

ig ToString

#

ooh okay

#

so it recognises the unknown types as having been derived from a

#

the asset file itself still has data for c's list of classes deriving from a

#

oh okay

#

so the asset file isnt actually saving any of the data

#

what its displaying is exactly what was being written to the file so maybe you cant serialise this way either Sadge

thorn raptor
#

wait I might be really stupid actually

#

i was stupid

#

i thought it said SerializeReference but is said SerializeField

#

the asset file seems to be saving all of it properly now

#

and the assets are now surviving script compilation

#

- ignore everything i've said please, its working now -

#

lmao

native geode
#

I got my custom menu item and i can spawn it.
i added this validator

return Selection.activeGameObject && Selection.activeGameObject.GetComponentInParent<Canvas>();

but is there function like CreateDefaultCanvas?
or should i create event system and canvas on my own in validator if none exists