• Advertisement
Sign in to follow this  

Unity Generic RPG stats.

This topic is 1654 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

So I've got an idea of how I want to handle stats in my RPG, but I'm not sure if I can implement it this way.  I'm using C# in Unity.

 

All entities in my game have some physical properties which can be modified.  This is stuff like mass, density and the like.  Just as any other statistic, I want to be able to modify this with various (de/buffs).  For example, an object that suddenly gets heavier will have its mass buffed.

 

So every entity needs the ability to be de/buffed without having its base stat values messed with, and every stat needs a minimum and maximum value that the buffs can't exceed.

 

 

Specific types of entities such as characters have special stats like Agility or Willpower and junk.  These are straightforward enough.

 

But when it comes to things like vitals (health/energy), there's some issues.  Some characters can have vitals other characters can't.  (Like Death Knights in WoW having Runic Power, Warlocks having Demonic Fury, Mages Warlocks and Priests having Mana, etc.)

 

 

So when I'm buffing an entity, I have to check whether the entity has any of these stats to buff in the first place.  And another thing to keep in mind is other types of stats that may need altering without messing with the base value; Vector3s like center of mass and buoyancy, bools like whether or not a character can breathe or fly, etc.

 

How can I handle all these different stats in a generic manner?  Is it a lost cause?

Edited by Nemox

Share this post


Link to post
Share on other sites
Advertisement

For the buffing it sounds like you need to have at least two stats.  For example, intrinsic_mass and effective_mass.  The effective_mass is a final computed mass.  You'll need some mapping, probably an equation, to use a variety of inputs to compute the effective mass.  One of these inputs will be intrinisic_mass.  Thus, all of your intrinsic properties are retained.  Whenever you encounter an event that modifies the effective mass, simply re-run your effective_mass equation.

Edited by Cosmic314

Share this post


Link to post
Share on other sites

For the buffing it sounds like you need to have at least two stats.  For example, intrinsic_mass and effective_mass.  The effective_mass is a final computed mass.  You'll need some mapping, probably an equation, to use a variety of inputs to compute the effective mass.  One of these inputs will be intrinisic_mass.  Thus, all of your intrinsic properties are retained.  Whenever you encounter an event that modifies the effective mass, simply re-run your effective_mass equation.

 

Yeah, that's the easy part.  The hard part is when it comes to other types of variables like Vectors or Bools and searching for the proper stats to modify.

Share this post


Link to post
Share on other sites

It seems like it would be pretty straightforward to just save base values for each of the stats and keep the buffs/debuffs and the final values as separate variables. That way, you can for instance recalculate the actual max health (another variable) by adding up the base health and all health related buffs/debuffs in the base class any time the value needs to change. (same thing for vectors and bools; just add together base and extra vectors, then and/or together all the related bools to get the final value) If a unit doesn’t have a certain stat at all, just include a Boolean in the base class for say, hasMana to exclude it from any mana related calculations.

Share this post


Link to post
Share on other sites

I suppose if you truly want something dynamic, create a property list.  Whenever you want a creature to have a new ability/buff, register a property along with a callback function.  Use some sort of transaction object to load appropriate values from the creature object and then pass it to the registered function.  The function does its calculation, returns a value which you store on your effective list.  I just get a vague notion that such a system might become too expensive to execute.

 

If you know all possible stats in the game simply create a base class with default computations.  Override as necessary in derived classes.  Keep a list of bools to indicate which stats are present.  You could even skip the bools and override with a stub that does nothing.

Edited by Cosmic314

Share this post


Link to post
Share on other sites

Hmm...  Maybe what I need at this point is a way to reference stats as a list, but to override the property in subsequent classes.

 

For example:
Entities have Mass and Density stats.

Characters have those and Agility and Wisdom stats.

 

The AddBuff() function of an Entity would list { Mass, Density }.

But when called on a character (even when referring to its base Entity class), it should return { Mass, Density, Agility, Wisdom }.

 

Is there some way to do that instead?  Is that what override functions are for?

Share this post


Link to post
Share on other sites

Use a data driven approach:

 

