Stats in Unity - How I do it!

Поділитися
Вставка
  • Опубліковано 30 лис 2022
  • Every video game needs stats for players, enemies, npcs, or weapons and armor. How you structure stats for your Unity project can make things easier or harder... So I thought I'd share how I'm doing it.
    Follow Up Video on Upgrades : • Upgrade System in Unit...
    Video Links
    ************
    Odin Inspector (you know you want it): assetstore.unity.com/packages...
    Sirenix SO video: • Scriptable Objects: Wh...
    Code Monkey SO video: • Be CAREFUL with Script...
    Unity Stats Blog Post: onewheelstudio.com/blog/2022/...
    Support the Channel!
    **********************
    ► Buy me a coffee: www.buymeacoffee.com/onewheel...
    ► Shop the Unity Asset Store (affiliate): assetstore.unity.com/top-asse...
    ► Become A Channel Member: / @onewheelstudio
    ► Or a Patron: / onewheelstudio
    ► My video and streaming kit: kit.co/onewheelstudio/tutoria...
    ► Buy a Game Design Book: kit.co/onewheelstudio/game-de...
    Video Gear List (Amazon Affiliate)
    ***********************************
    ► Sony A6100 Camera: amzn.to/32logXz
    ► Sigma 16mm 1.4 Camera Lens: amzn.to/3KA4Wr4
    ► GoXLR (audio interface): amzn.to/35dmr03
    ► Shure SM7B Mic: amzn.to/3fNbV1E
    ► Blue Mic Arm: amzn.to/3tHgwdQ
    Neewer Light: amzn.to/3rD8eRv
    Light Softbox: amzn.to/3GUaHgQ
    Neewer RGB Light: amzn.to/3rCTQJ9
    Other Links
    ************
    Discord: discord.onewheelstudio.com
    Twitter: / onewheelstudio
    Devlog: onewheelstudio.com/
    Twitch: / onewheelstudio
    Timestamps
    *************
    0:00 Intro
    #GameDevelopment #Unity3D #indiedeveloper

