#↕️┃editor-extensions

1 messages · Page 104 of 1

idle tree
#

all I want to do is solve that, and I thought getting that value in there would work, but it doesnt

#

I have no idea what im doing, no one I've reached out to will help me or even reply, I'm trying more and more things with no idea what im doing, I'm stuck and frustrated

#

I hate being ignored, I hate tutorials that don't explain things well enough, I hate that im so fucking stupid I can't do anything myself

mossy oyster
#

am trying to create tool to editor using the new Ui elements am having ObjectField the problem ObjectField doesn't persist the object after attaching it became empty again

acoustic egret
#

I have a type X which contains a type Y. How can I make the inspector for type X just show the inspector for the contained type Y?

#

Please ping me if you respond :)

acoustic egret
#

thanks!

patent pebble
#

@acoustic egret in that example they don't show how to draw the "header" (the title bar in the inspector)

#

but you can use myEditor.DrawHeader();

#

just before you draw the body of the inspector with myEditor.OnInspectorGUI();

#

however the header drawn with that is very thick, so I don't really like it

acoustic egret
#

perfect, thanks!

valid wharf
#

hello I'm trying to make my own Settings in the Project Settings window using a separate UXML file.
Am I doing this right? nothing is showing up.

sick canyon
#

Does anyone here know what to do with the Localization system and Japanese?

#

nvm

#

Got it

idle tree
#

This code block draws every property of a SerializedProperty. How would I refactor it to draw every property of a SerializedObject?

idle tree
# idle tree This code block draws every property of a SerializedProperty. How would I refact...
    protected void DrawProperties(SerializedObject obj)
    {
        var iterator = obj.GetIterator();
        iterator.Next(true);
        foreach (SerializedProperty p in iterator)
        {
            DrawProperties(p, true);
        }
    }```
This was my attempt to refactor it to work on SerializedObjects instead of properties, but it doesnt work. There's no error redline blocking compile, but the code doesn't fill the EditorWindow with anything
patent lichen
#

I am not sure if this question is best asked here or in a different channel, but I trying to use the Facebook SDK in my app. Currently, I am just authenticating with it. My code works fine on my machine, but when I push to an Android device, the app dies right at startup and the error is: Error AndroidRuntime java.lang.RuntimeException: Unable to get provider com.facebook.FacebookContentProvider: java.lang.ClassNotFoundException: Didn't find class "com.facebook.FacebookContentProvider" on path: Does anyone have experience with FB SDK and know how to address this?

gloomy chasm
fleet token
#

I'm having a weird issue I don't know exactly how to tackle: I'm trying to do some custom serialization for an array, its justa bunch of checkboxes and a field for its width. However, if I change the width value, on the OnAfterDeserialize call, I get an IndexOutOfRangeException, since the width value was changed, but at the time of that deserialization, the actual array itself still has its old Length. Am I going about this in a completely wrong way?

gloomy chasm
fleet token
#

Sure! One sec, let me trim to the relevant parts

fleet token
#

thanks for offering!

#

and yeah, the actual error happens on line 27 of this second paste, but the actual fault is not on that function: if I move from a 5x5 to a 6x5, To2D receives a 25-long array, but a "6" width

gloomy chasm
fleet token
#

Sorry, where would you do a double for?

#

you mean you wouldn't flatten and then rehidrate?

gloomy chasm
fleet token
#

Ah, yeah, I guess it is a bit inconsistent

gloomy chasm
#

Btw, use the height that you save, don't get it from the length as that could be messing stuff up

#

Actually, why are you not saving the size of the 2D array

fleet token
#

Well, I don't think it should make a difference. After some checking, I'm pretty sure that the issue is that I modify the Width value, that triggers a new serialization loop, and the DataGrid class has (for example) an updated Width, but an outdated _flatGrid, so the dimensions mismatch

gloomy chasm
#

Yeah, that sounds right

fleet token
#

I think if I could say something like "Hey, if your height or width change, flush your current grid data and start from 0" it would be fine

#

(or something like that)

gloomy chasm
#

You are using the 2d array's width when flattening, but using the stored variable when deserializing

#

Ya gotta be consistent

fleet token
#

ah

#

let me check

#

yeah man

#

right on the money

#

you a genius

#

makes total sense

#

sorry, in the end it really was a stupid mistake

sinful osprey
#

Oh I could have scrolled up to see property.isExpanded which works in my case. Still, if I were to have more than one foldout per property, what could I do?

gloomy chasm
sinful osprey
#

Perhaps using the isExpanded state from an unrelated subproperty that doesn't expand if it ever came to that?

mossy oyster
supple briar
#

Hello guys and ladies. I have custom Tile based on Tile class. But I need to visualize it depending which sprite I add. If will be ideal if it takes sprite from base Tile class so I can omit Preview property. Can you help me someone please? I prefer this order but will be grateful for any of it:

  1. Sprite drawn instead of universal asset icon.
  2. Sprite drawn in the inspector as preview (bottom) or as rectangle.
  3. Preview property in inspector like on material for example. So I can see it there instead of this row one.
patent pebble
#

is there any way to get the type of an asset from a GUID without having to load the object?

#

there's this method, but it uses instance IDs

InternalEditorUtility.GetTypeWithoutLoadingObject(int instanceID)
#

any alternative to that one?

onyx harness
#

Lol, kinda weird, instance Id means it is loaded isn't it?

waxen sandal
#

Afaik yes

#

Anyways, just get the metapath and cehck that for the guid

patent pebble
#

no idea I just found it googling randomly, haven't tested it

waxen sandal
#

I guess the metadata might be loaded since it needs to exist in the project view

lunar mortar
#

hello, I've created a piece of code in custom Editor Window that changes value of variable based on colliders. And it changes accordingly, but changes even if they are visible in scene after starting the game they are reverted. And I don't know why. Video shows the problem. Can You help me?

#

Sorry for sound, didn't know that twitch sound was also recording ;p

waxen sandal
#

You gotta use serializedproperties or dirty the object

idle tree
#

I dont understand how people are using these scripts with SerializedProperties to loop through anything or get more children, like, fundamentally I am missing something vital here

#

I am not understanding the difference between these two things maybe?
A serializedProperty is a single field in a SerializedObject? Yes? No?

#

How can all these scripts that ask for a single serialized property somehow serialize every field in a serialized object?

#

I -really- need some help with this, I am getting no where reading doccumentation

patent pebble
#

@idle tree have you used EditorWindows before? Just asking for context

idle tree
#

This is me trying to learn them

#

I got to where I am by following a tutorial to learn EditorWindows, but the tutorial was not very comprehensive and explained very little, so now I have gotten stuck trying to use any of it or go anywhere from here

#

I think I have a decent understanding of things like if(button) and layout, its specifically ScriptableObject SerializedObject and~~ ScriptableProperty~~ SerializedProperty that is tripping me up

patent pebble
#

@idle tree

public class SomeEditorWindow : EditorWindow
{
    // The actual data in this window class instance
    [SerializeField] private string _someString;
    [SerializeField] private float _someFloat;

    // The serialized representation of our Window's class instance
    private SerializedObject _serObj;

    // The serialized representations of our Window's class data
    private SerializedProperty _someStringProp;
    private SerializedProperty _someFloatProp;

    [MenuItem("Something/OpenWindow")]
    public static void OpenWindow()
    {
        GetWindow<SomeEditorWindow>();
    }

    // This is called when the Window is opened
    private void OnEnable()
    {
        _serObj = new SerializedObject(this); // Create a SerializedObject that represents the window instance
        _someStringProp = _serObj.FindProperty("_someString");
        _someFloatProp = _serObj.FindProperty("_someFloat");
    }

    private void OnGUI()
    {
        // Approach 1
        _someString = EditorGUILayout.TextField("Some String", _someString);
        _someFloat = EditorGUILayout.FloatField("Some Float", _someFloat);

        _serObj.Update(); // Update the SerializedObject so we get the values that currently exist
        
        // Approach 2
        _someStringProp.stringValue = EditorGUILayout.TextField("Some String", _someStringProp.stringValue);
        _someFloatProp.floatValue = EditorGUILayout.FloatField("Some Float", _someFloatProp.floatValue);

        // Approach 3
        EditorGUILayout.PropertyField(_someStringProp);
        EditorGUILayout.PropertyField(_someFloatProp);

        _serObj.ApplyModifiedProperties(); // Apply any changes that were made to the SerializedProperties
    }
}
#

This is one of the most basic examples I can think of to explain how it works

#

it's easy to visualize because it's all self contained in one class

#

see how the fields _someString and _someFloat can be used interchangeable with their corresponding serialized properties?

#

in the OnGUI method you can see 3 ways of editing the values of the fields in the class

#

1- Using the fields directly
2- Using the properties' data values
3- Using the properties with a property field

#

all 3 change the data in the exact same way, but 2 and 3 provide extra benefits. Like undo support, automatic styling, etc

#

the docs for SerializedObject say this
SerializedObject and SerializedProperty are classes for editing serialized fields on Unity objects in a completely generic way.

#

with "in a completely generic way" they mean that you can just deal with SerializedProperties by using a PropertyField and forget about anything else

#

you don't need to know the data type, you don't need to know almost anything

#

except the name of the property and the SerializedObject to which they belong

idle tree
#

(I'm reading all this carefully)

patent pebble
#

yeah take your time to internalize it all, it took me a while to get used to it the first time I tried to use them

#

I've lost context of your original conversation with MechWarrior so feel free to @ me and ask again whatever your questions are and I'll try to help

idle tree
# patent pebble I've lost context of your original conversation with MechWarrior so feel free to...

Will do. I am comparing your commented code example to the tutorials I followed and scripts I was shown.

SerializedProperty iterator = myProperty.Copy();
while (it.Next(true))
{
      Debug.Log(it.name);
}```
I was linked this as an example of "Looping through every serialized property in a serialized object" but I am not understanding where or how to use it to achieve that. Where does the reference to serialized object go? How does the property know if it is the "first" property? Or what the "next" property is?
gloomy chasm
idle tree
#

I am understanding now that the EditorWindow itself is the SerializedObject. In the tutorial I followed, the tutorializer made another SerializedObject as a variable within the EditorWindow, then populated the EditorWindow with all the Inspector data of the ScriptableObject variable the window held reference to.

However the way they did it confuses me greatly. Their ScriptableObject's "entry point" was an Array variable within the ScriptableObject, and mine has all the variables at the root of the scriptable object, not within a property, and so far all the examples I have looked at seem to refer to only a single Serialized Property, and don't explain how I can use that to use a SerializedObject ever, it all seems to revolve around Serialized Properties?

#

