Fantastic video! Was looking forward to this. I also find it funny you also came to the same conclusion of using events to notify of upgrades for classes that may care about it, like I did.
I love events. Maybe too much. 😊 I really like them in this case and in general as they can let you add functionality without messy coupling. Glad you liked the video! 🙏
Idea for the saving problem with scriptableobjects: just create a base scriptableObject called ResetSO that at OnEnable clones itself into an instance. Then use the instance to make changes. This way you always adjust changes to a clone and treat the scriptable object to start with as a preset
Great video as always. I would like to point out a (possibly) unintended side-effect. At 4:58, the code for applying upgrades is iterating through the list; this means the order of upgrades matter. If you start with 10 base damage, then get a +5 damage upgrade, followed by +100% damage upgrade, you'll end up with 30 damage. However, if you received the +100% damage upgrade before the +5 damage upgrade, it will be 25 damage. How would you handle this? Perform two foreach loops, first accumulating the non-percent upgrades, and then in the second foreach loop, compute the multiplier? Also, the dictionary is limited to one type, float in this case. Would storing ints, such as Level or CoinsCount, cause any issues?
My intent was to have the order of upgrades matter. If you are going to mix things like +5 damage and +10% damage I think something like this is inevitable. I think the solution might be to simply not mix and match types. So if you have +5 damage you don't also have +10% damage. As for the dictionary, yes the value is limited to one type. You could make it a more general type like an object, but that seems a bit silly in this case. I wouldn't expect an issue with storing ints in a dictionary of floats. I would assume that the ints get converted to floats, but if you really need to ensure that particular values are ints you could always round them to ints when you need to use the value.
I would just sort the list every time an upgrade is added. Multiplications at the end, so the player always has the most gain, no matter when he buys which upgrade. Feels most fair to me.
If I understood it correctly it seems like you are modified ScriptableObjects at runtime, which I'm personally not a fan of as I see them as static and non dynamic data containers which shouldnt be changed often at runtime. But other than that the system is pretty great and you can of course rebuild it with having the ScriptableObjects as non-changeable in mind.
Plenty of folks out there using scriptable objects for runtime use cases. There are two famous Scriptable Object talks that cover it on Unity channel and there are a few frameworks for implementing some of those ideas like Unity Atoms.
would love to see more use case of odin inspector ... I've bought it for years but ...i only know how to use the simple stuff....and simple stuff aren't worth the effort to instlal the package....
✅Nova UI (Paid): assetstore.unity.com/packages/tools/gui/nova-226304?aid=1100lHSw
✅Nova UI (Free): assetstore.unity.com/packages/tools/gui/nova-free-trial-231156?aid=1100lHSw
📝Blog Post: onewheelstudio.com/blog/2022/12/13/upgrade-system-stats-part-2
✅Odin Inspector: assetstore.unity.com/packages/tools/utilities/odin-inspector-and-serializer-89041?aid=1100lHSw
📽Stats Video: ua-cam.com/video/B2JsymHzgvE/v-deo.html
📽Code Monkey SO Video: ua-cam.com/video/5a-ztc5gcFw/v-deo.html
Always wondered your way with using editor tools! Great video as always
Fantastic video! Was looking forward to this. I also find it funny you also came to the same conclusion of using events to notify of upgrades for classes that may care about it, like I did.
I love events. Maybe too much. 😊 I really like them in this case and in general as they can let you add functionality without messy coupling. Glad you liked the video! 🙏
Awesome video!
Nice work :D yet another great video.
Idea for the saving problem with scriptableobjects: just create a base scriptableObject called ResetSO that at OnEnable clones itself into an instance. Then use the instance to make changes. This way you always adjust changes to a clone and treat the scriptable object to start with as a preset
very good video from ows again
Great video as always. I would like to point out a (possibly) unintended side-effect. At 4:58, the code for applying upgrades is iterating through the list; this means the order of upgrades matter. If you start with 10 base damage, then get a +5 damage upgrade, followed by +100% damage upgrade, you'll end up with 30 damage. However, if you received the +100% damage upgrade before the +5 damage upgrade, it will be 25 damage. How would you handle this? Perform two foreach loops, first accumulating the non-percent upgrades, and then in the second foreach loop, compute the multiplier?
Also, the dictionary is limited to one type, float in this case. Would storing ints, such as Level or CoinsCount, cause any issues?
My intent was to have the order of upgrades matter. If you are going to mix things like +5 damage and +10% damage I think something like this is inevitable. I think the solution might be to simply not mix and match types. So if you have +5 damage you don't also have +10% damage.
As for the dictionary, yes the value is limited to one type. You could make it a more general type like an object, but that seems a bit silly in this case. I wouldn't expect an issue with storing ints in a dictionary of floats. I would assume that the ints get converted to floats, but if you really need to ensure that particular values are ints you could always round them to ints when you need to use the value.
I would just sort the list every time an upgrade is added. Multiplications at the end, so the player always has the most gain, no matter when he buys which upgrade. Feels most fair to me.
If I understood it correctly it seems like you are modified ScriptableObjects at runtime, which I'm personally not a fan of as I see them as static and non dynamic data containers which shouldnt be changed often at runtime.
But other than that the system is pretty great and you can of course rebuild it with having the ScriptableObjects as non-changeable in mind.
Plenty of folks out there using scriptable objects for runtime use cases. There are two famous Scriptable Object talks that cover it on Unity channel and there are a few frameworks for implementing some of those ideas like Unity Atoms.
would love to see more use case of odin inspector ...
I've bought it for years but ...i only know how to use the simple stuff....and simple stuff aren't worth the effort to instlal the package....
damage ++; also a good upgrade system
Especially if it is called in the Update() method 😉