Pointers on using a Class Constructor to set up some stats.

Greetings,

Hoping somebody can nudge me in the right direction because I am going around in circles and unsure of what I am doing wrong.

I am trying to create a base class for stats, and then using that class create some player stats, economy stats, etc in different scripts that derivce from the main stat class.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[System.Serializable]

class Stat
{
    private string StatName;

    private int StatSlot;

    private float StatXP;

    private int BaseValue;

    private int MinValue;

    private int MaxValue;

    private int CurrentValue;

    private int FinalValue;

    // Constructor with Input Paramters for 'Standard' stat class. 

[System.Serializable]

    public Stat(string _statname, int _statslot, float _statxp, int _basevalue, int _minvalue, int _maxvalue, int _currentvalue, int _finalvalue)


    {
       StatName = _statname;
       StatSlot = _statslot;
       StatXP = _statxp;
       BaseValue = _basevalue;
       MaxValue = _maxvalue;
       MinValue = _minvalue;
       CurrentValue = _currentvalue;
       FinalValue = _finalvalue;
    }

   
}

Then in a sepeate player stats class - I am trying to create a new stat - that lets me set adjust these values on a per stat basis.

E.g for Stamina

public Stat Stamina = new Stat(ā€œStamina,1,0,0,0,0,0ā€);

Which would be a new stat called Stamina, with a stat slot of 0, 0xp, 0 base value, 0 max value, 0 min value, 0 current value and 0 final value.

I would like to be able to write in the player stats script

New Stat Stamina
New Stat Strength
etc

Then be able to adjust each stats parameters.

I am clearly doingn something wrong but Iā€™m confused about where I am going wrong.

Any pointers would be greatly appreciated.

Thank You for any help you can offer.

You say youā€™re doing something wrong, but you havenā€™t actually said specifically what isnā€™t working. Care to elaborate on that?

2 Likes

That sounds like a nightmare of boilerplate infrastructure code to support, especially since you mark it serializable!

Since itā€™s serializable, just initialize it from JSON, not that unusual CSV-like format you have above.

Alternately, why not consider just using ScriptableObjects for all this stuff?

Yeah it sounds like what youā€™re describing should work just fine.

One tweak I would make though would be to define an enum for the different stat types, instead of relying on strings for several reasons:

  • It is easy to make typos with strings.
  • Enums are exposed in the Inspector as convenient popups.
  • You get compile errors if you try to reference stat types that no longer exist in your code.
  • Your code IDE can auto-generate switch statements that contain all different stat types with enums but not with strings.
public enum StatType
{
   None = 0,
   Stamina = 1,
   Strength = 2,
   ....
}
[Serializable]
public class Stat
{
    [SerializeField]
    private StatType type;
    ...

    public Stat(StatType type, ...)
    {
        this.type = type;
        ...
    }
}

You could also consider making your PlayerStats class be a ScriptableObject.
This could make it easier to tweak the values on-the-fly in play mode, easily make backups of your stats and swap them out at will etc.

[CreateAssetMenu]
public class Stats : ScriptableObject
{
   public Stat stamina = new Stat(StatType.Stamina,1,0,0,0,0,0);
   public Stat strength = new Stat(StatType.Strength,1,0,0,0,0,0);
}
1 Like

Be veeeeeeeery careful with enums. I recommend not using them and here is why: Unity does NOT serialize enums semantically. They are just stored as an integer. Hereā€™s my blurb:

Enums enums are bad in Unity3D if you intend them to be serialized:

https://discussions.unity.com/t/809088/4

https://discussions.unity.com/t/817068/2

It is much better to use ScriptableObjects for many enumerative uses. You can even define additional associated data with each one of them, and drag them into other parts of your game (scenes, prefabs, other ScriptableObjects) however you like. References remain rock solid even if you rename them, reorder them, reorganize them, etc. They are always connected via the meta file GUID.

It feels like over-design ā€“ youā€™re figuring out a complicated way of storing complicated set of values without knowing how or even if you will use them. Itā€™s often better to start with just any simple structure; then write your program. Then youā€™ll realize things like ā€œI want what they do to be in a different area from how they improveā€, or ā€œthe stats-improve-by-using idea is boring, unfair and I hate itā€; or ā€œIā€™ll need a much more complex system for temporary stat buffs and debuffs. So complex I think I may need to simplify my ideaā€.

1 Like

True, enums are serialized using the underlying value, not the name, and it is very important to be aware of this fact.

This is the main reason why I tend to almost always explicitly specify the values of enum members. If you do this then you can remove existing members or add new ones even in the middle of an enum without having to worry about possibly altering the underlying values of other members.

Hello everybody, thanks very much for all of the input so far.

Iā€™ve been working on a system that allows me to do a couple of different things in different places with my planned attrributes, stats and other variables.

I am planning to use them in three main ways:

To define the availability of certain interactions - based on raw input values of the players ā€˜currentā€™ status.

To drive the result of a given action on an object.

To determine the availability of certain dialogue interactions and quests.

Then to use these stored variables that are persistent across interactions, conversations and quests to display UI elements.

Iā€™ve been trying to structure my data and variables in such a way that I can use the ā€˜storedā€™ version of a player attribute, or boolean flag to then hook into Dialogue Sysem for unity and some of the MMFeedbacks, MMTools and Top-Down engine features.

Originally I was storing all my of variables within the dialogue system database, then using an on use trigger and conversastion tree - to drive the core functions of my prototype.

This allowed me to esatblish my core bevahiours - for example - I had set up a couple of quests and a couple of interactible objects.

I had quests - that relied on obtaining items and handing them in to receive a reward to cash or increase a certain statistic.

I had actors in place - that would allow for you to inspect your current stats or ā€˜trainā€™ a stat by selecting a branch in the conversation tree.

The limitations of storing my variables on the dialogue system database was that I was unable to then easily access and use those variables in other areas.

So, I took a few days to try and familiarise myself more with fundamentals of scripting with c# and some of the basics of C# to drive behaviours.

I think I ended up in a situation where I was trying to set everything up all at once - and mentally was mapping many seperate systems into one big confusing web of ideas.

Having looked again at scriptable objects, and watched the two unity presentations on the benefits of scriptable objects as data containers - I am going to take a different approach and try to break everything into smaller modular elements.

I think the things that are confusing me most currently - are how I can take the data I am defining and using at runtime in a scriptable object and return the updated variables and have that stored somewhere in a persistent way.

I think what I will end up with, is a manager script for each of the different types of data that I then store on my game manager.

Iā€™ll spend a few more hours today looking at everything with a more modular and systematic approach and if I encounter any difficulties pop back for some help.

I believe that it is difficult for me to communciate clearly what I am trying to accomplish because I am intertwinining many different proposed behaviours into one ā€˜wholeā€™ system - when I should be focusing on establishing individual elements of the ā€˜webā€™ and then linking it all up afterwards.

Scriptable Objects definitely seem like a sensible place to start - thanks again for the input as it definitely helps me in terms of working out where I am going wrong - and particularly @Owen-Reynolds observation of over-design hits home.

2 Likes