(I also keep mixing up Scriptable Object with Serialized Object which isn't helping either)

gloomy chasm
patent pebble
#

a better way of debugging a SerializedPoperty is by doing

Debug.Log(someSerializedProperty.propertyPath);
#

a lot better to visualize the whole path of the property

idle tree
patent pebble
#

@idle tree can you maybe share the tutorial you're following? so we can see some context

idle tree
patent pebble
#

it may be that they are using a custom Editor for the scriptable object, or that they are doing it directly on an EditorWindow

idle tree
patent pebble
#

also, EditorWindows and SerializedObjects/SerializedProperties are not related per se

#

an EditorWindow is just a way of displaying whatever data you give to it

idle tree
# patent pebble <@!78571959029334016> can you maybe share the tutorial you're following? so we c...

https://www.youtube.com/watch?v=c_3DXBrH-Is
I even joined this person's discord and asked their community but did not get answers there

In this video we take a look at how to dynamically draw Editor Windows in Unity by harnessing the power of the SerializedObject and SerializedProperty classes.

We create a tool that will automatically draw an inspector-like editor window, for any object we pass into it.

Be sure to LIKE and SUBSCRIBE if you enjoyed this guide! Share the video ...

▶ Play video
patent pebble
#

you can display a bunch of variables in an EditorWindow without ever using any SerializedObject or SerializedProperty

#

ah ye I remember that tutorial, was also a bit confusing for me

idle tree
#

which is why I was lead towards the path of SerializedObject and SerializedProperty, because MechWarrior99 was telling me not to be sloppy and just do "SetDirty"

idle tree
patent pebble
#

yeah

idle tree
#

At this point I think Ive spent more time trying to learn a whole lot of new concepts all at once that I am unfamiliar with than if I had just done the work I need to do manually, but it is valuable knowledge to have, the ability to make your own tools to automate work

#

and I know Odin exists 🔥 But I don't want to use it, there are too many draw backs, like you can't use it in a project with any other person who doesn't have a license, which would make me incapable of using it in any kind of practical environment

patent pebble
#

in that tutorial you're getting confused by the array, because each element of that array represents an instance of the class he's using for the example

#

there's 3 different topics in that tutorial, and he just mashed them all together
EditorWindows
Custom Editors
SerializedObjects/SerializedProperties

idle tree
#
    protected void DrawProperties(SerializedProperty prop, bool drawChildren)
    {
        string lastPropPath = string.Empty;
        foreach(SerializedProperty p in prop)
        {
            if (p.isArray && p.propertyType == SerializedPropertyType.Generic)
            {
                EditorGUILayout.BeginHorizontal();
                p.isExpanded = EditorGUILayout.Foldout(p.isExpanded, p.displayName);
                EditorGUILayout.EndHorizontal();

                if (p.isExpanded)
                {
                    EditorGUI.indentLevel++;
                    DrawProperties(p, drawChildren);
                    EditorGUI.indentLevel--;
                }
            }
            else
            {
                if (!string.IsNullOrEmpty(lastPropPath) && p.propertyPath.Contains(lastPropPath)) { continue; }
                lastPropPath = p.propertyPath;
                EditorGUILayout.PropertyField(p, drawChildren);
            }
        }
    }```
This is the method he writes that loops through all the SerializedProperties from the root array, but it makes no mention of SerializedObject
idle tree
#

Maybe it would be better if I just gave up entirely and tried to find some other tutorial to introduce me to EditorWindows, Custom Editors, and SerializedObjects/SerializedProperties?

patent pebble
#

the initial SerializedProperty is the serialized representation of that list

#

that's why he's able to loop just using that SerializedProperty

idle tree
patent pebble
#
foreach(SerializedProperty p in prop)
{
  ···
}

this snippet you shared is looping through the elements of the GameData list in the GameDataObject

#

so each loop he has a SerializedProperty that represents a GameData instance

#

then he just recursively loops again in the children properties to draw all the variables he has in the GameData class

#

it's not a great tutorial, horrible naming scheme, mixes a lot of concepts without any real explanation of which is what

idle tree
patent pebble
#

foreach(SerializedProperty p in prop) in this example the prop is the GameData[]

#

i'd just skip this tutorial

#

go learn about custom Editors, EditorWindows and SerializedProperties/SerializedObjects separately

#

it will be a lot less confusing

idle tree
#

I will do that. I was kind of envious of this tutorial because he makes it sound very easy to set up Custom Editors / Editor Windows, because I know I have struggled with Custom Inspector type stuff with how much work it takes to write out a custom inspector

#

I put myself through a lot of anguish trying to "get it to work" from what little is in that video

patent pebble
#

once you get the hang of it, it's pretty easy

#

the thing that consumes the most time is designing the layout and all that stuff

#

for most custom Editors you'll just be using automatic layout and mostly using PropertyFields to automate everything

#

so you just need to learn how the SerializedProperties/SerializedObjects work, the quirks of the different types of properties, how to loop through them, etc

idle tree
gloomy chasm
patent pebble
#

to be honest, for this topic I just learned from the documentation examples and then fiddling around with them and trying out things and googling specific questions

#

and asking a lot on this channel, MechWarrior was specially helpful 😊
other folks too

idle tree
#

I also find I learn much better from video tutorials or people stepping me through code rather than Unity's documentation pages, they always assume the reader knows a lot more than I do I find

patent pebble
#

the most basic examples of SerializedProperties usage will probably be in Custom Editor tutorials

#

i'd suggest doing those

idle tree
# patent pebble the most basic examples of SerializedProperties usage will probably be in Custom...
Unity Learn

One of Unity's most powerful features is its extensible editor. This recorded talk from Unity 2011 introduces the basics of custom editor windows and inspectors, showing how to automate certain tasks, create custom GUI, and integrate with the rest of the editor to support specific workflows.

#

Oh custom editor tutorials in general, I understand now

patent pebble
#

yeah the terminology is a bit borked, some people called them "Custom Inspectors", but the "official" name seems to be Custom Editors

idle tree
#

I.. I am struggling to give up on this guy's tutorial. I don't want to lose, I don't want to fail. I think my ego is getting better of me, I want what he shows and it very nearly hurts to just give up on it, lose, be defeated

patent pebble
#

that video seems a bit old, but skimming through it it looks like they try to break down all the stuff into bite-sized chunks

idle tree
#

I feel like I am so close to beating it but in reality that is very likely not the case

patent pebble
#

nah don't worry

#

once it "clicks" you'll see how easy it becomes

#

it took me a couple of weeks to understand it, initially I was like "wtf is this alien language" but then i was "ah, this is so simple lmao"

#

🙃

idle tree
#

I feel like the sollution to this problem is that I need to find some way to loop through every top level Serialized Property, ignoring their children, of my Serialized Object, set them to currentProperty and then run DrawProperties on it, one by one

#

Mech then linked me a link on doing exactly that, looping through serialized object, but I got stuck again immediately

idle tree
#

This is where I posted that code snippet from that is supposed to do it

#

What is "myProperty" ? Is it ANY property in the Serialized Object? A specifc one? The first one?

#

How do I know if its first?

idle tree
#

I dont need to loop through all the children of a property, I need to loop through all the scriptable properties of a scriptable object

#

Thjat is what I am not getting, none of these tutorials ever reference Scriptable Objects Serialzied Objects

gloomy chasm
idle tree
# gloomy chasm `serializedObject.GetIterator();`
    // An attempt of mine to make it work with a serialized Object that does not work.
    protected void DrawProperties(SerializedObject obj)
    {
        var iterator = obj.GetIterator();
        iterator.Next(true);
        foreach (SerializedProperty p in iterator)
        {
            DrawProperties(p, true);
        }
    }```
#

I'm doing something wrong here, this is as far as I got with GetIterator and using the errors VSCode spat out to write it

gloomy chasm
idle tree
#

I know, I will google a tutorial on how to use GetIterator maybe?

idle tree
#

I have banished thoughts of doing anything after that because I haven't been able to get that much done yet, even I dont remember where I was going at this point

idle tree
#

    // An attempt of mine to make it work with a serialized Object that does not work.
    protected void DrawProperties(SerializedObject obj)
    {
        var iterator = obj.GetIterator();
        iterator.Next(true);
        foreach (SerializedProperty p in iterator)
        {
            DrawProperties(p, true);
        }
    }
#

This was my attempt to write code to make it accept a ScriptableObject

#

fuck

#

Serialized Object

gloomy chasm
#

Right, so what part of that code is not working?

idle tree
idle tree
idle tree
#

I ran it, it skips over foreach entirely

#

No console errors, nothing is null

patent pebble
#

@idle tree you don't need to do a recursive call of your method inside itself, using .Next(true) or .NextVisible(true) will get EVERY property after the one you provide as the iterator

#

including children properties

idle tree
patent pebble
#

i forget in what order the properties are iterated, but I think it enters children before moving to the next top level property

gloomy chasm
#

Internal implementation^

idle tree
#

two different methods that take a different parameter, I guess its not actually an overload method so I shouldnt have done that? Or it is maybe? At this point I doubt everything I know or have done

idle tree
idle tree
gloomy chasm
idle tree
#

I'm sorry I don't know what to do with this information

#

Should I edit GetEnumerator? I don't think I can do that

gloomy chasm
#

No

idle tree
#

I could write it like a regular for maybe?

#

I think this is equivalent?

gloomy chasm
idle tree
#
        for (int i = 0; i < iterator.arraySize; i++)
        {
            DrawProperties(iterator.GetArrayElementAtIndex(i), true);
        }
        foreach (SerializedProperty p in iterator)
        {
            DrawProperties(p, true);
        }```
gloomy chasm
idle tree
#

oh, sorry?

#

so should I go back to for each?

#

I am utterly lost at this point

gloomy chasm
#

Its okay, yeah. Just ignore it like you never saw it

#
public static IEnumerable<SerializedProperty> GetChildren(SerializedObject so)
    {
        var property = so.GetIterator();
        property.Next(true);
        var nextElement = property.Copy();
        bool hasNextElement = nextElement.NextVisible(false);
        if (!hasNextElement)
        {
            nextElement = null;
        }
 
        property.NextVisible(true);
        while (true)
        {
            if ((SerializedProperty.EqualContents(property, nextElement)))
            {
                yield break;
            }
 
            yield return property;
 
            bool hasNext = property.NextVisible(false);
            if (!hasNext)
            {
                break;
            }
       }
}
idle tree
#

and if you tell me they arent identical, I feel like you are telling me that I literally know nothing about for loops, and every single for loop ive ever written is wrong

#

Which may very well be the case

#

Is this one of those cases where -technically- its not the same because programmers very deeply care about being semantically correct, but functionally it does the same thing in the end?

idle tree
#

I'm sorry I'm being argumentatitive now. I'll read that post

patent pebble
#

that dude in the tutorial you linked earlier was using a foreach loop to just loop through the elements in the serialized property that represented an array

#

I don't think you can iterate through the other properties doing that, not sure, I alwaus just use Next or NextVisible

#

that will iterate through EVERY serialized property in your object

#

well, depending on if you tell it to go into the children

gloomy chasm
patent pebble
idle tree
idle tree
idle tree
# gloomy chasm I edited it

Your version wont compile.
GetIterator is a method which is not valid in the given context

using UnityEngine;
using UnityEditor;
using System.Collections.Generic;

public static class EditorExtensionMethods
{
    public static IEnumerable<SerializedProperty> GetChildren(SerializedObject so)
    {
        var property = so.GetIterator.Next(false);
        var nextElement = property.Copy();
        bool hasNextElement = nextElement.NextVisible(false);
        if (!hasNextElement)
        {
            nextElement = null;
        }

        property.NextVisible(true);
        while (true)
        {
            if ((SerializedProperty.EqualContents(property, nextElement)))
            {
                yield break;
            }

            yield return property;

            bool hasNext = property.NextVisible(false);
            if (!hasNext)
            {
                break;
            }
        }
    }
}
patent pebble
#

i mean, if you want the most basic example of how to iterate through properties on an object:

#
private void IterateProperties(SerializedObject serObj)
{
    SerializedProperty iterator = serObj.GetIterator();

    while (iterator.NextVisible(true))
    {
        Debug.Log(iterator.propertyPath);
    }
}
idle tree
# gloomy chasm Edited mine

Okay I am reading through, attempting to come to comprehension of it. It returns an IEnumerable. It starts from the first property, and moves through them in some way that my understanding starts to get muddy.

I am also getting a VERY long error when I try to use the method, trying to screen capture it

idle tree
#

I think its saying I cant convert a serialized Property to a serialized property?

#

I'm sorry I am not very bright, guys. You are doing a lot to help me and I feel like I am letting you both down

gloomy chasm
#

@patent pebble No idea if this will help or what it does, but I found UnityEditorInternal.InternalEditorUtility.ProjectWindowDrag(..) incase you are interested (The class has a tone of neat stuff)

idle tree
#

Okay I added the cast that VS code suggested

#

VS code was wrong

patent pebble
#

thx for sharing anyways

gloomy chasm
#

Ah yeah, makes sense. Didn't look at it at all haha

idle tree
#

it keeps saying I cant convert a serialized property to a serialized property

patent pebble
gloomy chasm
idle tree
#

Was I supposed to use it over here? Because that didnt work either

gloomy chasm
# idle tree

My man, the GetChildren returns an IEnumerable<SerializedProperty>

#

This is why ya can't just go copy pasting code, it doesn't help you understand anything

idle tree
#

I have no idea what that is or how it relates to all this, so far we have not covered that at all

#

Yes I know, I am not trying to copy paste code, I am trying to come to an understanding

#

that is why I am asking all these questions, here, now

#

Why did you link me that code block if you didnt want to help me come to an understanding?

#

That feels kind of cruel to link something, say this will solve all your problems, then refuse to elaborate further on how to use it

#

I guess you -didnt- say it would solve all my problems, that was just how it felt

#

I want to learn, I want to grow

#

I'm sorry I am not very bright or experienced

gloomy chasm
#

Right, you foreach over it.

var properties = EditorExtensionMethods.GetChildren(serializedObject);
foreach (SerializedProperty prop in properties)
{
  DrawProperties(prop, false);
}

If it doesn't make sense I would try looking up some info on foreach and IEnumerable.

idle tree
#

tenacity is just about the only good quality I have to rely on , sorry stuff about me personally doesnt matter, moving onto code again

#

professionals dont talk about themselves, we're in it for the code only 😣

gloomy chasm
# idle tree That feels kind of cruel to link something, say this will solve all your problem...

I am trying here man, I never know how much or little experience some one has so that makes it more difficult to know how much they need help sometimes. Some of the questions at this point are just normal C# questions, which I don't mind to a point, but ya also gotta look this stuff up your self or ask in #archived-code-general.
I try to help where I can, I understand editor stuff can feel complex or hard to get. But I also work, and just help out because I know how it is to be that person who doesn't understand.

idle tree
gloomy chasm
idle tree
#

I'm having trouble determining what things "are", when I debug log a serialized object, I just get "serialized object"

idle tree
patent pebble
#

or something like that

idle tree
#

Hmm, it gets to the yield break, but then outside of the method

#

it then bypasses foreach

#

when I step forward, it just ignores it

#

Im going to close and reopen VS code

patent pebble
#

make sure if you're using custom classes that the are marked as [Serializable] and that your variables are using the [SerializeField] attribute

idle tree
#

the class is serializable

patent pebble
#

what do your DrawProperties methods do currently?

#

you may be trying to draw an array's properties when the size of the array is 0

idle tree
#

havent touched them yet, right now the foreach is being skipped over, DrawProperties is never called

#

okay VS code is reopened, stepping through again

patent pebble
#

debug everything

idle tree
#

Hmmm something weird is happening

patent pebble
#

literally do a Debug.Log after every line

#

or you'll never know what's happening 🙂

idle tree
#

Okay I can do that

#

right now when I hit F11 on the first line

#

it doesnt go into the function, it skips it

#

but then it goes into that function of line 16 on line 17

#

plugging in debugs of everything now

#

Ive never seen VS do this, ever

#

so is Shovel, that's expected Im testing this on a shovel

#

I don't know what Base is refering to

#

nothing im aware of is called Base

#

and I definitely have no idea what m_objectHideFlags and m_script are, those aren't things I wrote

patent pebble
#

those are properties that belong to the SerializedObject, which in your case I assume it's either a Monobehaviour or a ScriptableObject

idle tree
#

ScriptableObject in this case, because that's what tutorial guy was using

patent pebble
#

SerializedProperties are not just your data, they are also a bunch of other things that the object has, like the scripts, the hide flags, the sizes of arrays, etc

idle tree
#

So it sounds like its getting caught up in scriptable object stuff? Yeah what you just said

patent pebble
#

you can avoid that by getting yourself your top-level SerializedProperties and then doing something similar to that GetChildren method

#

but instead of passing a SerializedObject you pass each of the top-level SerializedProperties

#

you can always access those because you know their names (the names of the variables in your ScriptableObject)

idle tree
#

Is there a way to loop all the top level serialized properties or would that involve me writing out line by line the variable name string?

#

The entire point of this was sort of to not need to write out line by line every string, at that point Im just writing a custom inspector with extra steps

#

which I mean, I guess, is what I am doing

#

I am not understanding why it stops on that one line and draws nothing though hrrmgh

#

Like, I would expect it to draw -something-, its supposed to be doing foreach every single serializedProperty

#

but its only doing the very first one, then never drawing it, and then just doing the very first one over and over?

patent pebble
#

@idle tree how are you drawing the properties?

#

with PropertyField?

idle tree
#

DrawProperties draws the properties and DrawProperties never gets called

#

foreach (SerializedProperty prop in properties) never enters

#

I'm not drawing the properties because the method to draw the properties doesnt get called because I cant figure out why the foreach wont enter

patent pebble
#

have you debugged the size of the collection of properties?

#

if it has nothing to loop on... well, it won't loop on anything

idle tree
#

Properties doesnt have a Size, Length, Count, or any other variable like that

#

properties is an IEnumerable<SerializedProperty>

#

I cant find a size to debug

idle tree
patent pebble
#

convert it into an array and debug the Length

idle tree
#

If I debug property INSIDE the function, it says it has no size

#

I think I should just stop, just quit

patent pebble
#

only properties of type array have an array size

idle tree
#

I have no comprehension at all what this script is doing anymore

#

I'm so far out of my depth and league its not even funny

#

this makes me incredibly unhappy to have to give up

patent pebble
#

i don't think you understand how the GetChildren method works, at this point it's better if you went and tried to elarn what all the pieces are and how they work

#

you don't know what an IEnumeable is or how to use it

#

that's one of the reasons you're struggling with this

idle tree
#

You are right, I don't know anything

#

it hurts me enormously in the chest to lose so badly like this. Programmers don't get hurt because they don't understand something

#

and i'm a programmer, so I shouldnt be in pain for losing

#

Its not losing to not understand something

patent pebble
#

i mean you can just skip the looping and get the properties manually by their name, and draw them with PropertyField

#

that will iterate automatically through all their children and draw them

#

literally most of the time when someone does a custom editor or anything involving SerializedProperties, we just get them by name

#

specially if it's something simple

idle tree
#

Something is happening that I don't understand

#

that is helping me see why I have no idea whats going on

#

I commented out ALL the new code

#

saved it

#

compiled it

#

Unity is still running all the code I just commented out

#

its spitting out all the debug logs from the method I am no longer running

#

Which is impossible if I saved the file and recompiled it like Unity and VS code both say I did

#

this is extremely frustrating

#

Nothing is working the way I am promised by the machines themselves that it will work. this. way.

#

How can I hope to debug anything when netiher Unity nor Vs Code will even show me the truth

#

the answer is because I'm stupid, as usual

#

I was running my stupid overload method with the same stupid name

#

and I didnt see it because i'm a fucking blind idiot

#

Great. So this is where I am at now. I wasted my entire day. @gloomy chasm I wasted your entire day. and @patent pebble I wasted your entire day.
I achieved absolutely nothing, and returned to the exact same position I started with, a complete failure

#

I'm sorry I'm so fucking worthless

#

im just going to leave now because my mental health has crumbled because of the utter failure that is myself and my attempts to achieve anything ever

#

I appreciate both of your help enormously

#

I'm sorry im a worthless failure

#

im sorry I wasted your time

patent pebble
#

you didn't waste our time, we help because we want to. We've been in the same situation asking something that we didn't know how to solve and people helped because they wanted to

#

it's fine

gloomy chasm
idle tree
#

I came back because I shouldnt run away and sit on the pity pot

#

I'm sorry I struggle with my mental health publicly

idle tree
patent pebble
#

you just have to get used to this sort of stuff

#

last week I spent 3 days trying to implement something that in the end wasn't possible due to Unity's limitations

#

i just scrapped it and moved on to the next thing 👍

idle tree
#

Tomorrow I will close all these files related to this tutorial that has caused me nothing but grief for 3-4 days now, and just google for more random custom editor tutorials I guess

patent pebble
#

it's fine to leave stuff aside and then come back some time later with a fresh mind

#

you'll get used to it

idle tree
#

I feel slightly better that even with the help of both you two experts, together all three of us still not solve it (through me) so its clearly not a simple thing to achieve

#

It was an unreasonable expectation I placed on myself to achieve this from the tutorial

#

because the tutorial guy made it sound easy and simple and showed the immediate results

#

and showed every line of code, one by one

#

it was unreasonable of me to think I would also be able to achieve success despite having everything handed to me line by line, and with the direct help of two experts

#

No my mental health is poisoning everything I am saying

#

I'm just going to go and do something, anything, for a while, that isnt this

gloomy chasm
#

Right-o, I finally got "restoring" to work for my sidebars. You can put them back to the exact same position when you first added them to the sidebar 👌

#

The logic was a pain to figure out and cover all of the different layout scenarios. Now I just gotta make it work for tabs and floating windows haha

patent pebble
#

I think Unity staff is working on something similar for future versions of the engine

#

I think it was publicly available for alpha testing, but i'm not sure

gloomy chasm
gloomy chasm
patent pebble
#

Cant remember tbh

hot nova
#

Hello ! I was wondering : Is there a method like GUI.DrawTexture but where you specify the texture position in world coordinates and that would automatically scale the texture depending on where the camera is ? Like how the camera icon is rendered.

#

Ideally I would be able to draw some kind of floating texture that is always facing the camera next to a position handle

#

is that possible ?

hot nova
#
        Handles.BeginGUI();
        if (equipmentPartItem.sprite)
        {
            Texture2D texture2D = equipmentPartItem.sprite.texture;
            Vector3 texturePos = Camera.current.WorldToScreenPoint(Vector3.zero);
            Vector3 textureScale = Camera.current.WorldToScreenPoint(Vector3.one) - texturePos;
            textureScale /= equipmentPartItem.sprite.pixelsPerUnit;
            GUI.DrawTexture(new Rect(texturePos.x, Camera.current.pixelHeight - texturePos.y, texture2D.width * textureScale.x, texture2D.height * textureScale.y), texture2D);
        }
        Handles.EndGUI();

I figured it out myself.

wintry badger
#

Hi, does anyone know the right way to add tabs to a custom inspector (the tabs open different groupings of settings)? Currently, the index of whichever tab I have selected is saved as an int value on the script, using SerializedObject/SerializedProperty. This is nice as I can leave the inspector (by selecting a different game object, opening a new scene, or closing the eidtor), and when I reopen that scripts inspector, I see the same tab.

However, this approach results in the Scene being marked dirty. I don't like this, as I think changing tabs should be a visual choice and not effect the scene the script is in. Has anyone else found a better approach? I've thought of using EditorPrefs, howerver then the tab indexes would be shared between components of the same type, and I can see potential issues when two inspectors are open for the script type.

I also know about SerializedObject.ApplyModifiedPropertiesWithoutUndo, however use of that approach would be a big hassle given my current code, and anyway, I am not sure it is the appropriate choice.

gloomy chasm
# wintry badger Hi, does anyone know the right way to add tabs to a custom inspector (the tabs o...

Honestly I would go with the EditorPrefs or SessionState (like EditorPrefs but the settings only last while the project is open).
I am always against saving editor values in runtime code if you can help it. If you really wanted to, you could use reflection to get the field and set it that way instead of using SerializedProperty. Only downside is that the value will not be saved unless something else is changed.

#

But that is the nature of it if you don't want the scene to be dirty.

patent pebble
#

i like SessionState for things like this

#

you don't have to be as careful, you can just shove data into it and forget about it

wintry badger
wintry badger
patent pebble
#

use the Instance ID for the targetObject of your custom Editor script

wintry badger
#

Awesome, thanks! I think this will be perfect.

patent pebble
#

iirc you get the ID with Object.GetInstanceID()

#

@wintry badger this is assuming you only have one component that uses a tab system, if you have multiple in the same object I guess you can just use the name of the component + instanceID

waxen sandal
#

You can also just serialize things on the editor instance, it'll persist between play mode but not objects and restarts iirc

#

Also instance Id isn't persistent eithrr

patent pebble
#

i forgot about it

wintry badger
#

Yeah, I was wondering that too. I guess it would be easy enough to test and find out.

waxen sandal
#

I don't think it's guaranteed but it almost always does

#

Iirc it sometimes also survives restarts

patent pebble
#

even if it's not 100% stable, seems good enough for a non-critical thing such as a tab index

wintry badger
patent pebble
#

in the custom inspector (it's an Editor class)

waxen sandal
#

Yes

#

Either public or serialize field

wintry badger
#

Hmm, I was under the impression that once you click on a different game object, the inspector "object" is destroyed. Is my understanding wrong? Because in that instance, the tab index value would be reset when switching between game objects.

waxen sandal
patent pebble
waxen sandal
wintry badger
#

Ok, I just wanted to make sure I understood your suggestion completely. Awesome, thanks for the help both of you! I think I have everything I need to implement a solution.

wintry badger
#

Okay, so after some testing it appears that the instance ID is changed if you close and reopen a scene, so using it as a key will not work if you want to save the tab index between opening/closing different scenes. It does survive an assembly reload though, so will most likely work for most use cases. However, I am making note of it here for others to find in case they need similar functionality.

twin dawn
#

I want to show a context menu item when right clicking a GameObject in the hierarchy, but not in the GameObject menu. How can I do that?

#

This is my code currently

    [MenuItem("GameObject/Guardrails/Physics Check", false, 0)]
    static void CollisionCheck(MenuCommand menuCommand) {
        Debug.Log($"Hello {menuCommand.context}");
    }```
chrome mist
#

@twin dawn oo... kinda tough actually. You can disable the guardrails element by making its validator use the "Selection.activeGameObject != null" check

#

but it will stilla ppear, just be grayed out.

#

GameObject/ MenuItem path is special

twin dawn
twin dawn
chrome mist
#

👍

#

makes it pretty easy to add a hotkey for it too

twin dawn
chrome mist
#

MenuItem("GameObject/Guardrails/Physics Check %_F")

twin dawn
#

Ah ok, it all goes in that string

chrome mist
#

ye

#

there's a bunch of modifier shit. look it up

patent pebble
#

@wintry badgerthere's also this ID, maybe you can use it

wintry badger
patent pebble
#

@wintry badger you could also try to use the Local File Identifier of the GameObject within its Scene

#
public static class LocalFileIDUtility
{
    public static int GetLocalFileID(Object obj)
    {
        PropertyInfo inspectorModeInfo = typeof(SerializedObject).GetProperty("inspectorMode", BindingFlags.NonPublic | BindingFlags.Instance);

        SerializedObject serializedObject = new SerializedObject(obj);
        inspectorModeInfo.SetValue(serializedObject, InspectorMode.Debug, null);

        SerializedProperty localIdProp = serializedObject.FindProperty("m_LocalIdentfierInFile");   //Note: The misspelling is correct

        return localIdProp.intValue;
    }
}
#

haven't extensively done stuff with GlobalObjectID and LocalFileID but I would assume they are persistent enough to satisfy your needs

#

i think LocalFileID can cause situations where two GameObjects in different scenes share the same identifier, so if you're gonna use LocalFIleID you should probably include the Scene's GUID or something like that in your identifier

#

here's an extension method to get the GUID

public static class GameObjectExtensions
{
    public static string GetSceneGUID(this GameObject gameObject)
    {
        string scenePath = gameObject.scene.path;
        return AssetDatabase.AssetPathToGUID(scenePath);
    }
}
supple briar
#

Hello. I have custom scriptable tile based on Tile class. It works but unfortunately it doesn't show preview of base's Tile class Sprite property preview. So I created drawer so I can draw it as texture at bottom of inspector view. But how exactly I can get this property from base class using property.serializedObject.FindProperty("sprite")? Is it possible or I have to create reference on this sprite in my custom scriptable tile script firts?

waxen sandal
#

m_Sprite is the name probably

#

If you hold alt and click in the inspector it should show the serialized name

patent pebble
#

^ while in debug mode

supple briar
#

Thank you guys. I'll try.

patent pebble
#

Is there a way to force Unity to close context menus on middle-mouse click?

#

currently it only registers left and right click

#

i have a small tool that changes selection and opens a GenericMenu when I middle click an asset
and it's kind of annoying having to click outside with left click to be able to do middle click again on another asset

#

i want to be able to do quick successive middle clicks like I can with right clicks

candid seal
#

Hello there, I am working on an editor tool and recently I started getting constant errors after code compile.

#

In the custom tool I am creating, I use my own defined profile with custom shortcuts. The only thing I do is setup a profile if the profile doesn't exist and I set the active profile id to my custom profile. I do this in OnFocus method and I revert the changes back to the default profile after the focus is lost. So, I am confused as to what could be an issue with that.
The weird thing is that I haven't received any issues related to shortcuts manager. These errors only started to appear recently. So, confused as to what I've done that could have caused this to appear.

#

This is the code that does all that:

private void OnFocus()
{
    if (ShortcutManager.instance.GetAvailableProfileIds().ToList().FindIndex(id => id == Utils.ShortcutProfileID) == -1)
    {
        ShortcutManager.instance.CreateProfile(Utils.ShortcutProfileID);
 
        ShortcutManager.instance.activeProfileId = Utils.ShortcutProfileID;
 
        var bindings = ShortcutManager.instance.GetAvailableShortcutIds();
        foreach (var bind in bindings)
        {
            if (!bind.Contains(Utils.Title))
            {
                ShortcutManager.instance.RebindShortcut(bind, ShortcutBinding.empty);
            }
        }
    }
    ShortcutManager.instance.activeProfileId = Utils.ShortcutProfileID;
}
private void OnLostFocus()
{
    ShortcutManager.instance.activeProfileId = "Default";
}
#

And then I have the other script file, where I define all the shortcut functions. I haven't really used the shortcuts manager up until this project, so I might be utilizing this feature in not so correct way, I am not sure.

#

Can someone please give some advice, as to what could be causing these errors to appear?

#

Also, these error messages do not disappear and keep spamming the console, until I cause Unity to recompile some script

idle tree
#

With a custom inspector of a component, what is the syntax to write an IF statement based on a variable of the component I am custom inspecting?

#

I can't just do If(variableName) because no such variable exists in the customInspector class

#

How do I do an If statement based on the thing this is a CustomEditor of

#

this is maybe the answer? but I have no idea how to use it in mine

#

VS code hates every line of it

#

It looks like this is the sollution ^

tough cairn
#

how do we access the generated physics shape data for imported 2d sprites ?

tough cairn
#

found it

mossy oyster
#

ui toolkit reset button doesn't work immediately unless i switch to another gameobject and back again

eager shale
#
using UnityEngine;
using UnityEditor;

[CustomEditor(typeof(BallController))]
public class BallControllerEditor : Editor
{
    SerializedProperty shootSpeed;

    private void OnEnable()
    {
        shootSpeed = serializedObject.FindProperty("<ShootSpeed>.k__BackingField");
        Debug.Log(shootSpeed.floatValue);
    }

any reasons why shootSpeed is null? dont get confused by the name 😄

#

the property is [field: SerializeField] public float ShootSpeed { get; private set; }

#

the name in debug mode is :

karmic ginkgo
#

check the name in the meta

eager shale
#

in the meta?

#

oh the .meta file in the folder i guess

#
BallController.cs.meta

fileFormatVersion: 2
guid: bc008ace14cc5d3439a6e7f0155996ce
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 
karmic ginkgo
#

no serialized fields?

karmic ginkgo
#

wrong meta

eager shale
karmic ginkgo
#

what i mean is any meta that has serialized data for it

#

like a prefab

eager shale
#

I dont have a prefab with that script

#

I can probably setup one for testing purpose

#
fileFormatVersion: 2
guid: b9d387287738a724b9daed7b4d7e6496
PrefabImporter:
  externalObjects: {}
  userData: 
  assetBundleName: 
  assetBundleVariant: 
#

^ the meta of the prefab with the script on it

karmic ginkgo
#

change that field in inspector, so its serialized

eager shale
#

i did

#

the meta refuses to change

#

i changed my property name to m_MaxScale which works

#

so the problem seems to be the name of the backing field of the auto property

karmic ginkgo
#

your custom inspector is active while youre doing all that?

#

you are in debug mode?

eager shale
#

nice, now it works

#

without anything changing

patent pebble
#

@eager shale you had an extra period in there
"<ShootSpeed>.k__BackingField" nope
"<ShootSpeed>k__BackingField" yes

eager shale
#

god forgive me what i have done

#

thank you SolaireLove

patent pebble
#

SOFTWARE DEVELOPMENT PROCESS:

  1. I can't fix this
  2. Crisis of confidence
  3. Questions career
  4. Questions life
  5. Oh it was a typo, cool
    🙃
eager shale
#

😔

karmic ginkgo
#

I have no idea why this doesnt work.
I have no idea why this works.

patent pebble
idle tree
#

Will this get me the name of the serialized object? x/y how do I get the name of a serialized object?

#

name in this context being the name of the unity component that I know the serialized object is serializing

gilded violet
#

Does anyone know if it's possible to change the options available in "Max size" in the texture importer settings?

I'm hoping to be able to add a size between 4096 and 8192 if possible

#

thanks for any help

idle tree
gilded violet
#

@idle tree Would that be not performant Ram-wise? Basically my issue is that I'm working with the quest 2, and it seems that the system hardware is using more ram in recent updates and pushing my app into crash territory, it's a very custom app so all that really matters is getting as much resolution as possible without crashing

Ideally if I could set a mid-point of 6144 max size somehow hopefully it'd bring the crashing under control

idle tree
gilded violet
#

Yeah I think there isn't really space for in-between sizes here, I can work with 4096 for now, surprisingly a 4k render with max size set to 8k is better looking than a 6k render with max size set to 4k 🤷‍♂️

timid coyote
#

Hello! How can I make _inputActionAsset to show up in the window?

gloomy chasm
#

Sorry to just link docs, but I would basically be just be repeating the info that is there

timid coyote
#

i tried something, but

gloomy chasm
# timid coyote i tried something, but

In this case the EditorWindow is the UnityEngine.Object that contains the field, so you need to pass it to the SerializedObject constructor. You will also need to add the [SerializeField] attribute to the _inputActionAsset field so it will actually be serialized.

#

And then for getting it, .FindProperty(..) you need to pass the string name of the field that is serialized. So in this case _inputActionAsset is the field you are wanting.

timid coyote
#

but im still getting the errors

gloomy chasm
# timid coyote

You are still passing the InputAction to the SerializedObject constructor

#

you need to pass the EditorWindow

#

aka this

timid coyote
#

ty so much, and sorry, im 0 at all the things connected to the cutom editor

gloomy chasm
timid coyote
#

also here i need to write _inputActionAsset = .. before that line right ?

gloomy chasm
# timid coyote yep

Nice! You will also want to cache the SerializedObject instance so it is not recreated every frame.

gloomy chasm
#

Are you familiar with reflection in C#? If so, then this is basically that. If not, then please don't worry about it.

gloomy chasm
timid coyote
#

ty again

gloomy chasm
# timid coyote nope

Then don't worry about. Was just going to use it as a thing to relate the SerializedProperty/SerializedObject to, but if you don't know it then it won't help so don't give it another thought 🙂

mental escarp
#

Good Morning, can somebody help me with this error? I'm using a linux system and already tried to run unityhub as admin, but the error still occurs

mental escarp
#

I was able to solve this. I changed the owner of Unity and UnityHub and all it contains data to my own account (some of the files are owned by root)

vestal sorrel
#

My selection outline stopped working for some reason. I have the Gizmo enabled but still wont show up. What could cause this?

karmic ginkgo
#

maybe color in color settings?

timid coyote
#

Im getting these 2 errors when trying to create scriptable objects from a input action asset, and i dont understand why.

#
private bool IsAssetCreated(InputData[] inputDataList, InputAction inputAction)
        {
            return inputDataList != null && inputDataList.Any(data => data.InputAction == inputAction);
        }```
#

_inputDataInstance = CreateInstance<InputData>();

vestal sorrel
#

The selection outline is gone from my main scene. It still works perfectly in my prototype scene. What is going on? I deleted library folder and rebuilt it still wont work

fast dew
#

Hello, "EditorGUILayout.PropertyField(serializedProperty, new GUIContent(name), false" does not work properly when it comes to arrays/lists past 2019. I want a way to drag and drop into the array/list field but I want to turn off the ability to show children and if possible turn off the array/list size field. is there a way to do that? in 2020+

timid coyote
patent pebble
#

is there a way to exclude a static class from domain reload?
I don't want to turn off Domain Reloading in the entire project, I just want a static class to retain its data

#

i wonder if there's any attribute or something to tell Unity "hey, leave this one alone"

timid coyote
#

how can i modify the scriptable object that i have just created?, because if write inputDataInstance.InputAction = inputAction; before the SO is created, it doesnt assign the input action. I tried also AssetDatabase.SaveAssets(); and AssetDatabase.Refresh();, but nothing

gloomy chasm
#

Asset creation

gloomy chasm
patent pebble
#

i could maybe try to make a hidden scriptableobject and keep the data there

#

don't know if HideFlags works with assets, or just gameobjects

gloomy chasm
#

If you don't save the ScriptableSingleton it will act the same as a SessionState

patent pebble
#

SessionState is too simple to fit my needs

#

but ScriptableSingleton could work

#

never used it before, so I guess it's time to learn

gloomy chasm
patent pebble
gloomy chasm
#
public class MyData : ScriptableSingleton<MyData>
{
  public string SomeValue { get... set... }
  // other serialized values and properties...
}

// In some method in another class...
MyData.instance.SomeValue = "Cool!";
patent pebble
#

@gloomy chasm thanks a bunch, as always! 😊

slim vector
#

does anybody know where i can find the code on how Unity snaps a vertex to a surface on another mesh (V + Shift + Ctrl)? tried finding the code in the VertexSnapping.cs on github (https://github.com/Unity-Technologies/UnityCsReference/blob/master/Editor/Mono/EditorHandles/VertexSnapping.cs) but it doesn't cover the vertex snap to a surface.

GitHub

Unity C# reference source code. Contribute to Unity-Technologies/UnityCsReference development by creating an account on GitHub.

slim vector
#

doesn't that snap the object to a nearby vertex?

#

trying to find the code where it snaps to a surface instead

#

this is what i'm talking about

gloomy chasm
#

You can use HandleUtility.GUIPointToWorldRay(..) I think

slim vector
#

alright

#

then it just snaps the object to whatever the hit point of the ray is?

gloomy chasm
#

Yup

#

Would probably need to filter through the returned colliders because the first one would be the object being moved.

#

I feel like there is a better way to handle this...

gloomy chasm
#

That assumes I remember what HandleUtility.PickGameObject() does...

slim vector
#

will try

#

thanks!

onyx harness
patent pebble
onyx harness
#

Oh it's per session

#

So, no saving

patent pebble
#

I mean, I'm sure I will use the ScriptableSingleton for tools that require the data to survive multiple sessions
But for this particular one I just need it to survive assembly reloads

onyx harness
#

I mean, no saving for the process lifetime, I guess you persist after a Domain reloax

patent pebble
#

yeye

patent pebble
gloomy chasm
#

If you had the FilePath attribute it will be saved between sessions. But otherwise it will only be saved between domain reloads

onyx harness
#

Oh shit, now we can have sub-channel that archives automatically, nice shit

#

I'm even outdated about Discord xD

patent pebble
#

I'm still not used to opening threads in Discord, so I always forget 😅

#

but ideally, what Unity staff wants us to do is open threads for topics whenever possible

#

but the Discord UI for that stuff is still kinda half baked, so it's not great

onyx harness
#

How is your tutorial stuff doing mister Mad?

patent pebble
#

slow lmao

#

i still have a lot of stuff that I need to learn before having enough competency to make a tutorial for it

#

and working on my own projects comes first, that stuff I do in my spare time or when I need a break from my games

onyx harness
#

Well you just learned about ScriptableSingleton :D

patent pebble
#

i wouldn't need to make tutorials for all these editor APIs if Unity had comprehensive documentation... 🙃

#

but I guess this stuff is low priority for them

onyx harness
#

I do need too a backbone, a plan for writing.
I'm sad I had this idea early on, but never committed T_T

#

I could have wrote so many discoveries

patent pebble
#

I've had an idea for a tool for taking notes in the editor that would let you attach notes to pretty much everything.
Put notes on components, put notes on exposed fields, attach notes to GameObjects, have top-level editor sticky notes, etc

#

but I just never got around to make it

onyx harness
#

Interesting idea

#

You can only do that since UIT

patent pebble
#

but I'm not sure

onyx harness
#

Embedded tooltips/tutorials is nice.
But it comes with 1 big downfall and 1 big upfall :D
It is embedded in Unity, and it is embedded in Unity :D

onyx harness
gloomy chasm
#

(Might be good to make a thread for this 😉 )

onyx harness
#

Except altering the code, which is forbidden

#

How do you start a thread

patent pebble
#

Editor notes and Tooltips

onyx harness
#

Embedded tooltip

#

As for now, threads seem quite nice

patent pebble
#

@gloomy chasm hey I was also checking out SessionState out of curiosity
is there any way of checking if a key already exists?

#

all it has is Erase/Get/Set methods

waxen sandal
#

Just use get with w/e you want for the default value

#

It's like editorprefs

#

Oh I guess playerprefs has a haskey

patent pebble
#

SessionState has a problem

#

for numeric and string values you can check with a default value of a very absurd number or string

#

but with bools there's not an option

#

you just get either true or false

waxen sandal
#

I never need that tbh

#

Just a default false is fine

patent pebble
#

Unity uses SessionState internally, so there's no way to know if you are overriding an internal key

#

it usually won't happen, but there's always edge cases

waxen sandal
#

Just prefix it with your assets name then

#

Or your company name or w/e

#

It's not that big of a deal

patent pebble
#

oh lol, I'm so dumb

#

yeah, using a prefix solves any potential problem

#

silly me 😅

upbeat yoke
#

how to draw GUI inside UIElements? i have custom window using UIElements and want to draw inspector with serialized stuff there

slim zinc
#

create the uxml or create the ui elements per code and display them in the window

tame onyx
#
//DroneComponent Script
public class DroneComponent : MonoBehaviour
{
    [HideInInspector] public DroneComponentManager manager;
    public void LinkToManager(DroneComponentManager manager)
    {
        if(this.manager != null)
        {
            this.manager.components.Remove(this);
        }
        this.manager = manager;
        if(manager != null)
        {
            manager.components.Add(this);
        }
    }
}

//DroneComponentManager Script
public class DroneComponentManager : MonoBehaviour
{
    public List<DroneComponent> components = new List<DroneComponent>();
}

//DroneComponentEditor Script
[CustomEditor(typeof(DroneComponent), true)]
public class DroneComponentEditor : Editor
{
    public DroneComponentManager manager;
    public override void OnInspectorGUI()
        DroneComponent myDroneComponent = (DroneComponent)target;        

        var manager = (DroneComponentManager)EditorGUILayout.ObjectField("Link Manager", myDroneComponent.manager, typeof(DroneComponentManager));

        if (manager != myDroneComponent.manager)
        {
            this.manager = manager;
            myDroneComponent.LinkToManager(manager);
        }

        EditorUtility.SetDirty(myDroneComponent);

        base.OnInspectorGUI();
    }
}
#

not sure where to put the serializable field thing so I tried it on all relevant variables and nothing worked

visual stag
#

You use SetDirty after making changes

tame onyx
#

oh

#

ok let me try

tame onyx
#

let me update code

#

there the prev code is updated

visual stag
#

You're also modifying manager, not myDroneComponent

tame onyx
#

oh so both>

visual stag
#

or... maybe not, you're modifying both?

tame onyx
#

I am adding to the component list in manager

#

so yes

#

right?

#

it worked

#

i changed it to this:

        EditorUtility.SetDirty(myDroneComponent);
        if(this.manager != null)
        {
            EditorUtility.SetDirty(this.manager);
        }
#

sweet thanks @visual stag and @wild edge

#

what a weird thing to have to do

visual stag
#

You should really only be dirtying things when changes happen. The SerializedObject/Property and Undo systems are the proper way of handling it. SetDirty is the laziest and least used way

gritty ridge
gloomy chasm
#

The only collections that Unity can serialize is T[] and List<T> (T being the type you want, for example string or Transform, etc.)

gritty ridge
gloomy chasm
#

I would also look in to SerializedObject and SerializedProperty for your editor scripting in the future and use them instead of setting values directly to ensure that changes are saved and support undo

teal timber
#

where should i stick something in an editor script that i want to update based on the position of the gameobject when it's being moved around in the editor? like for example if i want a reference to the closest gameobject of type whatever and they won't move at runtime so i want it to be done when placing the objects in the editor

#

like first i just stuck my logic in Editor.OnSceneGUI but it complained when i tried to use multiple targets and i know that probably isn't the place but i just want something that updates often

#

i guess the "correct" approach would ideally be to hook into some kind of event from the move tool itself or something but i have no clue about that

teal timber
#

or another thing, if i want to keep the default inspector but detect when a value in it was changed and do something based on it?

patent pebble
#

i don't think it was what that person asked

#

@teal timber another way to get notified when the Scene View is interacted with is subscribing to these events
SceneView.beforeSceneGui and SceneView.duringSceneGui

#

your question is a little bit confusing, can you clarify what issues you're having?
Are you having trouble getting the GameObject that's being moved?
Are you havin problems when multiple GameObjects are selected?

#

but it complained when i tried to use multiple targets
are you getting the "Multi-object editing is not supported? when you select multiple GameObjects with a custom editor?
if that's the case you can use the [CanEditMultipleObjects] like so:

[CanEditMultipleObjects]
[CustomEditor(typeof(MyMonoBehaviour))]
public class MyCustomEditor : Editor
{
    private void OnSceneGUI()
    {
        Debug.Log($"{GetType()} Calling: OnSceneGUI()");
    }
}
timid coyote
#

am i getting Type mismatch because i assign a instance to a field of a created asset?

public void SetInputAction(InputActionReference newInputAction) => inputAction = newInputAction;```
gloomy chasm
timid coyote
gloomy chasm
timid coyote
#

if i hover over the type mismatch nothing shows up

gloomy chasm
#

Oh that type of type mismatch

#

Not sure what to tell you tbh. Time for some debug.logs I guess

timid coyote
dreamy viper
#

Hi,
I have properties (Dark Square Prefab and Light Square Prefab) of type "Square". It works well but the Select window from the Inspector doesn't show the prefabs from my assets of type "Square". (but it show the gameobjects of type "Square" in the Scene Tab).

gloomy chasm
#

If you want to reference a prefab it has to be by GameObject

#

This I think changed in 2021.2 if you are using the new search window

dreamy viper
#

I see. Thank you @gloomy chasm

gloomy chasm
timid coyote
gloomy chasm
timid coyote
gloomy chasm
timid coyote
#

but i dont know any other way of creating an instance of a SO, because InputActionReference is a SO too

soft zenith
#

hi people, i'm implementing my own 2D Animator solution, and everything is working fine, but i wan't to be able to send events on certain frames, the problem is that i can use a sprite on EditorGUI.ObjectField but i can't use a UnityEvent, does anyone know how can i implement a UnityEvent on my editor ?

#

i wan't to somehow be able to show the events for certain frames, so i have a class called SpriteAnimationFrame that holds information about sprites and events, however i'm not being able to show the unityevent in the inspector just like i'm doing with my sprites

#

that's the spriteanimationframe class

#

and that's how i' drawing the properties

tough cairn
#

is there a way to get the Pixel Per Unity value from an Input Texture2D after that import settings were applied ?

tough cairn
#

nvm just realized i need to use sprites instead of texture2d references in the editor

#

textureSprite.pixelsPerUnit

gloomy chasm
#

Serialized Properties

viral nimbus
#

Hey all. I have an editor question... I have a prefab and when I drop it into a scene, I'd like for the editor to prompt me with some sort of "fill in these required fields" or something so I can set the prefab up appropriately in the scene.

Is this a thing?

#

Or, conversely, when I change the name of the GameObject in the editor, can I make a macro/script run to adjust stuff?

civic shore
#

Seems like Unity really wants me to use VS or VSCode. Setting up Emacs is a real pain

patent pebble
dark dome
#

Hello

#

Hello I have a two scripts that create scriptable objects. One creates TileClass that is than stored in TileAtlas. Every time I wanna add new class such as public TileClass stone; I have to go to script editor and add the new class. Is it possible to create editor extension that would do do this "for me", so that I would click button in editor, write name of a new class and it would be added. Rather than having to do it manualy.

slim zinc
#

use arrays

civic shore
#

I can't get Omnisharp to work at all, I've been at it for 3 hours, installing and uninstalling .NET versions, logging in and out, reinstalling Unity, Omnisharp, Mono, VSCode...

#
[fail]: OmniSharp.MSBuild.ProjectLoader
        The reference assemblies for .NETFramework,Version=v4.7.1 were not found. To resolve this, install the Developer Pack (SDK/Targeting Pack) for this framework version or retarget your application. You can download .NET Framework Developer Packs at https://aka.ms/msbuild/developerpacks```
```log
[fail]: OmniSharp.MSBuild.ProjectManager
        Attempted to update project that is not loaded: c:\Users\User\My project\Assembly-CSharp.csproj```
I've followed the instructions in [#854851968446365696](/guild/489222168727519232/channel/854851968446365696/) , on Microsoft's website, on Unity's website, and on VSCode's website, along with what the error said
#

I've read countless discussions with this exact error in the server and no one ever reached a conclusion or found a solution. In the rare occasions that someone managed to fix it, they don't specify clearly

#

I've never used Windows before and I'm genuinely confused

#

I've also tried to set all of this up with Emacs, with no avail

#

I've also tried with VSCodium

civic shore
#

I've tried multiple tools to remove this version, but none of them solved the 4.7.1 installer's error

#

I have logged out and rebooted the computer multiple times

visual stag
#

Are you installing the developer pack, not the runtime?

#

You want the pack

civic shore
#

You were right, I was using the runtime, not the dev pack

#

Auto-complete now works well!

#

It even works on Emacs! Hooray!

dark dome
# slim zinc use arrays

it doesn't work so well with arrays. I like that I can acess this as TileClass.stone instead of looping trough array looking for stuff

#

I could write a function right, that would go like Function(TileAtlas, name of what you are searching for)

#

but this still seems superior option

slim zinc
# dark dome but this still seems superior option

It's not easily scalable, you dont need the variable name to be different, only the exposed identifier, it requires a lot of writing.

That doesn't seem superior to me when arrays fix all the above

waxen sandal
#

Sure, you can generate that class

#

Arrays have terrible UX for that usecase

#

You end up makign a GetTile method that takes a string which you cn then typo

#

Or you need to make constants that contain the name of the tile and then we're back to the same problem

waxen sandal
#

And trigger a recompile

karmic ginkgo
waxen sandal
#

No they're not

karmic ginkgo
#
class TileWrapper
{
  public enum TileType tileType;
  public Tile tile;
}

consider array of these instead

waxen sandal
#

They can easily have different TileAtlasses with different tiles for biomes

karmic ginkgo
#

you have editor assigned tile type, where you can designate as much stone tiles as you want

slim zinc
karmic ginkgo
#

you can later query your collection and for example make random selection from all stone tiles you placed in

#

you can also validate it based on your criteria, i.e. each collection should have 1 of each tile type etc

waxen sandal
#

The only slowness is the compilation, considering this is probably not done very often it's fine

waxen sandal
slim zinc
#

It's not fine if there are better options

waxen sandal
slim zinc
#

They are fast

waxen sandal
#

Yes, just adding one element is fast. Looking up an element is slower (arguably not much depending on how long that list is going to get and how often they are querying it)

slim zinc
#

Just index?

waxen sandal
#

So each tile is a specific index..?

karmic ginkgo
#

array[TileType.stone]

slim zinc
#

They're arrays after all

waxen sandal
#

We're making the UX worse, and still not solving the problem (we've actually introduced the problem!)

slim zinc
#

The ux is not under consideration

waxen sandal
#

??

#

The whole point is that the UX of adding a new element is currently bad

#

It's cumbersome to edit code to add an extra element

karmic ginkgo
#

ah right

slim zinc
#

Because how they do it is bad

karmic ginkgo
#

so i solve the original problem simply with odin DropdownValue

#

you can supply enumerator which will locate anything you want, for example instances of TileClass assets

#

and display a dropdown which to select, acting as enum so you dont have to weave it

slim zinc
#

Pretty much, just write a nice simple custom editor

karmic ginkgo
#

guess you can do something similar rather simply

waxen sandal
#

That's a better solution but still, you have to end up dealing with an array at runtime to find the element you want

slim zinc
#

And you don't need Odin for that necessarily

waxen sandal
# slim zinc Index still

That's not a good solution, it's error prone unless you write code to validate that a certain index is always a certain tile in which case you'll end up having to change code again to set that up

#

And edit code to add the index property in the first place

waxen sandal
slim zinc
waxen sandal
#

Sure there's a (imo) small annoyance when adding a new property (compilation time)

#

But other than that, it's easy and fast to access

karmic ginkgo
#

it also has to be a dll as not to break in case of compiler errors, should also be able to handle renaming/removal, probably should do it automatically on asset changes

#

thats a rather big amount of work

waxen sandal
slim zinc
slim zinc
waxen sandal
waxen sandal
waxen sandal
#

And I'm going to lunch

slim zinc
slim zinc
karmic ginkgo
slim zinc
#

Well I guess you could do some code gen, but you'd then also end up with potentially a lot of fields in a single script, which I wouldn't say is ideal

karmic ginkgo
#
// codegen ?
static class TileTypes
{
  public const int Stone = 931239;
  ...
}

class TileAtlas
{
   [SerializeField]
   List<TileData> tiles;
  
   [Serializeable]
   class TileData {
      public Tile reference;
      // any additional data for queries
    }
}


tileAtlas.GetRandom(TileTypes.Stone);
tileAtlas.AllOfType(TileTypes.Grass);
shrewd parrot
#

Hello! I have a question about changing variable type based on an enumerator. The main concept is that if I changed the enum to Name, component's type should be set to TMPro and should i change the enum to Icon the component's type should be Sprite. I am very new to editing the inspector so I do not know if this is possible or not and if it is indeed not possible, just point me in the right direction. Thank You!

slim zinc
shrewd parrot
slim zinc
#

you need to hide / show different fields based on the enum. there's lots of examples for that out there

patent pebble
#

did you make that inspector? or do you know nothing about implementing custom Editors?

shrewd parrot
#

that is the default inspector. Its just a class in an array. To make it designer friendly I decided to try and swap types or hide/show relevant fields to the enum

patent pebble
#

ok start here

#

instead of making a custom Editor you could also use a PropertyDrawer, but it's a little bit more complicated

#

doing a PropertyDrawer would be better since it draws on every element of an array

#

if you make a custom Editor you are making the entire inspector, so you have to implement the array yourself and all that

#

@shrewd parrot lets assume the class you use in that array is named Display,
you can make a PropertyDrawer that targets the type Display,
and every time Unity needs to draw that it will use the logic in your PropertyDrawer

#

instead of using the default UI, which is what you're getting now

shrewd parrot
#

hmm okay

#

so i could just perhaps use a switch statement and check if the enum Display Type is of a certain type (like Name) and then display the relevant feilds (like TextMeshProGUI)?

patent pebble
#

it takes a Type as a parameter, which will make the field only accept objects of that type

shrewd parrot
patent pebble
#

@shrewd parrot on the PropertyDrawer documentation page scroll down to see the xamples that use IMGUI, instead of the UI Elements

shrewd parrot
#

yep i see it

hushed fern
#

I'm learning how to make these for a project and i was just wondering what are some simple yet effective things i can make to show off what i've learned

patent pebble
#

I needed to make a serializable version of a Dictionary for one of my tools
the tool only ever has to deal with the following types:
Bool, Float, Int, String, Vector3, Int[]

Because Unity doesn't serialize nested collections, I ended up having to use a wrapper for the int[] type like this:

[Serializable]
public class IntArrayWrapper : IConvertible
{
    [SerializeField]  public int[] Array;

    public IntArrayWrapper(int[] intArray)
    {
        Array = intArray;
    }

    public object ToType(Type conversionType, IFormatProvider provider)
    {
        return Convert.ChangeType(Array, conversionType);

    }
}
#

And use it in my manual serialization like so:

[Serializable]
public class SerializableDict<TKey, TValue> : Dictionary<TKey, TValue>, ISerializationCallbackReceiver
{
    [SerializeField] private List<TKey> keys = new List<TKey>();
    [SerializeField] private List<TValue> values = new List<TValue>();
    [SerializeField] private List<IntArrayWrapper> intArrayWrappers = new List<IntArrayWrapper>();

    public void OnBeforeSerialize() // Save the dictionary to lists
    {
        keys.Clear();
        values.Clear();
        intArrayWrappers.Clear();

        foreach (KeyValuePair<TKey, TValue> pair in this)
        {
            keys.Add(pair.Key);

            if (pair.Value is int[])
                SerializeValuesAsArrays(pair);
            else
                SerializeValues(pair);
        }
    }

    public void OnAfterDeserialize() // Load dictionary from lists
    {
        this.Clear();

        if (intArrayWrappers.Count != 0)
            DeserializeValuesAsArrays();
        else
            DeserializeValues();
    }

    private void SerializeValues(KeyValuePair<TKey, TValue> pair) // bool, float, int, string, Vector3 
    {
        values.Add(pair.Value);
    }

    private void SerializeValuesAsArrays(KeyValuePair<TKey, TValue> pair) // int[]
    {
        int[] array = (int[])Convert.ChangeType(pair.Value, typeof(int[]));
        intArrayWrappers.Add(new IntArrayWrapper(array));
    }

    private void DeserializeValues() // bool, float, int, string, Vector3 
    {
        for (int i = 0; i < keys.Count; i++)
            this.Add(keys[i], values[i]);
    }

    private void DeserializeValuesAsArrays() // int[]
    {
        for (int i = 0; i < keys.Count; i++)
            this.Add(keys[i], (TValue)Convert.ChangeType(intArrayWrappers[i], typeof(TValue)));
    }
}
#

I wonder if there's a better solution

#

this one seems to be too cumbersome, even though it appears to work

#

I've never done any custom serialization in Unity, other than the very basics, so I don't really know if this is a good approach or not 😅

#

this is what I'm making, a way of displaying SessionState data

onyx harness
#

Looks fine to me, wonder how it behaves in high scale.
Also at if (pair.Value is int[])
I would prefer typeof(TValue) == typeof(int[])
Or maybe even move it out to its own foreach for performance reason

#

you did it already when deserializing

oak belfry
# patent pebble I needed to make a serializable version of a Dictionary for one of my tools the ...

idk if this is late but i have the exact same issue right now and i think i found a working solution but i cant get it to work properly yet -
https://github.com/github-for-unity/Unity/blob/master/src/UnityExtension/Assets/Editor/GitHub.Unity/SerializableDictionary.cs

GitHub

GitHub for Unity. Contribute to github-for-unity/Unity development by creating an account on GitHub.

patent pebble
oak belfry
#

also looking at your issue now it might not be what you are looking for but whatever i guess 🤷‍♂️

#

maybe it helps a little

patent pebble
#

Looks fine to me, wonder how it behaves in high scale.

In what sense? adding big amounts of values?
or displaying large amounts of values in the UI?

oak belfry
patent pebble
#

@oak belfry yeah I've looked at a couple of serializable dictionary implementations

#

but they seemed too bloated, because they want to support all use cases

#

I wanted to implement mine as light as possible, because I know the data I need to serialize will never change type

#

it's gonna be always the same

#

Bool, Float, Int, String, Vector3, Int[] is all I will ever need to serialize

oak belfry
#

also since you know a bit about this, why does my editor give this error
SerializationException: there are 1 keys and 0 values after deserialization. Make sure that both key and value types are serializable.
SerializableDictionary`2[TKey,TValue].OnAfterDeserialize () (at Assets/Scripts/GenericDictionary.cs:40)

patent pebble
#

@oak belfry i have a similar safety check in mine too. It's usually caused by having types that are non-serializable

oak belfry
patent pebble
#

like nested collections, classes without the [Serializable], etc

oak belfry
#

for some reason it kinda works when i remove this

public void OnBeforeSerialize()
    {
        keys.Clear();
        values.Clear();
        foreach (var pair in this)
        {
            keys.Add(pair.Key);
            values.Add(pair.Value);
        }
    }
#

well the keys.clear and values.clear

patent pebble
#

@oak belfry what types do your dictionaries contain?

oak belfry
#

well i want to have gameObject + KeyCode, but i tried string + int too just to check

#

still didnt work tho ._.

patent pebble
#

maybe that borks the serialization?

#

your error is telling you you have a key that doesn't have a value associated to it

oak belfry
#

oh

#

i didnt understand the error then

#

that helps thanks

#

will work on it

patent pebble
#

debug everything and see what's happening

onyx harness
patent pebble
#

brb

onyx harness
#

Just a thought, no need for justification 🙂

patent pebble
#

@onyx harness it took 10 seconds to serialize 10k dictionaries with 5 elements in each dictionary

#

so around 1 ms per dictionary

#

and generated 456 bytes of garbage per dictionary

#

i have no clue if that's good or bad, because I have no perspective on this topic 😅

onyx harness
#

Sounds like a lot X)

#

You should precalculate the length, an use array instead of List

gloomy chasm
#

There is no way to make it lighter as far as I know.

patent pebble
patent pebble
#

i also produce no garbage on deserialization, but still a little bit on serialization

#

112 bytes per dictionary

onyx harness
#

Hehehe

patent pebble
#

@gloomy chasm your Dictionary had a little bit more of a performance hit

#

probably due to all the checks and stuff you do

gloomy chasm
patent pebble
#

with

gloomy chasm
# patent pebble with

Yeah I would expect as much. It is required in order to support duplicate values nicely in the property drawer

#

I was thinking of adding a 'editor only' dictionary which is just the serialization part without property drawer support

patent pebble
#

@gloomy chasm after trimming down your implementation I ended up with this

[Serializable]
public class UDictionary<TKey, TValue> : Dictionary<TKey, TValue>, ISerializationCallbackReceiver
{
    [SerializeField] private SerializableKeyValuePair[] _serializedPairs;

    [Serializable]
    private struct SerializableKeyValuePair
    {
        public TKey key;
        public TValue value;

        public SerializableKeyValuePair(KeyValuePair<TKey, TValue> pair)
        {
            key = pair.Key;
            value = pair.Value;
        }
    }

    public void OnBeforeSerialize()
    {
        _serializedPairs = new SerializableKeyValuePair[this.Count];
        int index = 0;
        foreach (var pair in this)
        {
            _serializedPairs[index] = (new SerializableKeyValuePair(pair));

            index++;
        }
    }

    public void OnAfterDeserialize()
    {
        this.Clear();
        foreach (var pair in _serializedPairs)
        {
            this[pair.key] = pair.value;
        }
    }
}
gloomy chasm
patent pebble
#

your example works a lot better because you wrap the TKey and TValue in the SerializableKeyValuePair
in my original approach I was struggling because i kept the list of TKey and TValue on the top level class
so I was having problems with nested collections

#

i had to implement a Wrapper class with the IConvertible interface to be able to cast to generic types

#
[Serializable]
public class IntArrayWrapper : IConvertible
{
    [SerializeField]  public int[] Array;

    public IntArrayWrapper(int[] intArray)
    {
        Array = intArray;
    }

    public object ToType(Type conversionType, IFormatProvider provider)
    {
        return Convert.ChangeType(Array, conversionType);

    }

    //... a bazillion more conversion methods required by the interface
}
#

it was a pretty annoying and ugly solution

gloomy chasm
patent pebble
#

i've seen a lot of examples online and I don't think a lot of them use your approach

#

I've seen serializable dictionary implementations WAY more bloated than yours

gloomy chasm
#

(I checked, it isn't legal as far as I can tell)

gloomy chasm
#

It is literally why I made my own, not a single one had a good way of handling it all, and I looked at every single one I could find on github lol

patent pebble
#

nice

#

seems like most of your stuff works great and is lightweight

#

@gloomy chasm thanks for all the help 💙

gloomy chasm
patent pebble
#

you shared it a while back

#

💪 so nice

gloomy chasm
#

Oh yeah, well glad you are liking it 😄

patent pebble
#

all your SerializedProperty/SerializedObject stuff was of great help and served as a great example to start writing my own extension methods for some use cases

stable crane
#

how could i add this derived class in there

#

im open to switching the way i do things but id rather avoid having tons of ScriptableObjects or storing it in a c# script / text file

#

I've thought of having every property on the base class and then an enum for the type, hiding certain properties depending on the type however i dont know if thats even possible

#

initially i tend to avoid using external libraries like this especially smaller ones but this one seems quite popular and has a lot of interesting features, hopefully it works well

waxen sandal
timid coyote
#

Ups

fickle quarry
#

Okay need some help with this.
I use a custom render pipeline to support a specific Oculus tech (SpaceWarp) and my current shaders don't support it.

If I build for android I want to change the shaders of all materials in my game to the simple lit shader. At runtime I just do .shader = simpleLitShader, but that gives graphical glitches because of spacewarp.

Now I am trying to do it in the build process, using the code below, but the materials stick with the old custom shader and not simple lit.
I also tried .material instead of sharedMaterial

Does anyone know if me or my code does something wrong?


public class ShaderSwitch : IProcessSceneWithReport
{
    public int callbackOrder => 0;

    public void OnProcessScene(Scene scene, BuildReport report)
    {
        foreach(GameObject go in scene.GetRootGameObjects())
        {
            var renderer = go.GetComponent<Renderer>();
            if (renderer)
            {
                var tex = renderer.sharedMaterial.GetTexture("_Diffuse");
                if (tex)
                {
                    Debug.Log("did it for " + renderer.material.shader.name);
                    renderer.sharedMaterial.shader = Shader.Find("Universal Render Pipeline/Lit");
                    renderer.sharedMaterial.mainTexture = tex;
                }
            }
        }
    }
}
waxen sandal
#

Probably need to Undo.RecordObject before changing it

#

Since you're changing the asset and not just the scene

fickle quarry
waxen sandal
#

sharedMaterial probably references an asset

#

If it doesn't then you're doing something unusual

fickle quarry
waxen sandal
#

Try Undo.Recordobject(renderer.sharedMaterial) before changing it

fickle quarry
#

Yeah but I gotta give it a new name as well

waxen sandal
#

Just do "Change material" or somethin

fickle quarry
#

Didn't change it. Just seems to not apply

waxen sandal
#

I'm not sure if that callback is intended to change assets/scenes but rather validate that things are correct

fickle quarry
#

I am not sure either that's why I ask here haha

fickle quarry
#

So if anyone else knows it for sure please let me know (:

fickle quarry
bitter barn
#

No, but maybe post in this thread to remind the devs that users would like features for upgrading data: https://forum.unity.com/threads/script-data-upgrade.427767/

The only way is to manually keep track of your references. In this case it would probably mean you would have to rename references directly in the YAML (we've built some basic internal tools for this sort of thing) or fix the references via some other editor process like finding them in code etc.

spark lichen
#

hey guys, can anyone explain why the toggles are all joined as rows (.gif image after code)?
this is the property drawer code:

[CustomPropertyDrawer(typeof(StructureLayout))]
public class StructureLayoutDrawer : PropertyDrawer
{
    const int maxStructureLength = 5;
    const float checkboxSize = 16.0f;
    const float lineSize = 20.0f;

    bool foldout;

    // test
    bool[,] toggleValues = new bool[maxStructureLength, maxStructureLength];

    public override void OnGUI(Rect pos, SerializedProperty prop, GUIContent label)
    {
        label = EditorGUI.BeginProperty(pos, label, prop);

        pos.height = lineSize;
        foldout = EditorGUI.Foldout(pos, foldout, label);

        pos.y += lineSize;

        if (foldout)
        {
            for (int i = 0; i < maxStructureLength; i++)
            {
                for (int j = 0; j < maxStructureLength; j++)
                {
                    toggleValues[i, j] = EditorGUI.Toggle(pos, toggleValues[i, j]);
                    pos.x += checkboxSize;
                }
                pos.x -= checkboxSize * maxStructureLength;
                pos.y += checkboxSize;
            }
        }

        EditorGUI.EndProperty();
    }

    public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
    {
        return base.GetPropertyHeight(property, label) + checkboxSize * maxStructureLength;
    }
}
waxen sandal
#

I wonder if toggles reserve more space in that row to make it easier to use

#

Best to check with the imgui debugger

bitter barn
#

This is what I would do and it seems to not have your issue (I'll think about why that may be caused by your code):

toggleRect.width = 16;
toggleRect.height = 16;

for (int row = 0; row < 5; row++)
{
    for (int column = 0; column < 5; column++)
    {
        toggleValues[column, row] = EditorGUI.Toggle(toggleRect, toggleValues[column, row]);
        toggleRect.x += toggleRect.width;
    }
    toggleRect.y += toggleRect.height;
    toggleRect.x = pos.x;
}```
#

Ah well, you forgot to set the width of the rect for the toggle. It seems to render correctly because there is some min size within the control, but you need to set the width to a valid value for the layouting/mouse check code to work.

#

For example, just do: pos.width = checkboxSize;

bitter barn
spark lichen
#

@waxen sandal @bitter barn Thank you! You guys were right, I just had to adjust the Rect width :)

