Serialize Types in the Unity Editor using Reflection

Sdílet
Vložit
  • čas přidán 28. 08. 2024

Komentáře • 88

  • @git-amend
    @git-amend  Před 6 měsíci +7

    Hey everyone, I hope you find this Unity hack useful. Bonus challenge: add implicit operators to the SerializableType class (solution is in the code gist)! 👍

    • @Legionope
      @Legionope Před 4 měsíci

      Any possibility for this to work with Unity 2019? I'm getting errors in my visual studio saying that the C# version I have (Community 2022) doesn't support feature "not pattern".

    • @git-amend
      @git-amend  Před 4 měsíci +1

      @@Legionope You could modify the code to be compatible with C# 7.3 by replacing the "not pattern" and other newer features with older syntax. For example, if you have something like if (x is not MyType), you could change it to if (!(x is MyType)).

    • @Legionope
      @Legionope Před 4 měsíci

      @@git-amend But how would I go around "IsGenericType", a feature of 'recursive patterns' not being available?

  • @volodymyrdotsenko4490
    @volodymyrdotsenko4490 Před 6 měsíci +5

    As soon as I learned how to serialize type in Unity I just can't stop) some things become so easy to implement without coding and if there is coding involved it's like so much simpler and cleaner. Not to mention a lot of features can be configured straight in editor now! Very long type list can be solved using AdvancedDropdown (that one is used with Add Component button in Inspector, and is with search text field built in!)

    • @git-amend
      @git-amend  Před 6 měsíci +2

      That's an excellent point about the Advanced Dropdown - I forgot about that one!

  • @poiop890
    @poiop890 Před 6 měsíci +8

    Wow, this is so useful, I feel like this should be base kit. I ran into a problem of needing to select types in editor, but solved it lazily by just making a string input that you need to actually type in that on deserialization is converted into a type, but this can create so many problems. Your solution is superb, I'm certainly "borrowing" it for my project😅 love your videos❤

    • @git-amend
      @git-amend  Před 6 měsíci +2

      Right on, so glad to read your comment!

    • @git-amend
      @git-amend  Před 6 měsíci

      @@moreicestreamingAs far as I know, Odin does not have built in support to serialize Types - only instances of Types. Correct me if I'm mistaken.

  • @V-post
    @V-post Před 6 měsíci +1

    You cover more advanced topics for game dev and unity in a clear and succinct way which is hard to find. So much better than “make your first game” walk throughs. Keep up the good work.

  • @Utamaru56
    @Utamaru56 Před 6 měsíci +1

    Thanks for the video. Really cool stuff. I've done something similar for a card game I've worked on where I had an editor for cards. Different card types had different action types, which I filtered using Unity's built-in TypeCache class in a similar to your attribute manner. And then I recieved list of constructor parameters that represented parameters for a card action (damage, heal amount, etc.). Possibilities with reflection are endless.

  • @Anvelir
    @Anvelir Před 6 měsíci

    A transition from Junior to Middle for me is on Reflection, it is powerful yet complicated.
    Thank you for this! Extremely valuable.

  • @chorong7351
    @chorong7351 Před 5 měsíci

    Thank you for sharing your own advanced techniques that are hardly found in nowhere

  • @David-gu8hv
    @David-gu8hv Před 6 měsíci +1

    Hoo, I have more to learn than I realized! Nice, thanks!!!
    Love deep tech!

    • @git-amend
      @git-amend  Před 6 měsíci +1

      Great! Glad to hear it!

  • @yashaswiification
    @yashaswiification Před 6 měsíci

    thank you for this, boiling down the hard concept in simple language and making us understand. i went through the video couple of times. probably i need to go through another couple of times to get familiar with the concept and implement on own. really really thanks a ton. by regularly making this videos and teaching us new concepts all the time.

  • @tiggleiggle6682
    @tiggleiggle6682 Před 10 dny

    Use it all the time now. Thank you!

  • @BigDaddyGameDev
    @BigDaddyGameDev Před 6 měsíci +1

    I've always wondered how this works, and now I finally understand!
    Who is this guy?

  • @alexandre2bi554
    @alexandre2bi554 Před 6 měsíci +1

    Hey, nice video again, keep the format you have with the intro, the full explanation and the showcase on each step, it really helps and many youtuber doesn't do it properly i think !
    Maybe a more visual/graphic in the middle could help as sometime it's hard to follow you ! :) (or maybe i am not enough good haha)

  • @danixadem
    @danixadem Před 6 měsíci

    Great topic to cover. Hope to see more tutorials like that one !!

  • @johnnydoe6696
    @johnnydoe6696 Před 6 měsíci

    So funny, I just rolled my own SerializedType solution a few weeks ago using ISerializationCallbackReceiver. Was making an attribute based runtime console command system and needed to cache relevant types after compilation to avoid searching through domain assemblies at runtime (very expensive). Even used the implicit operator. Great video btw.

    • @git-amend
      @git-amend  Před 6 měsíci

      Hey thanks! Sounds like an good usecase!

  • @MarushiaDark316
    @MarushiaDark316 Před 6 měsíci

    This is huge and would have been so helpful for a game jam project I was working on months ago in which I was building a train simulator and needed to get the types of cars from a dropdown in the Inspector, only to find out it couldn't do that natively. I could also see this being useful for Falling Sand simulator or anything that has a lot of child classes.

    • @git-amend
      @git-amend  Před 6 měsíci

      Thanks for sharing that example, I'm sure a lot of viewers are eager to hear about usecases.

  • @nexusplus4960
    @nexusplus4960 Před 6 měsíci +2

    I think You will get 100k subs very soon.

  • @sangsangwoo378
    @sangsangwoo378 Před 6 měsíci +1

    Thanks for the great tutorial video. Could you please create another tutorial that covers a specific use-case scenario?

    • @git-amend
      @git-amend  Před 6 měsíci

      If it comes up in another video, I will make note of it. My current use case is that all the states of my state machine are created at run time, but I wanted to expose a Type to the Editor so that I can make a logical choice about that type, such as if (IState state is Type) then...

  • @ryaz4704
    @ryaz4704 Před 6 měsíci

    I used a scriptable object as a type factory. It works but needs so many cs files for each type I wanna serialize. And there's no need to create more than 1 instance of those factories. So seeing your video just now blew my mind.

  • @NadjibBait
    @NadjibBait Před 6 měsíci

    Great video as always! Using Reflection combined with Custom Attributes for tools is awesome and I do it all the time (enums auto-generation, localizable strings extraction...). Small note about "InheritsOrImplements" extension method, why not just use the built-in one-liner typeof(baseType).IsAssignableFrom(type)?

    • @git-amend
      @git-amend  Před 6 měsíci

      Thanks! The built in method is indeed faster, but it only checks concrete types, whereas the custom extension method checks both concrete implementations as well as generic type definitions.

  • @davicro8817
    @davicro8817 Před 5 měsíci

    Really great video! I had a question though, how are you subscribing to the events using a Type rather than generics? Is this event bus very different from the one you showed in your previous video?

    • @git-amend
      @git-amend  Před 5 měsíci +1

      It's more for making logical decisions about Types than subscribing to instances of Types directly. So, if you had a list of events being used in a particular class, you could make a choice about which one to use. If necessary, you could also instantiate a new instance of an event using the Type of course, but I would say that's a last resort since it's resource intensive to do so at runtime.

    • @davicro8817
      @davicro8817 Před 5 měsíci

      @@git-amend Very insightful, thank you

  • @bazzboyy976
    @bazzboyy976 Před 2 měsíci

    Hey boss, great video. Is there any reason you don't use the TypeCache utiltiy in the Editor library for getting types? It's supposedly faster... or atleast its less code.

  • @kevin41307
    @kevin41307 Před 6 měsíci

    great tutorial!!

  • @asgorathalpha8316
    @asgorathalpha8316 Před 6 dny

    This is actually super close to what I want to do with an achievement system and it's amazing. The only thing I can't figure out is how I could expose variables depending on the selected type. Like achievement A has a string input and achievement B has an int input. How would you go about showing those variables in the editor?

    • @git-amend
      @git-amend  Před 6 dny +1

      You might need to build a custom editor for something like that, and then when the type value changes you can update the inspector to show specific fields.

    • @asgorathalpha8316
      @asgorathalpha8316 Před 5 dny

      @@git-amend What would you recommend I look up to help me with this? I know nothing about customizing editors

    • @git-amend
      @git-amend  Před 5 dny +1

      @@asgorathalpha8316 Go subscribe to Warped Imagination and then watch this too: czcams.com/video/ckke6tvZycQ/video.html

    • @asgorathalpha8316
      @asgorathalpha8316 Před 5 dny

      @@git-amend thanks

  • @yummybunny7351
    @yummybunny7351 Před 6 měsíci

    Good video!
    0:40 what plagin do You use for script creation?

    • @git-amend
      @git-amend  Před 6 měsíci +1

      This is a free tool from Infinity Code: assetstore.unity.com/packages/tools/utilities/project-context-actions-267429

  • @user-ef4vl9ys5m
    @user-ef4vl9ys5m Před 5 měsíci

    Any idea of serialize System.Type? I'm trying to use this Serialize Types to construct a unsafe Attribute Class, it contains the offset of class property and it's class Type. However I have trouble in saving the Type of class in editor mode!

  • @damonfedorick
    @damonfedorick Před 6 měsíci

    Nice, inventory time.

    • @git-amend
      @git-amend  Před 6 měsíci +1

      Working on it now, coming soon!

  • @pjarnfelt
    @pjarnfelt Před 6 měsíci

    OdinSerializer has an ImplementsOrInherits where the code is simply public static bool ImplementsOrInherits(this System.Type type, System.Type to){return to.IsAssignableFrom(type);} using the System's type IsAssignableFrom. Is this less performant or are there any other concerns with this implementation?

    • @git-amend
      @git-amend  Před 6 měsíci +1

      That's a good question. I would assume that using the built-in IsAssignableFrom is faster, because it checks if instances of one type can be assigned to another, which involves concrete types rather than generic type definitions. It might be more accurate from a performance standpoint to compare this custom extension method with Odin's ImplementsOpenGenericType method, however the custom extension is meant to handle checking for inheritance or interface implementation as well as handling open generic types.
      Regardless, I would probably do my best to use the 'is' keyword over either of these if possible in a Runtime scenario.

  • @m-horth2187
    @m-horth2187 Před 6 měsíci

    Damn, your stuff is always so good, keep it up!
    I plan to use something like this to create abilities for a game. One of my base types would be "CostFunction", which could have quite a few children inheriting from it such as "CostManaValue", "CostManaPercent", "CostHealthPercent", and so on. I'd want to be able to create an Ability ScriptableObject, and then drop any type of CostFunction in the inspector. But then I'd also want to type in values specific to that CostFunction.
    Does that seem doable with this as a starting point?

    • @git-amend
      @git-amend  Před 6 měsíci

      Thanks for the comment. Your suggeston might work, but you could also consider using a Strategy to calculate the costs for different Abilities (the CostFunction variations could be ScriptableObject Strategies), then you have native drag and drop.

  • @manzello107
    @manzello107 Před 6 měsíci

    This is amazing! I've implemented it but I can't for the life of me figure out how to convert a SerializableType to the class I want!!! I have one called initialState, and I would like to do stateMachine.ChangeState(initialState), but I can't because ChangeState() takes in the State class.

    • @git-amend
      @git-amend  Před 6 měsíci +1

      Keep in mind that this is serializing a Type and not an instance of a Type. If you need to create a pure C# state to use, you can do something like this: Activator.CreateInstance(mySerializableType.Type) as State

  • @Danyanyanyanya
    @Danyanyanyanya Před 15 dny

    Any chance to replace default dropdown with OdinInspector's dropdown?

    • @git-amend
      @git-amend  Před 15 dny

      I'm sure that's doable, give it a shot!

  • @danixadem
    @danixadem Před 6 měsíci

    I'm confused about how to create an instance out of startingState and other fields according to the selection in the inspector. Can you help?

    • @git-amend
      @git-amend  Před 6 měsíci

      This isn't really intended for creating instances at Runtime, but rather for making logical choices about Types at Runtime. However, you can create new instances using Activator.CreateInstance(typeof(Type)). Just be aware that uses Reflection and is much more expensive than using new Type().
      The intended purpose of what's shown in the video is so that you can do things like
      if (myInstance is SerializedType.Value) then do cool stuff.

    • @danixadem
      @danixadem Před 6 měsíci

      @@git-amendThanks for the reply. So, intended use case is more like using enums.

  • @techdave99
    @techdave99 Před 6 měsíci

    @git-amend Still trying to figure things out. Is this different than using SerialeReference?

    • @git-amend
      @git-amend  Před 6 měsíci

      Yes, different but similar. SerializedReference allows you to serialize an object. This allows you to serialize the Type of an object.

    • @techdave99
      @techdave99 Před 6 měsíci

      @@git-amend Ok. Thanks.

  • @techdave99
    @techdave99 Před 6 měsíci

    Will watch this a few times to make sure I understand it. I want to add some regular classes (not MB) to the inspector and choose settings for them. This looks like it will let me do this. Or am I not understanding this correctly? (edited to clarify my intent)

    • @git-amend
      @git-amend  Před 6 měsíci +1

      This will let you choose C# class Types from within the Editor so that you can Instantiate them at runtime, or compare runtime objects with a Type, and so on. It will not expose a pure C# class and it's properties to the Editor - this is for Types only. You would have to expose the settings you want for the C# class separately and then at runtime you can instantiate a new instance of the class of a particular Type with your settings using Activator.CreateInstance(Type)

    • @techdave99
      @techdave99 Před 6 měsíci

      @@git-amend Ok. Thanks for the clarification.

  • @ekekw930
    @ekekw930 Před 6 měsíci

    Do these scripts need to be made in the and Editor folder? I always thought things like PropertyDrawers should go there

    • @git-amend
      @git-amend  Před 6 měsíci +2

      Yes, the PropertyDrawer should be placed in an Editor folder.

    • @ekekw930
      @ekekw930 Před 6 měsíci

      @@anonymous49125 nice, didn’t know that.

  • @omeryilmaz1021
    @omeryilmaz1021 Před 3 měsíci

    can we actually access the methods of the inteface or base abstract class via type of SerializableType, somehow I cant

    • @git-amend
      @git-amend  Před 3 měsíci

      Yes but it is not easy. That is actually a longer video I have planned to produce when I have some extra time.

  • @MarushiaDark316
    @MarushiaDark316 Před 6 měsíci

    I know Custom Editors and certain other Editor-only script can be made in the same class by surrounding it with using directives - #if UNITY_EDITOR. Does that not work for property drawers? I usually hate having to make a dedicated Editor folder for that sort of thing.

    • @git-amend
      @git-amend  Před 6 měsíci

      You can do that in many cases, however it is considered a best practice to keep Editor only scripts in an Editor folder. I personally would prefer the folder over cluttering up my runtime scripts with functionality that is not meant for a build.

  • @yummybunny7351
    @yummybunny7351 Před 6 měsíci

    3:46 it would be nice to know what AI You using and do You recomend it?

    • @git-amend
      @git-amend  Před 6 měsíci +1

      I’m using GitHub CoPilot. I like it for code completion, but it does make mistakes sometimes. Near the end of the video I actually turned it off for a bit. But the code completion generally speeds things up. JetBrains AI gives better suggestions, imo. Both are useful.

  • @archeroliver6078
    @archeroliver6078 Před 6 měsíci

    I assume unity's [SerializeReference] is a solution to this problem?

    • @git-amend
      @git-amend  Před 6 měsíci

      SerializeReference is for serializing references to instances of Types. This is for serializing a reference to the Type itself.

    • @archeroliver6078
      @archeroliver6078 Před 6 měsíci

      Got it, true that.@@git-amend

  • @mohokhachai
    @mohokhachai Před 6 měsíci

    U use the two approach like me