The Ultimate Introduction to Scriptable Objects in Unity

Поділитися
Вставка
  • Опубліковано 3 лют 2025

КОМЕНТАРІ • 138

  • @samyam
    @samyam  3 роки тому +66

    Small Fix, in the video I said to put _SerializeField_ and a _private setter_ - but make sure to add the *field:* tag, like so:
    ---------
    [field: SerializeField] // Notice the field: part. Adding this inside any attribute will make it work with Properties.
    // Others you might want to use are [field:Range(min: 0, max: 100)], [field:Tooltip("description")], etc
    public int MaxHealth { get; private set; } = 100;
    ---------

    • @bunnybreaker
      @bunnybreaker 2 роки тому +2

      Wait, what?! I suddenly need to refactor my whole game...

    • @pabloalves
      @pabloalves 2 роки тому

      I didn't know this one... today you taught me two new things.. you got new sub 😁😁

    • @catafest
      @catafest 2 роки тому

      define NONE? I used IDLE and this aligns with the game logic. After scriptable objects and events, I think the next big issue is the delegate feature. Why don't you make videos about these?

    • @Sam4Progress
      @Sam4Progress 11 місяців тому

      I was on your channel looking for a playslit that included this video but couldnt find one? Did you end up making a playlist or series regarding Scriptable objects as part of another project?

    • @samyam
      @samyam  11 місяців тому +1

      @@Sam4Progress Not really, I do have this intro video though ua-cam.com/video/cy49zMBZvhg/v-deo.html

  • @neenaw
    @neenaw 3 роки тому +12

    This is by far the best scriptable object video I've seen!

    • @samyam
      @samyam  3 роки тому +1

      Thank you!! :D

  • @danielvindhjarta2851
    @danielvindhjarta2851 3 роки тому +104

    This is a good video, and I approve of it, but you forgot a very important part of ScriptableObjects: They can run code. Which means you can use them to alter behaviour of stuff. As an example, you can create different ScriptableObjects for different types of AI, and just switch out the "brain" of an enemy to try out different behaviours. I once made a game where we used ScriptableObjects to alter the behaviour of text, so when the player read to a certain point in the text, stuff such as particle effects, screen shakes or sound could play. This is a very powerful tool for your Designers. You should at least mention that it's possible, although all the possibilities would probably require its own video.

    • @samyam
      @samyam  3 роки тому +43

      That's a good point, I had forgotten to clearly mention it in the video, thanks! I should probably make a separate video on it just because it's such a exhaustive topic after the event based messaging for scriptable objects video 👍

    • @shyamarama
      @shyamarama 3 роки тому +3

      @@samyam That would amazing to see. Would really complement this video as a follow up

  • @Xxnightwalk1
    @Xxnightwalk1 3 роки тому +15

    The thing I like, is that you mention how important these are when working with designers
    So many tutorials forget that game development isn't just about programmers showing off their programming skills but cooperating with non programmers ( designers, artists, etc... ) and making sure they can work autonomously

  • @onatozdemir
    @onatozdemir 2 роки тому +23

    While I follow and really like your channel, I want to give humble advice. Your tutorials start easy and very understandable, it becomes really hard so quickly. I totally got lost on "Enemy Scriptable Object Example" part.
    Your presentation skills are great, and I really want to learn with your content.
    All the best!

    • @samyam
      @samyam  2 роки тому +7

      Thanks for the feedback! I’ll try my best to avoid doing that in the future :)

  • @BlackPanzerYZ-pq9nd
    @BlackPanzerYZ-pq9nd Рік тому +1

    Samyam, I am Incredibly grateful for your channel's inspiration during tough times. My game is hitting Steam after two years of learning!

  • @antontheyeeter
    @antontheyeeter 3 роки тому +5

    i am amazed by how much your channel has evolved. Congrats :)

    • @samyam
      @samyam  3 роки тому

      Thanks Anton! Hope you’ve been well!

  • @TheAgavi
    @TheAgavi 3 роки тому +3

    Easily my new favourite unity tutorial channel. The way your videos are organised is freaking perfect. Most other tutorials are jumping all over the place.

  • @emilyhorton996
    @emilyhorton996 9 місяців тому

    An ESSENTIAL Unity tutorial. Thanks again for such an awesome video!

  • @rebarius
    @rebarius 3 роки тому +3

    This woman is a hero ❤️🙌🏼 thank you so much for this Sam ❤️

    • @samyam
      @samyam  3 роки тому +1

      Thank you Rebar! :)

  • @marinemanaphy101
    @marinemanaphy101 2 роки тому +1

    Thank you so much for this video! I had a bunch of data in scriptable objects but was struggling to connect them to actual objects in the scene, this was a massive help!

    • @samyam
      @samyam  2 роки тому

      Awesome to hear!

  • @FireJojoBoy
    @FireJojoBoy 3 роки тому +2

    This is perfect! I needed a new introduction to scriptable objects lately

  • @gopalravi6676
    @gopalravi6676 2 роки тому

    normally i dont give reviews but maam youre amazing like i tried 2 videos on 2020 and one on 2022 but it wont work but i saw yr video today and it worked as being both content creators i respect your hard work and keep it up

    • @samyam
      @samyam  2 роки тому

      Thank you so much I appreciate it!! 😄

  • @Ylaid
    @Ylaid 9 місяців тому

    Thanks for actually showing how to create one unlike all the other videos I have watched where it just explains bunch of stuff instead of showing how to create a scriptable object lol

  • @kyleme9697
    @kyleme9697 2 роки тому +3

    New subscriber ... I really wish I had seen this video a year ago when I was digging into SOs. This was just so much better, clearer, and contains way more info, than all the other videos I watched last year. Such a simple example but the first part of the video explaining how its an asset really made it pop.

    • @samyam
      @samyam  2 роки тому

      Thanks so much glad you enjoyed it! :D

  • @semenshchepkin1333
    @semenshchepkin1333 2 роки тому

    this is really the best video about SOs, that i found today)
    thank you so much, waiting for new tutorials in your style :)

  • @millerbyte
    @millerbyte 2 роки тому +1

    You rock, this is super helpful. Subscribed.

    • @samyam
      @samyam  2 роки тому

      Thank you!

  • @BarcelonaMove
    @BarcelonaMove 2 роки тому

    Your code is so clean it shines. Awesome job.

    • @samyam
      @samyam  2 роки тому

      ✨ ✨ ✨

  • @sergiosdf599
    @sergiosdf599 2 роки тому

    Every time I stumble with your channel I read Saiyaman instead of Samyam so, with this and your useful tips I guess.. 🤔you're kinda my hero 😅

  • @DanPos
    @DanPos 3 роки тому

    Great video as usual! I've been really digging SO's for a while now

    • @samyam
      @samyam  3 роки тому

      Thanks Dan!! 😁

  • @Valdyr_Hrafn
    @Valdyr_Hrafn 2 роки тому

    I loved this video! this was very comprehensive and got me super excited to try it out!

  • @kazukixe
    @kazukixe Рік тому

    This is such an amazinly done video so clean and useful and to the point

  • @kirtanvinodbhaivekariya413
    @kirtanvinodbhaivekariya413 2 роки тому

    What an angel! You save my broken head!

  • @saadsarnaik
    @saadsarnaik 3 роки тому +1

    Excellent introduction for this topic. Thanks.

  • @SuperDutchrutter
    @SuperDutchrutter 2 роки тому

    Thanks Samyam, super useful video

  • @jakariarafi9737
    @jakariarafi9737 2 роки тому

    TNice tutorials was a fantastic beginner's guide, straight to the point, very clear. As a long-ti teacher I can tell you are quite apt at teacNice tutorialng!

  • @AleySoundz
    @AleySoundz 2 роки тому

    Amazing tutorial. Thank you for taking the time to do this.

  • @GRENADEable1
    @GRENADEable1 3 роки тому +10

    I have been using SOs (Scriptable Objects) for all of my projects now (been a year or 2). I use it for the Handling GameManager States such as if the game is starting, running. If the player is dead etc
    I am looking forward to Event-Based SOs as I use Unity Events and C# Events (Delegates and static events) but I have never figured it how it works with SOs.

  • @sdn2pomahan839
    @sdn2pomahan839 2 роки тому

    bro thanks so much, you actually made soft soft easy to understand

  • @mmediaculturel3738
    @mmediaculturel3738 2 роки тому

    and build tracks from there and leave the rest for a later session. I did both but did the first way initially and it took a day to get through

  • @LeiaInc
    @LeiaInc 2 роки тому

    Great work, Samyam! Love your videos. Keep going! 🙌

    • @samyam
      @samyam  2 роки тому

      Thank you!! 😁

  • @IlaiyaBharathi
    @IlaiyaBharathi 3 роки тому

    Didn’t know they had awake and onEnable. Brilliant video… thank you 😊

    • @samyam
      @samyam  3 роки тому

      Thank you!!

  • @0xF81
    @0xF81 Рік тому

    15:15 what about using this line instead of what you have on line 9 ? This way you'll omit implicit casting that might result in a runtime error, right?
    test = ScriptableObject.CreateInstance();

  • @amac333
    @amac333 3 роки тому +1

    I'm going to experiment with a localization system with Scriptable Objects. Would be cool to see your take on this!

    • @walterh2113
      @walterh2113 3 роки тому +3

      It might be good to know that Unity has a built-in Localization System. Though I'm not saying you shouldn't make (a better) one, just be aware of it.
      _com.unity.localization_

  • @jacksonfrederick514
    @jacksonfrederick514 2 роки тому

    hanks lot Sir.. You helping us..

  • @diliupg
    @diliupg 3 роки тому +1

    Nice creative title.

  • @jmikleo4336
    @jmikleo4336 Рік тому +3

    Great video but I want to clear one thing that scriptable Object are not used for save system, because they don't persist data in build runtime i.e. the game runtime, they persist data only in the editor and any other scene which has reference to that specific scriptable object, if there is no reference to it on other scene the data will lost.

  • @TheSixoul
    @TheSixoul 3 роки тому +4

    Good video on the basic usage of scriptable objects. One of the biggest things is using them for events. You mention an inventory or save system but I've heard those are actually more complicated than one would think. Do you think it's possible for you to cover those in a future video as well as events?

    • @samyam
      @samyam  3 роки тому +2

      That's a great idea, perhaps I will once I get through some other videos first!

  • @ludo6314
    @ludo6314 2 роки тому

    THIS IS AMAING !! you and the way you explained it and also scriptable objects

    • @samyam
      @samyam  2 роки тому

      Glad to hear!

  • @clavesi
    @clavesi 3 роки тому

    Wonderful tutorial as always!

  • @blo0m1985
    @blo0m1985 2 роки тому

    So how actually access that "goblin" parameters? Only main script is accessed in the example.

  • @TheKr0ckeR
    @TheKr0ckeR 2 роки тому +1

    Great video! I have a save system with scriptable objects that holds data. So for every object that i want to save, i create a scriptable objects. I watched this video and saw we can create instances of them. So, what my question is that is this going to create instance every time we start playing the game if we use that code in start?

  • @joshuahauhio5936
    @joshuahauhio5936 2 роки тому

    Fantastic video! Subscribed :)

    • @samyam
      @samyam  2 роки тому

      Thank you!!

  • @thesilentwisp
    @thesilentwisp 3 роки тому

    Thank you so much for this.

  • @superdahoho
    @superdahoho Рік тому

    what if you have functions that you need to save as data. like making a game with active/ passive skills that you can use.
    If i store functions how would I execute that from a scriptableObject and apply it to the scene?

  • @Kathayne636
    @Kathayne636 2 роки тому

    How do you access the Scriptable Object data without use of the inspector, purely in code? Like if I wanted to get the Goblin Enemy Scriptable Object's Health integer from inside another script?

  • @markorossie9296
    @markorossie9296 3 роки тому

    This is fantastic, thanks

  • @3d-ai-model
    @3d-ai-model 2 роки тому

    what a great video :D

  • @JH-uv7km
    @JH-uv7km Рік тому

    thanks! helped a lot!

  • @Thesupperals
    @Thesupperals 2 роки тому

    Watching this seemed very basic, and although a really good thing it also has me wondering about the limitations. These would extend to Dictionaries, lists, Indexing, using a NameSpace, and its just how far encapsulation can go.

  • @Jeff-zc6rr
    @Jeff-zc6rr 2 роки тому

    When you create an instance of a scriptableobject where is it? They obviously don't show up in the hierachy and they don't show up in any folder and they are not attached to any gameobject. So where was it? If you didn't create a scriptableobject with code you'd have to do it through the menu system and then it shows up in your folder so you can edit the values and then drop it onto a gameobject. But running CreateInstance does exactly what?

  • @cizlrb
    @cizlrb 2 роки тому

    So ScriptableObject.Destroy(); will destroy /delete the script from the project folder & not just in the hierarchy ?

  • @mypetlove1578
    @mypetlove1578 Рік тому

    forexample i want to grow tomato, i wrote all scripts required. i just duplicate tomato object in the scene but when i grow 1 of the somato, other also grow at the sametime... so 1 scriptable object will be enough for both of them work independent ?

  • @irisdv658
    @irisdv658 3 роки тому

    great video !

  • @ТимурРоманов-ь6и
    @ТимурРоманов-ь6и 3 роки тому

    Thank you so much 😊😊😊

  • @codeFriendlyART
    @codeFriendlyART 3 роки тому +1

    In between minutes 12~14, it seems that person is only thinking about the ones who makes or generates games / apps via Unity, instead of remembering that there are tools makers as well (like persons that extends on default Unity's Editor functionality) - so it is logical that SOs are also friendly for such usage as well. I don't get why the exaggerated [????] writing thing... Like if it necessarily needs to be a bug ?
    Then, about execution order, well, after all, it is just a generic file container, so I don't see why they need to forcefully be tied up to any particular execution order by design? Thus, when you do cast* them (their contents), it is not 'so you can access it more easily' but rather, so you can access it. Like, so it can become the adequate data/variable type for your script to correctly handle without producing an error.
    Regarding instantiating and memory usage, nothing takes RAM memory until you actually spare 'room' for it (allocate) at execution time. So (in my opinion) stating that because some data structure is residing in an SO will make it not to consume memory can be misleading for the new ones. It does consumes storage memory while at the file (SO) dormant level, the memory needed to store the related file content, plus, if you decide to instantiate many enemies say that makes use of any value store in there you are casting into your own variable and using, then it is using exactly the same memory as any other regular monobehaviour script structure will use. 500 individual enemy health float variables on game screen takes the very same RAM memory if instantiated (allocated) at run time, no matter if from a file's data (SO) or from a script. Allocating for usage is allocating for usage. So I think that the memory conservation can be a misleading subject all-in-all. Unless I'm not getting to understand the point, in case which I do honestly apologize for any related confusion then.

  • @ZactarZero
    @ZactarZero 2 роки тому

    Can you really make a save system system with them? It seems the changes are not persistent if you close and reopen the game in a build, outside of the editor

    • @jmikleo4336
      @jmikleo4336 Рік тому

      you can not make save system with them, they only retain value in the editor or any other scene which is reference that specific scriptable if they are no reference for it in the other scene the scriptable object will go back to its previous state.

  • @darkman237
    @darkman237 9 місяців тому

    So let's say you have an SO of item, with it's attributes and sub classes for armor, weapons, consumables, etc, each with its own attributes. How then do you access those things like: defense rating or attack rating? Or am I just not getting it?!?

  • @Tenaciousanimations
    @Tenaciousanimations 2 роки тому

    In my case I am trying to make a card game whose card effects are very unique per card. I've taken the approach to make each card a unique scriptable object, meaning each card will have a new scriptable object implementation, and one instance of that scriptable object. Is this a good approach?

  • @astrahcat1212
    @astrahcat1212 3 роки тому

    What about just not inheriting from monobehaviour, having data be just classes you serialize into json or xml files, then load and save these data types.

  • @KonradGM
    @KonradGM 2 роки тому

    what is the color theme used for VSCode?

  • @yjonesy
    @yjonesy 3 роки тому

    Game idea: drink a shot every time you say "scriptable object"!
    Jokes apart, very exhaustive explanation. 👏👏

    • @samyam
      @samyam  3 роки тому

      Hahaha that would cause alcohol poisoning. Thanks so much!

  • @tubytwu
    @tubytwu 3 роки тому

    Could u make a tutorial of how to get active controller? if is a playstation, xbox or a keyboard?

    • @samyam
      @samyam  3 роки тому +1

      The PlayerInput component has an event you can subscribe to OnControlsChanged that tells you when a new device is registered, I go over it here 26:40
      ua-cam.com/video/Y3WNwl1ObC8/v-deo.html
      But a dedicated video is a good idea :)

  • @prosvade1337
    @prosvade1337 2 роки тому

    Hey would it be a good idea to use scriptable objects for projectiles in my top down shooter game? i'm trying to implement it but having trouble. Ive looked elsewhere and no one uses them as short lived objects. What do you think?

    • @NorthernlionLP
      @NorthernlionLP 2 роки тому

      I don't think you'd gain anything by putting meshes on scriptable objects. It won't save any memory since Unity already references duplicate meshes from a shared Mesh pool. Would 100% recommend object pooling though!
      I think ScriptableObjects mostly shine from a design perspective since you can use it to make quick adjustments to speed, damage, etc.
      Even if you want to describe every bullet in the scene, lets say with a 16 byte string that says "BulletAR", and a 4 byte int to store the damage. You'd only be saving 20 bytes per bullet in your scene. That's only 20KB saved per thousand bullets.

  • @faridbehrouzi2380
    @faridbehrouzi2380 Рік тому

    great video thanks a lot

  • @flyswitdesigner9097
    @flyswitdesigner9097 3 роки тому

    Hello samya I love your content and your excellent voice I am going to leave my subscription and like, but I have a question, with the new input system you can interact with objects, that is, doors, cabinets, pick up stones or boxes etc, with mobile controls and with the keyboard??

    • @samyam
      @samyam  3 роки тому +1

      Yes of course! The input system just managed input, it’s up to you to read the input and do what you want with it. Thank you!!

    • @flyswitdesigner9097
      @flyswitdesigner9097 3 роки тому

      @@samyam awww thank you thank you but I'm new to that system jsjsjsjs 🥺🥺🥺🥺 you couldn't do a tutorial on how to do it please☺️🥺🥺

    • @samyam
      @samyam  3 роки тому +1

      ua-cam.com/video/m5WsmlEOFiA/v-deo.html

  • @someoneontheinternet3090
    @someoneontheinternet3090 3 роки тому

    Your sponsor message scares me to death

  • @burceaionut6516
    @burceaionut6516 2 роки тому

    I've always wanted to make soft but every ti I download software to do so, I just look at the 5,000 buttons/settings, cry for a few

  • @bunnybreaker
    @bunnybreaker 2 роки тому

    I've been using ScriptableObjects for a while, but I had no idea about those built in functions and their shenanigans. I'ma stay the hell away from those jeez.
    Thanks for the video.

  • @jinbeisallblue9016
    @jinbeisallblue9016 3 роки тому

    I'm a simple guy..
    I see my name, i click

  • @VLOneWay
    @VLOneWay 2 роки тому

    thx nice video

  • @attenurmi936
    @attenurmi936 2 роки тому +1

    Scriptable objects are NOT meant to be used as a save system! You will lose data if you try to use them in a program as a way to save persistent data.
    Here is a demonstration video from Code Monkey about this pitfall:
    ua-cam.com/video/5a-ztc5gcFw/v-deo.html

  • @manuelabarcacrespo8298
    @manuelabarcacrespo8298 3 роки тому +1

    you can set values to enums, so the part of "Replacing enums with scriptable objects" makes no sense. Anyway, it was a great video and very educational, TY

  • @Esimaxchannel
    @Esimaxchannel Рік тому

    Don't you think there are many mistakes in this video, I would say is best to re-record it if it is possible and add the new link into this.

  • @PeterSedesse
    @PeterSedesse 2 роки тому +1

    great video. Just to add a small opinion. Do away with the random b-roll stuff, it is just distracting and non-informative. Just keep up your graphics instead of flipping back and forth to random b-roll people.

    • @samyam
      @samyam  2 роки тому +1

      Thanks for the tip! I actually think the B-roll increases audience retention to keep capturing their attention, but I’ll play around with it and see the best results :)

  • @蝎子莱莱-w8j
    @蝎子莱莱-w8j 2 роки тому

    I feel like there is gonna be a r/whoosh joke here

  • @jwakeuplink7671
    @jwakeuplink7671 3 роки тому +2

    Good video, I didn't know about the OnEnable etc in ScriptableObjects!
    I'm confused about the use of ScriptableObjects to replace enums though. My understanding is that you should never hard code in the index, e.g.:
    if (attackChoice == 0)
    You should use the name of the member, e.g.:
    if (attackChoice == AttackType.SWEEP)
    So it shouldn't matter if an enum member is deleted. I thought enums are largely used to avoid this specific issue of having to hard code in numbers for a set of options.
    And in the situation where you're working with a messy codebase - where whoever wrote the code has been littering indexes as they relate to an enum, rather than the enum itself - and you need to delete something from an enum knowing full well that there are index magic numbers that will break elsewhere in the code, there seems to be a better fix.
    Rather than delete an enum option or replace it with NONE, you can just manually set the member after the deleted one back to its expected index, e.g.:
    enum AttackType {
    SWEEP,
    //removed JAB, which was index 1
    TEST = 2,
    SIDESTEP
    }
    Now you've removed the unwanted member without affecting any of the existing indexes.
    Finally, there shouldn't be a problem with a designer creating a new enum member, unless there are magic number index references (instead of referring to the enum member name).
    Please do let me know if I'm missing something here! Great video and I definitely learned something new, just lost on this one point. Subbed :)

    • @Eddycted
      @Eddycted 3 роки тому +1

      This addressed here in the talk samyam linked in the description: ua-cam.com/video/raQ3iHhE_Kk/v-deo.html
      Short answer: enums are serialized to their number values.

    • @christophwei2890
      @christophwei2890 Рік тому

      @@Eddycted Yeah but you can specify the numbers an enum value corresponds to

  • @NotASpyReally
    @NotASpyReally 2 роки тому

    This is a good tutorial but the start looked like an ad and made me cringe a bit D:

  • @NorthernlionLP
    @NorthernlionLP 2 роки тому

    How the script was written for this video -
    ____ _____ _____ Scriptable objects. ____ _____ _____ Scriptable objects. ____ _____ _____ Scriptable objects. ____ _____ _____ Scriptable objects. ____ _____ _____ Scriptable objects. ____ _____ _____ Scriptable objects. ____ _____ _____ Scriptable objects. ____ _____ _____ Scriptable objects. ____ _____ _____ Scriptable objects.

    • @samyam
      @samyam  2 роки тому

      I don’t write scripts 😉

  • @nova_digital_video
    @nova_digital_video 2 роки тому

    life is life la laa - la la la bruh

  • @wormholeinteractive
    @wormholeinteractive 2 роки тому

    It's like a variable on steroids!

  • @Jeff-zc6rr
    @Jeff-zc6rr 2 роки тому

    Where is the script that you created with code? After the "how to create a scriptable object" there is nothing of value actually. Those lifecycle methods are not useful. A more useful demo would have been to get data for 100 objects from a database, then create a scriptable object for each to apply to each enemy. You're essentially bringing the scriptable object into existence and destroying it before we even know it even existed.. how is that useful?

  • @mrxbg4610
    @mrxbg4610 2 роки тому

    the way.

  • @MrDavehathaway
    @MrDavehathaway 2 роки тому

    The ENUM explanation is so wrong. Who in their right mind uses values in their code when they have ENUMS defined ???????? Sounds like a case of someone not knowing basic programming - NO magic numbers! It is a really good idea to use the Scriptable Objects instead though.

  • @emanueltejadacoste2250
    @emanueltejadacoste2250 2 роки тому

    And how the heck do we learn machinations xD? Joking

  • @Smir-jo4rj
    @Smir-jo4rj 8 місяців тому

    please do not use scriptable objects as a save system, its not persistent when you build the game, if you do use scriptable objects, use json

  • @moviesixstudio8626
    @moviesixstudio8626 2 роки тому

    god bless u xdd

  • @eladonstar2721
    @eladonstar2721 3 роки тому

    Sam you got 18k subs...
    Why posting only one video per month then 😐😐😐

    • @samyam
      @samyam  3 роки тому +2

      Cause I’m a busy person! 😉

  • @reverbloadedmusic6190
    @reverbloadedmusic6190 2 роки тому

    Dave 84

  • @Chieseled_Renegade
    @Chieseled_Renegade 2 роки тому

    UwU

  • @goldduck924
    @goldduck924 2 роки тому

    and sa tNice tutorialng other way around

  • @monkeyrobotsinc.9875
    @monkeyrobotsinc.9875 Рік тому +1

    it would be cool if you pitched your voice down to a male level so it sounded super cool and not god awful annoying. so i have to leave and thumb you down so sorry.

  • @ACADEMICMFC
    @ACADEMICMFC 2 роки тому

    realy work)