This video is based on *Unite Austin 2017 - Game Architecture with Scriptable Objects* conference ua-cam.com/video/raQ3iHhE_Kk/v-deo.html I feel like not many people are using this approach (including me) so I thought is would be worth sharing again :)
Thanks for watching! I am guilty of using enums in this fashion for a long time so I though others might too be interested in how to solve this issue :)
I am glad to hear that! SO are very useful as a tool but at the same time it is not "ground breaking". You can achieve the same effect using Plane C# classes (but you can't easily preview them in the inspector) or by using Prefabs (it takes a bit more time and MonoBehaviours are less performant just to store some data). If you want to learn more about those check out my other tutorials as I try to use SO often ;)
I'm serious, I went through 2 to 3 videos about this topic, but I still didn't grasp the complete understanding and its practical applications. This tutorial is the finest, tailored for beginners to comprehensively grasp what a scriptable object is and how to effectively implement them. Thank you for producing such top-notch content. Keep up the excellent work!
I keep trying my team to use more data oriented architectures to be more friendly for the designers, but one of the biggest reason is how you can easily add new content through CMS without having to update the game code, which can be amazing in the long run! Enums are great for some stuff, but content generation is not one of them!
Hey! Yeah that is right. Most of those solutions one can learn only by creating a bigger project to actually *see the problem* . When you don't know about the problem it is hard to see why you wouldn't use a good old enum for everything data related. Thanks for watching!
This is where a good understanding of C#/OO would help any unity developer. What you are doing here is following the principles of good OO practice - encapsulation, abstraction etc. it’s nothing specific to unity.
You are definitely right. After working with SO for some time now I can see that using them makes it much easier to separate data and inject it to a class that needs it compared to a pure c# implementation 🙂
What i dont get is we could have used simple prefab instead scriptable object. What is the difference between scriptable object and prefabs in this particular scenerio?
Well we could. The usefulness of SO is to store data and to easily connect this data to different objects in our scene without having to couple the objects themselves. The benefit could be that while we could have a "GameObject" field we can assign to it anything. If we create an "ItemSO" we still need that "GameObject" field in it to access the prefab. It just gives us more context to not assign "UIInventoryPrefab". We can also implement Serialization checks to ensure that the object is of specific type. All that said at the end of the day SO are just a way to allow us to better utilize the fact that we have the Unity Inspector at our disposal. In a plain c# project would would use constructors to assign data to the objects. Here we can create a HealthValueSO and connect it with Player and PlayerUI object and non of them needs to know about the other one. I hope it gives you some context!
I find using enums mainly for "states" now, for example AI or a minigame states. When I started out coding I was exploiting enums and switch cases exactly as you demonstrated here. And as you mentioned it is scaling very badly.. Great video!
Thanks for the comment! Yes enum has their place and especially in a small project / prototype its much easier to use them. It's only later as the project grows that you can see how bad they scale and it is useful to know how use Objects / ScriptableObjects instead of enums.
Hello. What should I do if I have two identical bow prefabs in the scene that contain a different number of arrows? That is, how to track a certain number of arrows for each individual prefab.
Hey! One solution could be that you have data parameter saved as JSON (string) and that you decode it - can be a bit tricky. An Object Oriented solution could be that you have inheritance tree with Iterm.cs as a base class and WeaponItem.cs or RangeWeapon.cs that would store the arrow quantity value. in the Players code you could have a FactoryMethod that would check the type of the object and process it accordingly while still getting as an argument the base class reference Item.cs In general the bast way to go about it is to save all the data in the object that we pick up and a corresponding ItemManager.cs and WeaponManager.cs that would be able to process different objects (WeaponManager.cs would know that it needs to search for ArrowQuantity value base on the object type). This way player can just delegate the process of decoding the object to a specialized low level class. I hope it gives you an idea on how to design this kind of system.
This is very nice and simple example even for beginners. And case when you have enum and switch(es) is a warning you should do it differently. Otherwise maintainability will be hell. Also good example with that traffic lights and compass, but usually it is not as clear as you work with game concepts. I am currently struggling with situations, where I have several enums values, which areprobably not going to change much, and are connected to maybe one variable. So I dont feel it's rasonable to do SO just for one variable, but at the same time there are about 20 enum values, so I fear if I run to switch case with them.
Hey! Yeah the idea itself isn't new - it's just a more object oriented way to store data without relying on primitives like enum. I just think that enums are abused in prototypical code but this code is what most people see and they end up like me asking wrong question *"how can I create enum at runtime"* when the answer is -> use a more Object-Oriented solution (or any other that doesn't rely on a primitive).
So, with these scriptable object weapons as an example, would you need an So for each weapon? For example, in most RPGs you've got multiple bow types, and multiple sword types, etc. Or would the so data container be able to hold the weapons class and, say, a range of damages and things that prefab objects could draw from? I might have missed this in the video (watched it twice) but I'm also completely exhausted at the moment and my brain is totally crashing at the moment ... Lol😅
Great question! I will try to cover a more advanced topic. Generally SO are good for small games although you can get the data about different weapons from an Excel file / database and create SO from code that will represent DATA. The point of this video is: we can add a new type of weapon very easily by using OOP (objects) instead of hard coded enums. Any code modification can cause a bug. At the same time we can add a method called "Use" to our Weapon abstract SO and easily implement different versions of this Use() logic in different weapon. I cover this in more details in my course *Make a 2D platformer in Unity using Design Patterns* if you are interested. Here is the link courses.sunnyvalleystudio.com/p/code-a-2d-platformer-game-in-unity-using-design-patterns
Trying to understand the difference between scriptable object script and just using regular scripts..? I don't really get it. What is the difference between using regular scripts and inherit from them? ☺️☺️
The only difference is that pure c# script can only be created by another script which SO can be created inside unity (just like MonoBehaviour). Basically if we use MB or SO we can benefit from using Unity inspector to set all the data etc. When working in Unity most of the time you want to use SO or MB to make your life easier when prototyping a game / creating small games.
Hey! You can add custom logic to ScriptableObject definition or you can split your system into ax PickUp system that relies on the ScriptableObject that in turn instantiates a new Weapon and either uses composition by adding to it ex "FireModifier" or by using inheritance and simply passing a "new FireWeapon()" class instance. If you want to learn more about Object Oriented Programming (to learn more about using inheritance / composition) maybe you will find my *OOP for Unity devs* course useful courses.sunnyvalleystudio.com/p/learn-to-write-clean-object-oriented-code-in-unity I hope it helps!
If you are using an SO based solution you would have a singele SO called "WeaponDatabase" where you have a List(). In the simples case you would just loop through this list and spawn them. This way whenever you create a new weapon you add it to your SO list and you don't have to modify the code. I would not exclude usage of Enums (Sorry for making it sound like that). They are very useful for storing things that rarely change.
@@SunnyValleyStudio I'm more thinking for lists that change, e.g. you have several people working on new items regularly, and a single item list would be a bottleneck. I'm trying to figure out if there's a way it could be modularized instead, so any designer could just check a box on their item to say "yes include me in the game" rather than having everyone constantly updating the same file.
@@SunnyValleyStudio I'm more thinking of a situation where several designers on working on weapons, so it might be nicer to just let them flag weapons individually as "include me in the game" rather than having to constantly merge a weapons list asset. Does that make sense?
Enums are extremely flexible, and you should use them. An example is states for a weapon: Is the player ADS'ing? Is he running? Is he jumping? The weapon will behave differently depending on these states, and an enum is a great way to resolve this. It would be silly to fix this with a scriptable object
Hey! Thanks for the comment. You are 100% right. This would call for a Object oriented solution. Ex player can be in Idle State or RunningState or JumpingState where by using *State Pattern* we can define in each state object what happens with the player. This way we can add new states without modifications ex we can have UseWeaponState where attack animation is player and we use a weapon. This way also we can control what transitions are possible between states without creating a long list of * if* statements and we don't have to modify existing code to add new enum value. SO substitute can be useful when you have ex Weapon stats like "Durability". We can have mnay weapon stats so it is easier to create a new DurabilityStatSO and when we hit a rock the rock can have a list of WeaponStatsSO and how hitting a rock affects the weapon. This way if we want to add a new star to a weapon all we need is to add a new ex ElementalDamageStatSO object instead of new enum. Still i should have created a better example. Sorry about that 😅
Great video!!! I have two different weapons, both of them attaches to the same weaponSlot but only one weapon matches perfect in the players hand after some transform tweaking with the empty gameobject attached to the hand. How do I make it so both weapons match perfectly in the hand?
I'm not sure since I mostly work in 2D. What I usually do is to ensure that the weapon has a parent object which defines its offset so that it matches a singular attach point on the player. In case you have a significantly different weapon you would need a new animation anyhow so I would add a secondary attach point on the hand of the player. There might be other ways to solve it.
@@SunnyValleyStudio I'll try the parent object way. Thanks a lot for replying! I've watched a couple of your vids and I think they are great, keep it up! :)
i found it a bit confusing.. I've been looking for a way to reference a scriptable object exactly like what you did in the video, and I can't seem to find any part where you reference it, I mean scriptable object is an asset, how did you get the reference?
Hey! SO is just an asset that we can drag and assign through the inspector or create art runtime. What I do in the vid around 7:05 is have the pickable object (weapon models) have the reference to the SO - it represents the weapon data. In OnCollisiont / OnTrigger the data is passed to the player so that it can process it.
For the weapon manager script ,you could simply create an array of prefab references (That's what arrays are for) and cast enum to int to access the respective index => no need to use the switch statement For default, you should always have None All you have to do now is add another enum
Sure. To add another enum you need to edit the code that works perfectly fine. To add another SO all you do is create another subclass = more object oriented solution. You could do exactly the same thing without SO but rather by using prefabs, inheritance and polymorphism. What we get is easy way to extend the functionality without touching the old code that works.
There’s another problem with the enum solution - Unity serializes Enums as integers not as strings. So if you have multiple developers working on the project, then the order in which the enum types are added matters. If a merge conflict is incorrectly resolved, then you have broken references
You could have skipped all of this and had a c# script with this data in it named "Weapon" on your weapon prefab... SO are in no way a replacement for enums, your original design was just strange
Hey! Thanks for the feedback. Enums are great for prototyping and for teaching beginners. I myself included learned how great "enum" is for defining type. That was until it wasn't since I needed to add extra operation to my types that differed. Anyhow remember that not everyone is at the same programming level as you. Some beginners needs to learn that there is a better OO way to define types than enums. That is my target audience for this vid.
This is nice in theory, but we usually end up using enums anyway for things like weapons. Enums are easier to serialize for game saving and networking. Also queries like "does the player own this specific weapon/item/card?" are much simpler with enums.
Yes. Definitely enums are easier to use and if you remember to add NONE case if you need null value equivalend and always add a new enum at the end they will work for most cases. The issues begin when you start using a switch statement to handle some logic based on the enum type + you have a need to constantly add new enums. I assuer you that I use enums to prototype ex 3 units in a simple RTS. But whenever I want to move forward and have all the units perform different attacks ex "Range shot", "Move close and melee attack" and others I would never use a switch checking the unit enum type. I would always go for an inheritance / composition based solution where I can call Unit.Attack() where ex Attack is an abstract method.
@@SunnyValleyStudio You're right, there are definitely certain drawbacks to using enums. But we use them just as IDs for relatively static sets of items, so for instance, we have our weapon logic in classes that have a WeaponId property. We don't really need any switches except for switches in factories. So I think sometimes it's fine to break the "do not use enums for anything that can change" rule. But as always, it depends on what you're trying to achieve. You can often get away with using plain enums but there are many situations when you need something more sofisticated, that's for sure.
Yeah that is true. I could have come up with a better example. In my latest Inventory System tutorial I show how to add *Item Stats* and making those into SO instead of enums allows us to place an SO Reference on a list of *stats to modify* and assign the specific stats to an *item stats list* ua-cam.com/video/uKTLyjaF4hA/v-deo.html. The point is that now instead of modifying the enum we create a new *ItemStatSO* subclass and we can add it to our lists and easily modify/add the stats to the items without having to modify any code. Thanks for watching and for your feedback!
A. Enums are already extremely developer friendly have the same overhead as an int. There is absolutely, 100%, no reason to replace them with a scriptable object.... especially taking in to account the effort to create and implement the scriptable object is much more that creating and maintain an enum. B. It seems like almost every Unity developer is extremely desperate to jusifty the existence of scriptable objects, but the truth is there is none. They don't make anything easier. People want them to, they hear someone else that wants them to just as much say they do... But they don't. They don't even negate the need to write in C#. You absolutely know that people are desperate when they even consider suggesting replacing enums with them. If you have the option of using enums or an entire scripted object, please use enums. Every other developer will thank you AND you will learn how to program in a way that can scale without being a horrid waste of time and system resources.
You definitely have a point there. I have been using SO for a while and while they have a lot of uses using them instead of enums doesn't work that great. Sorry about that. Don't get me wrong this is still valid point. I would just skip use of SO. If you add a new enum you have to also change every Switch / If statement. When you add a new object that implements some common abstraction you never modify a line of the old code that deals with the logic of "what it is". You just add a new Weapon ex Bow and the Bow class creates a projectile when it receives Weapon.Use() call. No need to modify any previous working code - risking that it will stop working. Here is a better use case for SO where we use it to split the dependency between Health system and health UI by using SO to implemented a more Data Oriented design ua-cam.com/video/6deqAk3jypo/v-deo.html
I am glad to read your comment and find I am not crazy, I have been programming as a fullstack web dev for over a decade and started playing around with Unity recently as a hobby. I was wondering why I should use SO for anything, every time I need to make a small maintenance in the code I had to click through every SO and change it manually, I can't imagine having hundreds of items made on it.... as a solo dev I found a better option to manage hundreds of items data in a Google Spreadsheet and by a script call generate a JSON and add into the resource folder, then at initialization create a Dictionary to be accessed anywhere by ids directly.
Why people don't want to watch longer 20 video tutorials but expect to learn about creating OOP code that utilizes SOLID principles and design patterns in a 5 minute video? Why can't I make longer courses where I can explain everything step-by-step but I have to limit videos to 10 min to get any traction on YT? Hint: People on YT don't want to watch longer vids and it's much faster to write "public int myInt" compared to explaining why to use properties because the average viewer will switch to the next vid mid explanation. Anyhow thanks for the feedback. I will do my best to use properties instead in my future vids!
@@SunnyValleyStudio Thanks for reply. What I meant by that is that I see this style of writing from many Unity developers, not just you. And writing property is actually faster if you use Visual Studio. Type word "prop" (without quotes) and press tab twice. Properties also have some advantages.
@@flyingdutchman2692 It's because public fields, unlike public properties, get serialized in Unity. Meaning you can modify their values in the editor. Alternatively, you can use a private field with a [SerializeField] attribute and use a property with a public getter to access said private field from other classes. But that's usually not worth the hassle... It's just unneccessary noise. Public fields are often good enough. Gamedevs usually have this pragmatic, "get stuff done quickly" mindset, they don't care if they use a public field instead of a property, they're not afraid of "anti-patterns" like singletons etc. If it works, it works.
@@cfffba Wait, what? You can't use public property as SerializeField? This is completely fake info. [field: SerializeField] public int MyProperty { get; set; } -> and entire property (except serialize field part) was created for me, just by typing prop.
@@flyingdutchman2692 Well that's just syntactic sugar for using an attribute on the backing field of a property. Public properties are not serialized by default in Unity (without using an attribute).
Looking back at this video I think it still is relevant but I do think that enums and switch statement has their place for enumerating more static things like Directions or things your set through the inspector. Like when you have a designer set a season that a crop grows in it is quick and easy to create an enum {Winter, Spring, Summer, Autumn} and expose it 🙂
I guess this seems fine for small projects. I personally dislike the idea of manually adding scriptable objects and having to drag them around in the editor. With better game logic and enum use it should be easy to add a new weapon without having to do anything manually, other then write some text data for the new weapon. Your Enum should probably be Melee / Ranged. That way it's not going to change. Axe / Sword logic should be the same, since they are handled as Melee weapons. If the axe is different in some way form the sword, just add an AxeScript to the gameObject or something. Easily done with a switch in script or by putting it on your prefab in the editor.
Thanks for sharing feedback! I love to learn how thinks about SO used this way. You are right. C# wise it is nothing new or better. Even worse it is Unity specific solution if you use So. I don't agree with "small project" approach. The whole point here I think is that people who don't know how to code can easily swap around So by dragging them. By all means you can do it with a Type object pattern and a prefab that is a data object. Not a fan of enum unless it is a cardinal direction or sth else that really doesn't change. Any other case it would be a strategy pattern or any other oo approach.
@@SunnyValleyStudio I think you hit the nail on the head with: "People who don't know how to code can easily swap around SO by dragging them". I'm also learning, but I prefer to learn how to code in c# rather than learn Unity. In any case, it's good that you show how you can use SO in a game.
SO is good replacement for ugly Singletons, and can be used for global event systems. Watch video about SO at official Unity channel. In fact ScriptableObject is instance of a class and in the right hands can be very useful tool.
Hey! Definitely keep using them when prototyping / having a cardinal direction enum where you know that there are no more directions to add. I wouldn't use them for anything like "UnitType" because you have ex 3 enums {Soldier, Worker, Boat} and next you suddenly remember that units can interact with Boxes that are immovable but your logic expects an enum type check so you add {None} to it. If you add it in the front ex {None, Soldier, Worker, Boat} and you have some serialized values in the inspector all the GO that had Soldier type will have None. Also if you have a switch statement checking the type now you need to modify it. That is why beside prototyping I would always choose an Object Oriented solution using Scriptable objects or inheritance and create a new subclass while my general logic works on the base class (or nowdays I would try to implement composition first). I hope that it answers your questions!
Maybe you are right. Still is seems to me like using enums always ends us as "Primitive Obsession" code smell later on in the project. We always need more data to go with the enum value refactoring.guru/smells/primitive-obsession
@@SunnyValleyStudio I think you're right in this example. Though if you designed your game ahead of time, you would find some things where enums would be a good fit. For example if you were only going to have sword, axe, hammer as weapon types and thats it, because you completed the design ahead of time. Then an enum for weapon type on your SO's might be handy. Then later you add a talent system where if you are using a weapon SO with weapontype.hammer you get +10% hammer damage. Stuff like that can still make sense. I think the big difference is not tying lots of dependent code to the enum. So like the weapon manager probably shouldn't care what type it has, but a talent or something else later might care, and it can go find out.
SO is a unity tool. You have your purist blinders on. SOs are way more useful when managing a team. Solo devs can do what they feel comfortable with ultimately but please don’t downplay the usefulness of SOs when it comes to workflow and project iteration.
This video is based on *Unite Austin 2017 - Game Architecture with Scriptable Objects* conference ua-cam.com/video/raQ3iHhE_Kk/v-deo.html
I feel like not many people are using this approach (including me) so I thought is would be worth sharing again :)
how to sumarize a 1 hour and 30 minute unity ted talk into 11 minutes :D, one of the best explanations I've seen so far.
Glad it helped! 🙂
Actually one of the best scriptable objects tutorial for beginners, good job!
Thanks for watching! I am guilty of using enums in this fashion for a long time so I though others might too be interested in how to solve this issue :)
This is actually the first time I've understood ScriptableObjects and seen a usecase for them!
I am glad to hear that! SO are very useful as a tool but at the same time it is not "ground breaking". You can achieve the same effect using Plane C# classes (but you can't easily preview them in the inspector) or by using Prefabs (it takes a bit more time and MonoBehaviours are less performant just to store some data). If you want to learn more about those check out my other tutorials as I try to use SO often ;)
i love this sort of stuff, not enough tutorials use real world examples to drive the point home
Thanks for watching!
I'm serious, I went through 2 to 3 videos about this topic, but I still didn't grasp the complete understanding and its practical applications. This tutorial is the finest, tailored for beginners to comprehensively grasp what a scriptable object is and how to effectively implement them. Thank you for producing such top-notch content. Keep up the excellent work!
Thanks for watching!
This is by far the best Unity tutorials channel on UA-cam
Lots of respect
Thanks for watching 🙂
I keep trying my team to use more data oriented architectures to be more friendly for the designers, but one of the biggest reason is how you can easily add new content through CMS without having to update the game code, which can be amazing in the long run! Enums are great for some stuff, but content generation is not one of them!
Hey!
Yeah that is right. Most of those solutions one can learn only by creating a bigger project to actually *see the problem* . When you don't know about the problem it is hard to see why you wouldn't use a good old enum for everything data related.
Thanks for watching!
You have taken my coding to new heights with this tutorial. Thank you so much!
Glad to hear it!
Simple, straight to the point ! I like it !
Thanks!
Best Example of Scriptable object
Thanks for watching!
This is where a good understanding of C#/OO would help any unity developer. What you are doing here is following the principles of good OO practice - encapsulation, abstraction etc. it’s nothing specific to unity.
You are definitely right. After working with SO for some time now I can see that using them makes it much easier to separate data and inject it to a class that needs it compared to a pure c# implementation 🙂
Thank you very much! The greatest explanation i've seen.
Glad it was helpful! 🙂
Working right now. Cant wait to watch it later :D
Thanks for checking the video out :)
What i dont get is we could have used simple prefab instead scriptable object. What is the difference between scriptable object and prefabs in this particular scenerio?
Well we could. The usefulness of SO is to store data and to easily connect this data to different objects in our scene without having to couple the objects themselves. The benefit could be that while we could have a "GameObject" field we can assign to it anything. If we create an "ItemSO" we still need that "GameObject" field in it to access the prefab. It just gives us more context to not assign "UIInventoryPrefab". We can also implement Serialization checks to ensure that the object is of specific type.
All that said at the end of the day SO are just a way to allow us to better utilize the fact that we have the Unity Inspector at our disposal. In a plain c# project would would use constructors to assign data to the objects. Here we can create a HealthValueSO and connect it with Player and PlayerUI object and non of them needs to know about the other one. I hope it gives you some context!
I find using enums mainly for "states" now, for example AI or a minigame states. When I started out coding I was exploiting enums and switch cases exactly as you demonstrated here. And as you mentioned it is scaling very badly.. Great video!
Thanks for the comment! Yes enum has their place and especially in a small project / prototype its much easier to use them. It's only later as the project grows that you can see how bad they scale and it is useful to know how use Objects / ScriptableObjects instead of enums.
Hello. What should I do if I have two identical bow prefabs in the scene that contain a different number of arrows?
That is, how to track a certain number of arrows for each individual prefab.
Hey!
One solution could be that you have data parameter saved as JSON (string) and that you decode it - can be a bit tricky.
An Object Oriented solution could be that you have inheritance tree with Iterm.cs as a base class and WeaponItem.cs or RangeWeapon.cs that would store the arrow quantity value. in the Players code you could have a FactoryMethod that would check the type of the object and process it accordingly while still getting as an argument the base class reference Item.cs
In general the bast way to go about it is to save all the data in the object that we pick up and a corresponding ItemManager.cs and WeaponManager.cs that would be able to process different objects (WeaponManager.cs would know that it needs to search for ArrowQuantity value base on the object type). This way player can just delegate the process of decoding the object to a specialized low level class.
I hope it gives you an idea on how to design this kind of system.
This is very nice and simple example even for beginners. And case when you have enum and switch(es) is a warning you should do it differently. Otherwise maintainability will be hell.
Also good example with that traffic lights and compass, but usually it is not as clear as you work with game concepts.
I am currently struggling with situations, where I have several enums values, which areprobably not going to change much, and are connected to maybe one variable. So I dont feel it's rasonable to do SO just for one variable, but at the same time there are about 20 enum values, so I fear if I run to switch case with them.
Hey!
Yeah the idea itself isn't new - it's just a more object oriented way to store data without relying on primitives like enum. I just think that enums are abused in prototypical code but this code is what most people see and they end up like me asking wrong question *"how can I create enum at runtime"* when the answer is -> use a more Object-Oriented solution (or any other that doesn't rely on a primitive).
@@SunnyValleyStudio get out of my google search history! 😂😂
So, with these scriptable object weapons as an example, would you need an So for each weapon? For example, in most RPGs you've got multiple bow types, and multiple sword types, etc. Or would the so data container be able to hold the weapons class and, say, a range of damages and things that prefab objects could draw from? I might have missed this in the video (watched it twice) but I'm also completely exhausted at the moment and my brain is totally crashing at the moment ... Lol😅
Great question! I will try to cover a more advanced topic. Generally SO are good for small games although you can get the data about different weapons from an Excel file / database and create SO from code that will represent DATA.
The point of this video is: we can add a new type of weapon very easily by using OOP (objects) instead of hard coded enums. Any code modification can cause a bug. At the same time we can add a method called "Use" to our Weapon abstract SO and easily implement different versions of this Use() logic in different weapon.
I cover this in more details in my course *Make a 2D platformer in Unity using Design Patterns* if you are interested. Here is the link courses.sunnyvalleystudio.com/p/code-a-2d-platformer-game-in-unity-using-design-patterns
@@SunnyValleyStudio I am extremely interested. I'll definitely be checking this out! Thank you! And thanks for for such a detailed answer!
A good explanation, thank you
You are welcome!
Even NSEW isn’t great for an enum if there is a chance you’ll want to add NE, SW, etc
That is true.
Thank you for doing this video :3
Great tutorial. Thanks 😊
A very nice tutorial, thank you a lot!
really good tutorial.
Glad you think so! 🙂
Thank you so much!
You're welcome!
Trying to understand the difference between scriptable object script and just using regular scripts..? I don't really get it. What is the difference between using regular scripts and inherit from them? ☺️☺️
The only difference is that pure c# script can only be created by another script which SO can be created inside unity (just like MonoBehaviour). Basically if we use MB or SO we can benefit from using Unity inspector to set all the data etc.
When working in Unity most of the time you want to use SO or MB to make your life easier when prototyping a game / creating small games.
That's a great solution, but what if I want to make special logic for a certain weapon/item?
Hey!
You can add custom logic to ScriptableObject definition or you can split your system into ax PickUp system that relies on the ScriptableObject that in turn instantiates a new Weapon and either uses composition by adding to it ex "FireModifier" or by using inheritance and simply passing a "new FireWeapon()" class instance.
If you want to learn more about Object Oriented Programming (to learn more about using inheritance / composition) maybe you will find my *OOP for Unity devs* course useful courses.sunnyvalleystudio.com/p/learn-to-write-clean-object-oriented-code-in-unity
I hope it helps!
Let's say you wanted to spawn 1 of each weapon in code. How would you go about getting a list of allowed weapons, without using an enum?
If you are using an SO based solution you would have a singele SO called "WeaponDatabase" where you have a List(). In the simples case you would just loop through this list and spawn them. This way whenever you create a new weapon you add it to your SO list and you don't have to modify the code.
I would not exclude usage of Enums (Sorry for making it sound like that). They are very useful for storing things that rarely change.
@@SunnyValleyStudio I'm more thinking for lists that change, e.g. you have several people working on new items regularly, and a single item list would be a bottleneck. I'm trying to figure out if there's a way it could be modularized instead, so any designer could just check a box on their item to say "yes include me in the game" rather than having everyone constantly updating the same file.
@@SunnyValleyStudio I'm more thinking of a situation where several designers on working on weapons, so it might be nicer to just let them flag weapons individually as "include me in the game" rather than having to constantly merge a weapons list asset. Does that make sense?
good clear , thank you
Thanks for watching!
this is great
3:58 did i miss something? i've done what you did, but nothing happens
Enums are extremely flexible, and you should use them. An example is states for a weapon: Is the player ADS'ing? Is he running? Is he jumping? The weapon will behave differently depending on these states, and an enum is a great way to resolve this. It would be silly to fix this with a scriptable object
Hey! Thanks for the comment.
You are 100% right. This would call for a Object oriented solution. Ex player can be in Idle State or RunningState or JumpingState where by using *State Pattern* we can define in each state object what happens with the player. This way we can add new states without modifications ex we can have UseWeaponState where attack animation is player and we use a weapon. This way also we can control what transitions are possible between states without creating a long list of * if* statements and we don't have to modify existing code to add new enum value.
SO substitute can be useful when you have ex Weapon stats like "Durability". We can have mnay weapon stats so it is easier to create a new DurabilityStatSO and when we hit a rock the rock can have a list of WeaponStatsSO and how hitting a rock affects the weapon. This way if we want to add a new star to a weapon all we need is to add a new ex ElementalDamageStatSO object instead of new enum.
Still i should have created a better example. Sorry about that 😅
Will this work after a game build and between runs?
Yes it should 👍
Great video!!!
I have two different weapons, both of them attaches to the same weaponSlot but only one weapon matches perfect in the players hand after some transform tweaking with the empty gameobject attached to the hand. How do I make it so both weapons match perfectly in the hand?
I'm not sure since I mostly work in 2D.
What I usually do is to ensure that the weapon has a parent object which defines its offset so that it matches a singular attach point on the player.
In case you have a significantly different weapon you would need a new animation anyhow so I would add a secondary attach point on the hand of the player.
There might be other ways to solve it.
@@SunnyValleyStudio I'll try the parent object way. Thanks a lot for replying!
I've watched a couple of your vids and I think they are great, keep it up! :)
i found it a bit confusing.. I've been looking for a way to reference a scriptable object exactly like what you did in the video, and I can't seem to find any part where you reference it, I mean scriptable object is an asset, how did you get the reference?
Hey!
SO is just an asset that we can drag and assign through the inspector or create art runtime. What I do in the vid around 7:05 is have the pickable object (weapon models) have the reference to the SO - it represents the weapon data. In OnCollisiont / OnTrigger the data is passed to the player so that it can process it.
@@SunnyValleyStudio I see, I might have misread what you did.. I think i have got a grasp on it, Thanks!
For the weapon manager script ,you could simply create an array of prefab references (That's what arrays are for) and cast enum to int to access the respective index
=> no need to use the switch statement
For default, you should always have None
All you have to do now is add another enum
Sure. To add another enum you need to edit the code that works perfectly fine. To add another SO all you do is create another subclass = more object oriented solution.
You could do exactly the same thing without SO but rather by using prefabs, inheritance and polymorphism.
What we get is easy way to extend the functionality without touching the old code that works.
There’s another problem with the enum solution - Unity serializes Enums as integers not as strings. So if you have multiple developers working on the project, then the order in which the enum types are added matters. If a merge conflict is incorrectly resolved, then you have broken references
You could have skipped all of this and had a c# script with this data in it named "Weapon" on your weapon prefab... SO are in no way a replacement for enums, your original design was just strange
Good point! Thanks for the feedback 👍
How did you even think using enums as weapons would be a good Idea at all?
Hey! Thanks for the feedback.
Enums are great for prototyping and for teaching beginners. I myself included learned how great "enum" is for defining type. That was until it wasn't since I needed to add extra operation to my types that differed.
Anyhow remember that not everyone is at the same programming level as you. Some beginners needs to learn that there is a better OO way to define types than enums. That is my target audience for this vid.
This is nice in theory, but we usually end up using enums anyway for things like weapons. Enums are easier to serialize for game saving and networking. Also queries like "does the player own this specific weapon/item/card?" are much simpler with enums.
Yes. Definitely enums are easier to use and if you remember to add NONE case if you need null value equivalend and always add a new enum at the end they will work for most cases. The issues begin when you start using a switch statement to handle some logic based on the enum type + you have a need to constantly add new enums.
I assuer you that I use enums to prototype ex 3 units in a simple RTS. But whenever I want to move forward and have all the units perform different attacks ex "Range shot", "Move close and melee attack" and others I would never use a switch checking the unit enum type. I would always go for an inheritance / composition based solution where I can call Unit.Attack() where ex Attack is an abstract method.
@@SunnyValleyStudio You're right, there are definitely certain drawbacks to using enums. But we use them just as IDs for relatively static sets of items, so for instance, we have our weapon logic in classes that have a WeaponId property. We don't really need any switches except for switches in factories. So I think sometimes it's fine to break the "do not use enums for anything that can change" rule. But as always, it depends on what you're trying to achieve. You can often get away with using plain enums but there are many situations when you need something more sofisticated, that's for sure.
24.000!
Thanks for support! 🙂
It just looks like you made a bad use of enums in the first place in my opinion 🤔
Yeah that is true. I could have come up with a better example. In my latest Inventory System tutorial I show how to add *Item Stats* and making those into SO instead of enums allows us to place an SO Reference on a list of *stats to modify* and assign the specific stats to an *item stats list* ua-cam.com/video/uKTLyjaF4hA/v-deo.html. The point is that now instead of modifying the enum we create a new *ItemStatSO* subclass and we can add it to our lists and easily modify/add the stats to the items without having to modify any code.
Thanks for watching and for your feedback!
A. Enums are already extremely developer friendly have the same overhead as an int. There is absolutely, 100%, no reason to replace them with a scriptable object.... especially taking in to account the effort to create and implement the scriptable object is much more that creating and maintain an enum.
B. It seems like almost every Unity developer is extremely desperate to jusifty the existence of scriptable objects, but the truth is there is none. They don't make anything easier. People want them to, they hear someone else that wants them to just as much say they do... But they don't.
They don't even negate the need to write in C#.
You absolutely know that people are desperate when they even consider suggesting replacing enums with them.
If you have the option of using enums or an entire scripted object, please use enums. Every other developer will thank you AND you will learn how to program in a way that can scale without being a horrid waste of time and system resources.
You definitely have a point there. I have been using SO for a while and while they have a lot of uses using them instead of enums doesn't work that great. Sorry about that.
Don't get me wrong this is still valid point. I would just skip use of SO. If you add a new enum you have to also change every Switch / If statement. When you add a new object that implements some common abstraction you never modify a line of the old code that deals with the logic of "what it is". You just add a new Weapon ex Bow and the Bow class creates a projectile when it receives Weapon.Use() call. No need to modify any previous working code - risking that it will stop working.
Here is a better use case for SO where we use it to split the dependency between Health system and health UI by using SO to implemented a more Data Oriented design ua-cam.com/video/6deqAk3jypo/v-deo.html
I am glad to read your comment and find I am not crazy, I have been programming as a fullstack web dev for over a decade and started playing around with Unity recently as a hobby. I was wondering why I should use SO for anything, every time I need to make a small maintenance in the code I had to click through every SO and change it manually, I can't imagine having hundreds of items made on it.... as a solo dev I found a better option to manage hundreds of items data in a Google Spreadsheet and by a script call generate a JSON and add into the resource folder, then at initialization create a Dictionary to be accessed anywhere by ids directly.
Why Unity developers use public variables instead of properties? This is not a C# convention. If it's public, it should be property, otherwise, field.
Why people don't want to watch longer 20 video tutorials but expect to learn about creating OOP code that utilizes SOLID principles and design patterns in a 5 minute video? Why can't I make longer courses where I can explain everything step-by-step but I have to limit videos to 10 min to get any traction on YT?
Hint: People on YT don't want to watch longer vids and it's much faster to write "public int myInt" compared to explaining why to use properties because the average viewer will switch to the next vid mid explanation.
Anyhow thanks for the feedback. I will do my best to use properties instead in my future vids!
@@SunnyValleyStudio Thanks for reply. What I meant by that is that I see this style of writing from many Unity developers, not just you.
And writing property is actually faster if you use Visual Studio. Type word "prop" (without quotes) and press tab twice.
Properties also have some advantages.
@@flyingdutchman2692 It's because public fields, unlike public properties, get serialized in Unity. Meaning you can modify their values in the editor. Alternatively, you can use a private field with a [SerializeField] attribute and use a property with a public getter to access said private field from other classes. But that's usually not worth the hassle... It's just unneccessary noise. Public fields are often good enough. Gamedevs usually have this pragmatic, "get stuff done quickly" mindset, they don't care if they use a public field instead of a property, they're not afraid of "anti-patterns" like singletons etc. If it works, it works.
@@cfffba Wait, what? You can't use public property as SerializeField? This is completely fake info.
[field: SerializeField] public int MyProperty { get; set; } -> and entire property (except serialize field part) was created for me, just by typing prop.
@@flyingdutchman2692 Well that's just syntactic sugar for using an attribute on the backing field of a property. Public properties are not serialized by default in Unity (without using an attribute).
enum and switch always smells
Looking back at this video I think it still is relevant but I do think that enums and switch statement has their place for enumerating more static things like Directions or things your set through the inspector. Like when you have a designer set a season that a crop grows in it is quick and easy to create an enum {Winter, Spring, Summer, Autumn} and expose it 🙂
I guess this seems fine for small projects.
I personally dislike the idea of manually adding scriptable objects and having to drag them around in the editor.
With better game logic and enum use it should be easy to add a new weapon without having to do anything manually, other then write some text data for the new weapon.
Your Enum should probably be Melee / Ranged. That way it's not going to change. Axe / Sword logic should be the same, since they are handled as Melee weapons.
If the axe is different in some way form the sword, just add an AxeScript to the gameObject or something. Easily done with a switch in script or by putting it on your prefab in the editor.
Thanks for sharing feedback! I love to learn how thinks about SO used this way.
You are right. C# wise it is nothing new or better. Even worse it is Unity specific solution if you use So.
I don't agree with "small project" approach. The whole point here I think is that people who don't know how to code can easily swap around So by dragging them. By all means you can do it with a Type object pattern and a prefab that is a data object.
Not a fan of enum unless it is a cardinal direction or sth else that really doesn't change. Any other case it would be a strategy pattern or any other oo approach.
@@SunnyValleyStudio I think you hit the nail on the head with: "People who don't know how to code can easily swap around SO by dragging them".
I'm also learning, but I prefer to learn how to code in c# rather than learn Unity.
In any case, it's good that you show how you can use SO in a game.
SO is good replacement for ugly Singletons, and can be used for global event systems. Watch video about SO at official Unity channel. In fact ScriptableObject is instance of a class and in the right hands can be very useful tool.
Why would you stop using enums? Enums are fantastic!!
Hey!
Definitely keep using them when prototyping / having a cardinal direction enum where you know that there are no more directions to add.
I wouldn't use them for anything like "UnitType" because you have ex 3 enums {Soldier, Worker, Boat} and next you suddenly remember that units can interact with Boxes that are immovable but your logic expects an enum type check so you add {None} to it. If you add it in the front ex {None, Soldier, Worker, Boat} and you have some serialized values in the inspector all the GO that had Soldier type will have None. Also if you have a switch statement checking the type now you need to modify it.
That is why beside prototyping I would always choose an Object Oriented solution using Scriptable objects or inheritance and create a new subclass while my general logic works on the base class (or nowdays I would try to implement composition first).
I hope that it answers your questions!
If you were to use enums properly, it would solve most of your problems!
Maybe you are right. Still is seems to me like using enums always ends us as "Primitive Obsession" code smell later on in the project. We always need more data to go with the enum value refactoring.guru/smells/primitive-obsession
@@SunnyValleyStudio I think you're right in this example. Though if you designed your game ahead of time, you would find some things where enums would be a good fit. For example if you were only going to have sword, axe, hammer as weapon types and thats it, because you completed the design ahead of time. Then an enum for weapon type on your SO's might be handy. Then later you add a talent system where if you are using a weapon SO with weapontype.hammer you get +10% hammer damage. Stuff like that can still make sense. I think the big difference is not tying lots of dependent code to the enum. So like the weapon manager probably shouldn't care what type it has, but a talent or something else later might care, and it can go find out.
SO is a unity tool. You have your purist blinders on. SOs are way more useful when managing a team. Solo devs can do what they feel comfortable with ultimately but please don’t downplay the usefulness of SOs when it comes to workflow and project iteration.