teal palm
#

Hello! Has anyone used Firebase Analytics in their Unity projects? I'm trying to find an alternative to Unity Analytics and would like to see if Firebase has any cons

shadow moss
#

This is an array of BuildObject (not a scriptable object). I'm attempting to override the inspector inside each element to add a button to the Action Data field.
I have added a script:

[CustomEditor(typeof(BuildObject)]
[CanEditMultipleObjects]
public class BuildObjectEditor : Editor {
  public override void OnInspectorGUI() {
    GUILayout.Label("Hello");
  }
}

However, this isn't working

#

How can I do this without completely reimplementing the reorderable list implementation?

patent pebble
#

@shadow moss a custom Editor draws the entire inspector for a component

#

if you want to affect individual fields you can use a PropertyDrawer

shadow moss
#

Oh, so a property drawer then?

#

Excellent, thank you

patent pebble
#

yeye

#

on a list, the PropertyDrawer will target each element of the list, instead of the list itself

shadow moss
#

If I completely override OnGUI, I was expecting the inside of the foldout to be blank. However, I see that the entire element is blank.

#

I'm looking at ReorderableList.cs, but I don't see much in terms of foldout

patent pebble
shadow moss
#

That makes sense

patent pebble
#

you can override PropertyDrawer.GetPropertyHeight and return a height of 0, but I think the list's drag handles will still draw for each element

#

what are you trying to do? why do you need the list to be empty?

shadow moss
#

I'll try returning a height of zero

#

I'm trying to just add a button to ActionData field (bottom)

#

Each element is of type BuildObject, and so I have a property drawer for BuildObject

#

I hope that makes sense

patent pebble
#

yes

#

just draw all the properties with PropertyFields and then add a button at the end

#

or maybe you can just call the base OnGUI and then do the button after that

shadow moss
#

I tried the latter, but if I call base.OnGUI, then I get a message stating that the GUI is not implemented

patent pebble
shadow moss
#

Doing that now

patent pebble
#

@shadow moss ah sorry I just realized you can just use one PropertyField for the target property of the drawer

#

you don't need to do it for every single child property

#

just pass a bool to let the field know it has to include children

#
EditorGUI.PropertyField(position, property, label, true);
shadow moss
#

Oh, interesting

patent pebble
#

@shadow moss here's an example

[CustomPropertyDrawer(typeof(SomeClassForPropertyDrawer))]
public class SomePropertyDrawer : PropertyDrawer
{
    private readonly float buttonHeight = EditorGUIUtility.singleLineHeight;
    private readonly float spacing = EditorGUIUtility.standardVerticalSpacing;

    public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
    {
        float defaultHeight = EditorGUI.GetPropertyHeight(property, label, true);
        return defaultHeight + spacing + buttonHeight;
    }

    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        EditorGUI.PropertyField(position, property, label, true); //Draw property with children

        Rect buttonRect = new Rect
        {
            x = position.x,
            y = position.yMax - buttonHeight,
            width = position.width,
            height = buttonHeight
        };

        // Intend the rect to match with the property's intentation
        EditorGUI.indentLevel++;
        buttonRect = EditorGUI.IndentedRect(buttonRect);
        EditorGUI.indentLevel--;

        if (GUI.Button(buttonRect, "Some button"))
        {
            // Button logic
        }
    }
}
#

dealing with the height is a little bit annoying because you have to manually account for the extra stuff you add

#

I'm not an expert on custom drawers so there's probably cleaner ways of doing this, but for basic stuff this seems to be fine

shadow moss
#

Wow, thank you

#

I'm looking over it