КОМЕНТАРІ • 43

  • @Daeniak57
    @Daeniak57 Рік тому +1

    Hey, just writing a comment here on a more recent video, I was checking the observer pattern video and it was really clear. I might check this one later because I'm interested about it
    Thanks for explaining everything so clearly !

  • @richardrothkugel8131
    @richardrothkugel8131 7 місяців тому +1

    Your videos are so valuable to me. I'm a decent coder, but I don't spend that much time researching coding solutions. I'll generally just use the knowledge I have to hack together a solution (that isn't necessarily the best). Every time my hacked together solution starts to buckle, I'll scroll through your videos to see if there is a better way, and usually there is. Your coding patterns videos and tutorials are some of the most valuable programming content on UA-cam. Looking forward to your future content.

  • @siklus6177
    @siklus6177 Рік тому +1

    Good info on SOs, thanks. Looking fwd on how you tackled the "CodeMonkey" problem.

  • @EEEdoman
    @EEEdoman Рік тому +2

    How I ended up here? Just like how you imagined, looking up how other people do it - though I'm pleasantly surprised you came to the same conclusion I did: Dictionaries. Great stuff, looking forward to the next video you teased here that'll include the problems you had with the ScriptableObjects and your upgrade system!

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

    I love scriptable objects also. For a Genetic AI unity project I have been making I couldn't figure out how to use it. I needed new stats that is a random value of two other game objects stats then a random chance of changing + or -. I was not able to figure out how to make a new scriptable object while in game. Only know in editor. So used stats that were part of the movement of the AI. Your videos are great. Just found your channel and used your RTS camera for this project.

  • @simonnordon8421
    @simonnordon8421 Рік тому +8

    I had a thought to basically have a stat modifier stack, which is a list of stat modifier commands. You have your base stats, set in stone and serialised in the inspector. Then as buffs/debuffs are added the object it they're added to that stats modifier stack. Each time a stat is read it's pulled through the modifier stack to produce the actual value. Added benefit is it also stores which modifications have been applied to the state. Of course you would have a quick read buffer for the calculated stat when no recalc is required.

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

      This is pretty close to what I ended up creating (in the next video). I didn't cache value but that could be a nice addition to my system with a little extra logic.

  • @halivudestevez2
    @halivudestevez2 Рік тому +2

    What I have also added to my statvalues:
    - unit (KG, HP, XP)
    - label for display
    - value limit [0..100] - but yes, what to do if I upgrade my hero's shield, how to raise the upper limit? needs a solution
    - valuechanged event - useful to change display scores/stats or check for ... death or level up events.

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

    i like the way you cut the video with a slight "One Wheel" pause.

  • @windwalkerrangerdm
    @windwalkerrangerdm 8 місяців тому +1

    I use a combination of scriptableobjects and systems that consume them to sort of achieve instance-based entity-component-system architecture. each instance of unit (say, enemies) start with same stats, then different systems consume them (health, enemyMovement, targetDetection etc.) to monitor and upkeep instance-based values for each of these. It's not perfect but it's working.

  • @thepolyglotprogrammer
    @thepolyglotprogrammer 10 місяців тому

    Good job and thank for sharing! I am writing a stat system for a game now just like you I am doing a little research to see what is our there and that is how I found your video.
    If I may say, the one thing I did not like is when you used an ENUM for the Stat Types. I even saw that you added a couple of "Unused slots" in the enum in case you needed yo squeeze in more stats in the future. Personally I do not like to use ENUMs for things that may change in the future. When that is the case specifically in Unity I either set a arbitrary value to the enum items like 100, 200, 300, this way is very easy to squeeze in other values in the middle without others losing their prior values. Or even better, since you are already using Scriptable Objects here, you could also create a StatTypeSO that just defines the different stat types. This way you also get the benefit of being able to create new stat types entirely in the editor without having to refactor any code and add items to an ENUM.
    Either way, good video! Subscribed!

    • @OneWheelStudio
      @OneWheelStudio  10 місяців тому +1

      You’re totally right on the enums. I like the simplicity but there are potential big downsides. Assigning values is a great way to avoid most of those downsides. Love it.

  • @SojoTaku
    @SojoTaku Рік тому +1

    Noice!!

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

    I was using SO's for upgrading my stats & so that i can show them easily in UI just by referencing the data. But this caused me requirement to reset values every time i start the game meaning setting it to the default values too. But that caused to have "a lot of" values for defaults & currents.

  • @WeslomPo
    @WeslomPo Рік тому +2

    In get method is best to throw an error. Not gently show message - it will be ignored with time. This thing need to blow up early. Also it can be written in four lines 'if (Try)
    return ...;
    return 0;' else are bad. In our project we name method with "Get" - that will throw error if it can't find a thing. And we call method with "Find" if it can't find and silently return default value.
    Also there are a problem, that you need to diffrentiate a static data and real data. You made a point in the end of the video about it, but it need to be more explicitly. You have two version of data - static - that never changes between run, and real data - that may change in run. Static data is your database, real data is your gameplay data. Before use, you may wan't to convert static data to real data. Point is that static data can be in other format - like in yours it is a some kind of dictionary in scriptable object, but real data can be anything realy. May be fields in class, objects from database (sprites/prefabs etc). So it will need to be initialized.
    We store our data in components, because we use ECS pattern with Entitas and this is just a convinient way.
    Nice video. Subscribbed :)

  • @OneWheelStudio
    @OneWheelStudio  Рік тому +1

    Upgrade Video: ua-cam.com/video/HuI3vcMIggM/v-deo.html
    Stats in Unity Blog Post: onewheelstudio.com/blog/2022/11/8/how-i-do-stats
    Upgrades 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
    Sirenix SO video: ua-cam.com/video/W5ECIJyoW80/v-deo.html
    Code Monkey SO video: ua-cam.com/video/5a-ztc5gcFw/v-deo.html

  • @RK-dj9wf
    @RK-dj9wf 8 місяців тому

    i am having an issue where I used your code for the stats class, I copied your code exactly so that I could edit and alter it where needed but decided to just run a test(with all the upgrade information that is used in the next video mostly commented out!) and for some reason I am getting an error I cant seem to figure out where its not finding the namespace Stat which i find odd.....

  • @MalikenGD
    @MalikenGD 8 місяців тому

    Hey, around 3:25 onward you talk about if you upgrade your tower, all towers can be affected easily because they all use the same scriptable object. My question here is how? Are you changing your scriptable object's data at runtime (which I hear you typically don't want to do?) and polling it from the towers? Or what are you doing here to propagate the upgrades to all of your towers?

    • @OneWheelStudio
      @OneWheelStudio  8 місяців тому

      The real danger with SOs at runtime is thinking of them as a save system. It can also get a bit messy in the editor, but there are ways around it. So bascially I clean out any changes when the game stops. Probably other ways around it. I might restructure things but for now it's working.

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

    SerializedScriptableObject is a class provided by Odin inspector? I wonder how did you provided an enum in the Inspector

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

      Odin Inspector is a third party asset it's great: assetstore.unity.com/packages/tools/utilities/odin-inspector-and-serializer-89041?aid=1100lHSw
      As for the enum, they should show up if they are public or serialized. In my examples, I'm using an enum as the key to a dictionary - the dictionary only shows up because I am using the SerializedScriptableObject.
      Hope that helps.

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

    The upgrade system at 1:24 looks very cool, is there a video where it is being built?

    • @OneWheelStudio
      @OneWheelStudio  Рік тому +1

      Yep! Here you go: ua-cam.com/video/HuI3vcMIggM/v-deo.html

    • @kucirulz
      @kucirulz Рік тому +1

      @@OneWheelStudio so in the next video :D sorry for being impatient and cheers!

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

      No worries. YT doesn’t do an awesome job helping with that kind of stuff.

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

    I don't really agree with you on the "SO's should not be used as a save system" statement. Serializing class based data as a save system is basically the same as serializing SO data, but SO's give you the option to give access to said data to a bunch of different places simultaneously like you mentioned.
    I've been using SO's as a framework for tying together systems using shared data and even events/signals for a while now in various client projects and I love the flexibility it gives you.
    With some special parsing I even use it for practically seamless streaming and storing said data to the cloud.
    I'd love to hear your thought though

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

      To paraphrase @CodeMonkeyUnity video: The issue is that in the editor an SO can work like a save solution. Simply set the value of a variable and that value is there when you leave play mode or when you open up your project at some later date. But in a build, changing the value of a variable on an SO isn't persistent. You can't save a level or a player state. This can be a huge bummer if you've worked on a game for months before testing in a standalone build.
      This is the pitfall that myself and Code Monkey are trying to help folks avoid. I've got a link to the Code Monkey video in a pinned comment and in the video description. it's worth checking out.

  • @sebastianecheverry4458
    @sebastianecheverry4458 3 місяці тому

    Hi, I have a question. Where I see the source code of this video to be able to follow along better?. Im unable to find the SerializedScriptableObject part

    • @OneWheelStudio
      @OneWheelStudio  3 місяці тому

      SerializedScriptableObject is part of Odin Inspector.

  • @ninosandlarz783
    @ninosandlarz783 Рік тому +1

    I noticed that all your stats are of type float, how will you do if you need other type of stats, like for example vector3 or color ?

    • @OneWheelStudio
      @OneWheelStudio  Рік тому +1

      In my project I've added other types, but that does mean I needed additional ways to access those types. In my case I had a list of terrain types. I just made the list public. Not fancy, but it does the job.
      But if you have colors or vectors you could create additional fields and or additional dictionaries depending on how many of each type you have and what makes sense. There are a ton of edge cases!

    • @arthurborges7313
      @arthurborges7313 Рік тому +1

      I Think you can get more generic by creating a generic class that holds the stat type and the stat data itself by the generic type. That way you only need a list of this stats class or a dictionary with the stat type as key. After that you need to create some methods like UpgradeFloat or UpgradeColor, for example, to do the calculations and only need to call for a Upgrade method on the upgrade class and with a generic parameter as the value to be changed.

  • @MrHandsy
    @MrHandsy Рік тому +1

    Can I try to brainstorm a stat system with you on Discord? I have a few ideas along the lines of this, but with a few modifications.

    • @OneWheelStudio
      @OneWheelStudio  Рік тому +1

      For sure. Make a post in #gamedevhelp and ping me I’ll make sure to take a look.

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

      @@OneWheelStudio I had to find this message before YT doesn't alert me to these. jeez lol

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

      @@OneWheelStudio I am Danny Algorithmic

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

      How do I ping you in Discord? I cannot find your name

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

    creating instances of scriptable objects for every game unit sounds bad. Why not a class which have ref to blueprint scriptable object?

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

      The SO is per unit type. Not per unit in the scene - just to make sure we're on the same page. So the prefab of each unit has a reference to the SO for that type of object. Maybe this is what you were suggestion?

    • @nightyonetwothree
      @nightyonetwothree Рік тому +1

      ​@@OneWheelStudio ah, i miss this part. My bad

  • @docelapohudektypekpodleme8065
    @docelapohudektypekpodleme8065 2 місяці тому

    Honestly, this video is so confusing to me, that I don't even know what I'm looking at.

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

    I know it sounds so cliche to read these comments, BUT I was JUST working on my current iteration of stats. I found this at the perfect time, YAY for not working too hard on it last night. I also needed a base stats and unit stats, but a contructor or something to give me the combine stats would work. (Yet to see how you handle this in your Upgrade video.)
    System.Linq can parse a list, a bit easier, not sure HOW much a performance improvement, but would mitigate the list use case.
    Thanks for coming out with GREAT videos, sometimes at the perfect time.
    My first shot, not tested.
    using System.Linq
    StatInfo localStatInfo = stats.Find(a => a.StatType == sType);
    if (localStatInfo != null) return localStatInfo.Value;

    • @NadjibBait
      @NadjibBait 6 місяців тому +1

      LINQ is definitely slower than a simple for/foreach loop (and most of the time allocates memory). Also Find is not a LINQ extension, but it's part of List, the equivalent (and slower) versions in LINQ are First/FirstOrDefault, Single/SingleOrDefault.
      TLDR: Avoid using LINQ in hot paths (Update()...etc).