Define a base Stat as a class with a field storing a semantic and a field storing the value type. Derive concrete Stat classes that add a value field of respective type. Define a base StatEffect as a class with a semantic field, a type field, and a duration field. Derive concrete StatEffect classes that add a value field of respective type. 

 

A StatEffect has an influence on the Stat where Stat.semantic == StatEffect.semantic and Stat.type == StatEffect.type; if no such Stat is attached then the StatEffect is to be ignored.

 

The stats of an object of interest then is a list / vector / array of Stat instances. The currently active buffs / debuffs are a list of StatEffect instances attached to the object of interest.

Share this post


Link to post
Share on other sites

Use a data driven approach:

 

Define a base Stat as a class with a field storing a semantic and a field storing the value type. Derive concrete Stat classes that add a value field of respective type. Define a base StatEffect as a class with a semantic field, a type field, and a duration field. Derive concrete StatEffect classes that add a value field of respective type. 

 

A StatEffect has an influence on the Stat where Stat.semantic == StatEffect.semantic and Stat.type == StatEffect.type; if no such Stat is attached then the StatEffect is to be ignored.

 

The stats of an object of interest then is a list / vector / array of Stat instances. The currently active buffs / debuffs are a list of StatEffect instances attached to the object of interest.

 

Ahhh, this makes a lot of sense!  I'll still have to do some reading and swish it around in my tiny brain for a bit, but this may very well be the solution I'm looking for.

Share this post


Link to post
Share on other sites

A very flexible system would be for the object or character to have a stat field that indicates the minimum, maximum, and current values of a particular stat. From there, de/buffs are something applied -- they would never change the current value, but the effective value of the state would be calculated from the stat and the sum of all de/buffs. The effective value can be cached for performance if necessary, but its likely not a real issue.

 

More generally, de/buffs fall under the category of status effects -- they're a modifier that applies to something based on the presence of something else. Status effects might include things like a character being poisoned, mute, unconscious, or berserk, in addition to simple stat de/buffs. For maximum flexibility, you don't want to limit your thinking to things like one status effect affects only one stat, or status effects don't interact... For example, maybe there's something called the "Ring of Power" in your game that gives you +1 STR, maybe there are "Gauntlets of Power" that give you +2 STR, maybe there's an entire suit worth of "X of Power" armor that each give you +Y STR individually -- what if you want to give the player an additional +20 STR when they have collected and equipped the entire suit "of Power"?

 

This sort of thing builds interesting choices into your game -- is it better to buy the last piece in your suit "of Power", or is it better to get that Diamond Chestplate that has better base-stats than the Chestplate of Power, but won't give you the bonus buff? Or, what if you loot a mysterious ring from a warlocks home, equip it, and find out that it's cursed! You can't take it off, and the Warlock won't remove it for you unless you pay him 5,000 silver pieces. The penalties are interesting because not only can you not equip other useful rings, the cursed thing might prevent you from ever attaining the kind of bonus buff I described above, because you'd never be able to equip a complete suit "of Power".

 

Being flexible allows you to be more creative as a designer, and to offer the player more interesting choices that have real consequences. Notice that in the above scenario, choosing to steal the ring from the Warlock was something of a moral choice, it wasn't about simply upgrading equipment. That's interesting for the player, and the experience of being bitten by their greed will have an effect on the way they play the rest of the game. Particularly in an RPG where the game is really about choices and their effects, and with a strong emphasis on stats, equipment, and customizing the character to suit the player's playstyle, it makes a lot of sense to spend time building a very flexible system into those core game mechanics.

Share this post


Link to post
Share on other sites

I've just learned of Interfaces, and I think I'm trying to do something similar.  I'm not exactly sure what the deal is with semantic types, but I know a few basic things.

 

I've got (let's say 3) types of stats:  Floats, Vectors, and Bools.  I'll need to make a Property within the stat that gets/sets the stat's value based on type.  How does one go about implementing this?

Share this post


Link to post
Share on other sites

I've just learned of Interfaces, and I think I'm trying to do something similar.  I'm not exactly sure what the deal is with semantic types, but I know a few basic things.

 

I've got (let's say 3) types of stats:  Floats, Vectors, and Bools.  I'll need to make a Property within the stat that gets/sets the stat's value based on type.  How does one go about implementing this?

 

If you want to use a property it's really easy. You could define the getter of the property like this:

 

private int strength; // This is the base stat, before any modifications
 
...
 
public int Strength
{
     get
     {
          int effectiveStrength = strength; // Creates a local variable and accounts for the base stat
 
          effectiveStrength += equipmentStrengthModifier;
          effectiveStrength += spellStrengthModifier;
 
          return effectiveStrength;
     }
 
     private set { strength = value; }
}

 

Using a property this way, any code outside of your Character class can only get the strength value through the Strength property, which will automatically account for any modifiers that can be applied. You could use a similar setter property for applying effects, where you write code that checks to see if the modifier can be validly applied and then update the relevant field. The variable type isn't too important because the accessors handle the specific implementation you want internally and you can use generic code to apply/check for effects on any entity type.

 

If you want to use an interface the approach would be very similar but you would be using a method for any class which implements your EntityStat interface (or whatever you name it). I'm not great with interface implementation myself, so I can't give you a whole lot of guidance on it. However, I'm not sure that in this case it would do what you're intending without adopting an approach haegarr suggested.

 

The semantic piece describes the "catgory" of a stat as a field of that stat class definition. This has nothing to do with variable types like int, bool, etc. So if a character has the agility stat, and something happens that would affect the character's agility, you would check the character's stats to see if any have the "agility" semantic, and if so the effect is applied. If not, nothing happens. The big advantage of this is it's a very easy, direct way of checking to see if a buff/debuff applies as opposed to trying to use a built-in variable type, like a Vector3, which won't contain the kind of information you want to use.

 

A Vector is not a stat. Bouyancy would be a stat, which it sounds like you intend to represent as a vector. Same with something like "breathes"-- that's a stat. A bool is not. If I'm interpreting haegarr's post correctly (and if I'm not, I guess I'm making a new suggestion), you would define a base class "Stat", which has a field (an enum would work) that will describe the "category" of classes derived from Stat and an integer which indicates the degree of the stat.

 

When you derive Agility : Stat, you define the semantic field as "agility" or whatever, and then set the integer any way that makes sense for your game.

Share this post


Link to post
Share on other sites


The semantic piece describes the "catgory" of a stat as a field of that stat class definition. This has nothing to do with variable types like int, bool, etc. So if a character has the agility stat, and something happens that would affect the character's agility, you would check the character's stats to see if any have the "agility" semantic, and if so the effect is applied. If not, nothing happens. The big advantage of this is it's a very easy, direct way of checking to see if a buff/debuff applies as opposed to trying to use a built-in variable type, like a Vector3, which won't contain the kind of information you want to use.
 
A Vector is not a stat. Bouyancy would be a stat, which it sounds like you intend to represent as a vector. Same with something like "breathes"-- that's a stat. A bool is not. If I'm interpreting haegarr's post correctly (and if I'm not, I guess I'm making a new suggestion), you would define a base class "Stat", which has a field (an enum would work) that will describe the "category" of classes derived from Stat and an integer which indicates the degree of the stat.

This is almost what I meant. The reasoning is described in the following. I'm not familiar with C#, so I fall back to terms used by C++ where appropriate.

 

The art of making a flexible system is to program what is needed but not more, and give the designer the possibility to make what s/he imagines, so to say. This means that you need to distinguish the types of e.g. Stat on the programming language level due to the fact that vectors needs other operators (in the mathematical sense) than scalars do. So, if you embed a Vector3 instance in a specialized type of Stat then you have another one as when embedding a scalar float in it. On the other hand, the programming language is not aware of semantic types, because it isn't interested in whether you use a float value as strength or as dexterity. So an instance of the FloatStat class can be used for strength, while another instance of the same class can be used for dexterity. To distinguish them, there is the field for the semantic type, which is set to either the constant STRENGTH or else the (of course distinct) constant DEXTERITY, in this example.

 

Up to here you, as the programmer, have avoided to derive a class for each kind of Stat; instead you have implemented a class for each kind of value a Stat may have. However, things go further. Because instances of Stat (and StatEffect) are objects, they can be collected dynamically, at design time but also at runtime if you want so. This allows the designer to attach a specific kind of Stat to a model, or to not do so. Notice please that we are leaving inheritance and entering composition.

 

In the extreme (not to be understood as the way I suggest you to implement) also the semantic types need not be pre-defined. It is possible to let the designer the freedom to define a couple of semantic types (in interrelation with choosing the belonging value type). Of course, the price for this flexibility is that the designer has more work to do, and s/he has more responsibility for the operativeness. It is an art in programming to lower the burden of this, i.e. to control the correctness of what the designer does. This requires a well done editor, for example.

Share this post


Link to post
Share on other sites

I figured out a very simple solution that I can't believe I missed before.

 

I can simply have different stat types with their own typed methods for de/buffing them, and accomodate this through my StatusEffect class/struct!  No complex interfacing necessary.

 

So like, I can have:

StatusEffect:

FloatStat   mass +1

VectorStat   centerOfBuoyancy  -Vector3.down

BoolStat   underwaterBreath   false

 

 

I suppose my main issue now is deciding how I want to set up my stats for different types of entities.  I thought about having them be "plugin" types of things.  Like, a ninja and a car both have some degree of Strength, but a car doesn't have Wisdom.  'n' such.  But this does bring about some issues regarding consistency.

Edited by Nemox

Share this post


Link to post
Share on other sites

Use a data driven approach:

 

Define a base Stat as a class with a field storing a semantic and a field storing the value type. Derive concrete Stat classes that add a value field of respective type. Define a base StatEffect as a class with a semantic field, a type field, and a duration field. Derive concrete StatEffect classes that add a value field of respective type. 

 

A StatEffect has an influence on the Stat where Stat.semantic == StatEffect.semantic and Stat.type == StatEffect.type; if no such Stat is attached then the StatEffect is to be ignored.

 

The stats of an object of interest then is a list / vector / array of Stat instances. The currently active buffs / debuffs are a list of StatEffect instances attached to the object of interest.

 

Would a visitor pattern be appropriate here?  It could remove explicit type checking.  I'm not fully sure if it would be effective / too expensive here.

Share this post


Link to post
Share on other sites


Would a visitor pattern be appropriate here?  It could remove explicit type checking.  I'm not fully sure if it would be effective / too expensive here.

Valid, for sure; appropriate ... may be ;) See, the selection of the Stat is primarily done on basis of the semantic type. Only if that type matches, the visitor mechanism would be invoked just to handle the value type. So the amount of "double dispatches" would be limited.

 

However, there is a probably more important dependency on the mechanics of the StatEffect influence itself. What to do when two or more effects of the same semantic type occur at a time? Do they add up in value? Is the maximum of all values valid? Is the stronger one active, and the weaker one temporarily appended? Depending on how the mechanic is implemented, the majority of dispatches may be inherent in here. 

 

Notice please that checking for the value type can be neglected at all, as soon as you bind the value type implicitly to the semantic type and don't need to have mixed forms.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
  • Advertisement
  • Popular Tags

  • Advertisement
  • Popular Now

  • Similar Content

    • By Manuel Berger
      Hello fellow devs!
      Once again I started working on an 2D adventure game and right now I'm doing the character-movement/animation. I'm not a big math guy and I was happy about my solution, but soon I realized that it's flawed.
      My player has 5 walking-animations, mirrored for the left side: up, upright, right, downright, down. With the atan2 function I get the angle between player and destination. To get an index from 0 to 4, I divide PI by 5 and see how many times it goes into the player-destination angle.

      In Pseudo-Code:
      angle = atan2(destination.x - player.x, destination.y - player.y) //swapped y and x to get mirrored angle around the y axis
      index = (int) (angle / (PI / 5));
      PlayAnimation(index); //0 = up, 1 = up_right, 2 = right, 3 = down_right, 4 = down

      Besides the fact that when angle is equal to PI it produces an index of 5, this works like a charm. Or at least I thought so at first. When I tested it, I realized that the up and down animation is playing more often than the others, which is pretty logical, since they have double the angle.

      What I'm trying to achieve is something like this, but with equal angles, so that up and down has the same range as all other directions.

      I can't get my head around it. Any suggestions? Is the whole approach doomed?

      Thank you in advance for any input!
       
    • By devbyskc
      Hi Everyone,
      Like most here, I'm a newbie but have been dabbling with game development for a few years. I am currently working full-time overseas and learning the craft in my spare time. It's been a long but highly rewarding adventure. Much of my time has been spent working through tutorials. In all of them, as well as my own attempts at development, I used the audio files supplied by the tutorial author, or obtained from one of the numerous sites online. I am working solo, and will be for a while, so I don't want to get too wrapped up with any one skill set. Regarding audio, the files I've found and used are good for what I was doing at the time. However I would now like to try my hand at customizing the audio more. My game engine of choice is Unity and it has an audio mixer built in that I have experimented with following their tutorials. I have obtained a great book called Game Audio Development with Unity 5.x that I am working through. Half way through the book it introduces using FMOD to supplement the Unity Audio Mixer. Later in the book, the author introduces Reaper (a very popular DAW) as an external program to compose and mix music to be integrated with Unity. I did some research on DAWs and quickly became overwhelmed. Much of what I found was geared toward professional sound engineers and sound designers. I am in no way trying or even thinking about getting to that level. All I want to be able to do is take a music file, and tweak it some to get the sound I want for my game. I've played with Audacity as well, but it didn't seem to fit the bill. So that is why I am looking at a better quality DAW. Since being solo, I am also under a budget contraint. So of all the DAW software out there, I am considering Reaper or Presonus Studio One due to their pricing. My question is, is investing the time to learn about using a DAW to tweak a sound file worth it? Are there any solo developers currently using a DAW as part of their overall workflow? If so, which one? I've also come across Fabric which is a Unity plug-in that enhances the built-in audio mixer. Would that be a better alternative?
      I know this is long, and maybe I haven't communicated well in trying to be brief. But any advice from the gurus/vets would be greatly appreciated. I've leaned so much and had a lot of fun in the process. BTW, I am also a senior citizen (I cut my programming teeth back using punch cards and Structured Basic when it first came out). If anyone needs more clarification of what I am trying to accomplish please let me know.  Thanks in advance for any assistance/advice.
    • By Yosef BenSadon
      Hi , I was considering this start up http://adshir.com/, for investment and i would like a little bit of feedback on what the developers community think about the technology.
      So far what they have is a demo that runs in real time on a Tablet at over 60FPS, it runs locally on the  integrated GPU of the i7 . They have a 20 000 triangles  dinosaur that looks impressive,  better than anything i saw on a mobile device, with reflections and shadows looking very close to what they would look in the real world. They achieved this thanks to a  new algorithm of a rendering technique called Path tracing/Ray tracing, that  is very demanding and so far it is done mostly for static images.
      From what i checked around there is no real option for real time ray tracing (60 FPS on consumer devices). There was imagination technologies that were supposed to release a chip that supports real time ray tracing, but i did not found they had a product in the market or even if the technology is finished as their last demo  i found was with a PC.  The other one is OTOY with their brigade engine that is still not released and if i understand well is more a cloud solution than in hardware solution .
      Would there  be a sizable  interest in the developers community in having such a product as a plug-in for existing game engines?  How important  is Ray tracing to the  future of high end real time graphics?
    • By bryandalo
      Good day,

      I just wanted to share our casual game that is available for android.

      Description: Fight your way from the ravenous plant monster for survival through flips. The rules are simple, drag and release your phone screen. Improve your skills and show it to your friends with the games quirky ranks. Select an array of characters using the orb you acquire throughout the game.

      Download: https://play.google.com/store/apps/details?id=com.HellmodeGames.FlipEscape&hl=en
       
      Trailer: 
       
    • By khawk
      Watch the latest from Unity.
       
  • Advertisement