Introduction

Concept

Many games uses statistics mechanisms, for various reasons and differents ways.

Shiny Stats aims to help devs to introduce stats into their games and fine tune the meta. You can create simple to advanced stats mechanisms using Shiny Stats without coding from scratch all the mechanism it involves!

World of Warcraft character stats Pokémon stats Tower defense stats

Glossary

Stats in game are confusing. Terms and their meaning differs from games to games. Here is our own vocabulary:

Name Description
Entity This is the player, enemies, towers... Things to what we will apply statistics in your game.
Stat Primary building element to define entities' abilities. It can be affected by the entity level and attributes.
Attribute Secondary building element to define entities' abilities. It is static and it is not affected by the entity level.
Class Group element in which all similar entities will share the same attributes.
Level Primary building element to define entities's abilities. Can also be used as 'Tier' for Tower Defense games.
Experience Experience points gathered by the entity to reach higher levels. It is a special stat element.
ModifierNew in v1.1 ! Influence an attribute value or a stat calculation.
Global VariableNew in v1.2 ! Secondary building element to define entities' abilities. It is static and it is not affected by the entity level nor classes.

Components

Name Description
Shiny Stats Script Core script to be placed in scene. That's where we store the Shiny Stats configuration.
Shiny Stats Window Shiny Stats Editor Window in Unity where you setup Shiny Stats.
Shiny Stats Entity Script Core script to attach in all entities.
Shiny Stats Entity Inspector Entity Inspector to configure the entity.
Shiny Stats Modifier Script New in v1.1 ! Core script to attach in entities or children gameObject.
Shiny Stats Modifier Inspector New in v1.1 ! Modifier Inspector to configure the modifier.

Installation

Note: You may also read Shiny Stats setup in 3 minutes if you want a straight forward approach.
We will deal with additional details in this manual.

ShinyStats script

One ShinyStats script must be in the game scene. This script is mandatory as it will store the Shiny Stats configuration for your game.
Best practice could be to place it into an empty dedicated GameObject.

Tip: You can also set the GameObject as Static to improve performances.
ShinyStats GameObject in scene Adding ShinyStats script to GameObject ShinyStats script inspector
Note: This is not supported to have more than one ShinyStats script in scene. Shiny Stats will let you know if this happens.

ShinyStats window

Shiny Stats can be configured using the Shiny Stats Editor Window.

Opening Shiny Stats Editor Window Shiny Stats Editor Window

ShinyStatsEntity script

Attach the ShinyStatsEntity script to all entities in scenes and in folders (prefabs).
This script will store contextual configuration about the entity such as the current level, its class and its attributes settings.

Adding ShinyStatsEntity script to GameObject ShinyStatsEntity inspector

ShinyStatsModifier script New in v1.1 !

Attach the ShinyStatsModifier script to any gameObject you want that is in a ShinyStatsEntity hierarchy (same gameObject or children).
The ShinyStatsEntity automatically detects the presence of ShinyStatsModifier scripts in children (of self) gameObjects. This script will store contextual configuration about the modifiers.

Info: Disabling a Shiny Stats Modifier script or its gameObject will automatically disable its effects.
Info: The Shiny Stats Modifier script will warn you in the console and won't affect anything if it does not find any Shiny Stats Entity in self or parent.
Adding ShinyStatsModifier script to GameObject ShinyStatsModifier inspector

Configuration

In this section, we will cover all the functionalities of Shiny Stats.

Info: Shiny Stats can do more than RPG games genre.
You will find alternative ways to use Shiny Stats features in sections like this one.
Note: You may also read Shiny Stats setup in 3 minutes if you want a straight forward approach.
We will deal with additional details in this manual.

General

Every good things comes with a cool name. The configuration name field is used to identify your game configuration. The entities will have the same configuration name.

in the Shiny Stats Editor Window in the Shiny Stats Editor Window
Tip: You can use the configuration label to do Semantic Version with your configuration. It will help you preventing synchronization issues with entities. See Entity synchronization for more info.

Attributes

Attributes is considered as the secondary building element type to define the entity's abilities.
They have constant values that cannot be affected by the entity level. They can be consumed right away using the API and used as variables for stats.

Once the attributes are defined, you can set the attributes values of each entities in their respective Shiny Stats Entity inspector.

Info: If you want to use the same values for several entities, look at the classes feature.
Troubleshooting: If the attributes list is not reflecting the global setup, you must sync the entity. See Entity synchronization.

Classes

You can have several entities sharing the same attributes values thanks to classes.

You can define them in the home tab.

In the classes tab, you can setup the attributes values.

You can assign the class of each entity in their respective Shiny Stats Entity inspector once you have at least one class defined.
You can select Custom if you want to ignore the existing classes and use a custom configuration.

The Attributes values section will output the corresponding values.

Stats

Stats is the primary building element type to define the entity's abilities.
Unlike attributes, their values can be computed against the entity level.

You can define stats in the home tab.

The stats setup is done under the stats tab.

A stat can be computed using a Manual definition or a Expression definition. The entity to preview GameObject must be in the game scene.

Stat Definition

Manual stat definition

This is the easiest way to do stats !
Using this definition, you will define the stat value from each level by hand. In this mode, you cannot use the attributes and classes.

Tip: Missing levels will fall back to the nearest inferior level configured, don't repeat yourself. :)
Tip: You can still mix manual definition and classes by creating specialized stat like Attack Power - Sentry Gun Tower and Attack Power - Missile Tower.

Expression stat definition

The stat will be computed using a math expression.
The level and the attributes can be used as variables in the math expression.

Info: The result box will appear red if the expression is invalid.
The toolbox contains all the variables and functions available with the math parser engine.

Basic Expressions

Constant example

[Intellect]

Linear example

[Level] * [Stamina]

Logarithmic (like) example

8 + [Strength] * [Level]^0.3

Power (like) example

8 + [Strength] * [Level]^2 / 1000
Note: You can find more examples in the Shiny Stats RPG use case page.

Advanced Expressions

Logic operators <, > and = will output 0 if false and 1 if true.
This can be used to apply restrictions to the function such as:

([Level] < 31) *
  [Level] * [Strength]
+
([Level] > 30) *
  ([Level] * [Strength] / 2 + 30 * [Strength] / 2)

Level

You can configure the level behavior globally in the home tab.

Minimal level and Maximal level will set the game's level range.
Initial level is the default level for an entity. Resetting an entity will set his level back to the initial value.
Infinite levels can be checked if you don't want a maximum value in your game mechanics.

Each Entity have its own level. You can review and manipulate it in the Shiny Stats Entity inspector or using the API.

Tip: If you don't want levels in your game, set minimum and maximum to 1 and exclude the Level variable in your stats definitions.
Due to technical reasons, level cannot be set below 1. The workaround is to use an offset if you need negative levels in your game (you monster).

Experience

Shiny Stats provide a experience system for entities to increase levels. This is a facultative feature you can activate under the home tab.

It uses a special stats Experience so you can configure the amount of point required to level up for each level.
Similar to levels, each entity have its own experience points. You can review them and edit them in the Shiny Stats Entity inspector or using the API. For each levels, an entity need to gather the amount of points in order to level up.

Can De-level to true will allow entities to lose a level when loosing experience points below 0. Else the experience points bound to 0.
Use surplus Exp points affects how a level-up works. Set to true, the surplus of experience (entity gained more exp than required to level up) will be stored in the next level Exp gauge. If false, the surplus is lost: the entity level up and its experience points is 0.

Global Variables New in v1.2 !

Global Variables are values meant to be used globally in the game. They can be read and modified on the go using the ShinyStats API. They can also be used as variable in Stats' math expression.

Modifier New in v1.1 !

Shiny Stats allows you to apply modification to entities. This is perfect to create status effects, buffs, de-buffs, wearable effect (weapon gameObject increasing strength for instance). This is a facultative feature you can use thanks to the Shiny Stats Modifier Script.

Read how to install modifiers regarding installation and integration.

Info: To implement a status effect (buffs, de-buffs, modifier effects disabled after a certain duration), you can use the script StatsEffect.cs joined in the demo.

Attribute/Stat - Name The Attribute or Stat you want to modify.
Multiply by/Add value - value The mathematical operation and value you want to apply.
Priority Useful when you want a modifier to apply before another (Resolve starts from 1 to 9).

Shiny Stats Entity shows your modifiers

You can review all the entity modifiers from the Shiny Stats Entity Inspector.

Shiny Stats Entity shows your modifiers effects

You can review the modifiers effects from the Shiny Stats Entity Inspector (left without, right with modifiers).

Shiny Stats - Stats preview with and without modifiers

You can preview a stats with and without modifiers.

Usage

Entity synchronization

You have to manually synchronize your entities after editing the attributes, classes and stats.
This is being done using the Shiny Stats Entity inspector sync button.

Tip 3000: You can select multiple gameObjects or prefabs at once and sync 'Em all in one click.
Dev note: There is several reasons why the entities aren't synchronized automatically. For short, the Unity API is not reliable enough to provide a robust sync (and revert) on the go. An automatic sync of entities could impact experience overall since it may break entity config, especially for the project prefab entities when switching between scenes.

This might be tedious to keep all the entities synchronized. You can secure this by introducing Semantic Version to your configuration label.

In this example, the entity config is outdated and need a sync (entity is v1.0.1, global is v1.0.2).
Tip: Shiny Stats warns you during the game runtime if there is a mismatch between an entity and the global config label.
Overview of the Shiny Stats data location and if affected by the synchronization
Configuration Element Stored in Shiny Stats Stored in Shiny Stats Entity Is synced
Configuration Name Yes Yes (copy, proof of sync) Yes
Attributes list Yes Yes (copy) Yes
Classes list Yes Yes (copy) Yes
Stats list Yes Yes (copy) Yes
Attribute value (from a class) Yes Yes (copy) Yes
Experience Settings Yes Yes (copy) Yes
Stat config Yes No No
Level Settings Yes No No
Entity Attribute value (custom class) No Yes No
Entity Class No Yes No
Entity Level No Yes No
Entity Experience No Yes No
Global Variables Yes No No

Integrate to your game

Get Strength attribute value

  // Get the ShinyStatsEntity reference of the entity.
  var sse = GetComponent<ShinyStatsEntity>();

    // Get Strength attribute.
    var str = sse.EvaluateAttribute("Strength");
    

Evaluate the Attack power stat value

    // Get the ShinyStatsEntity reference of the entity.
    var sse = GetComponent<ShinyStatsEntity>();

      // Evaluate the Attack power stat (at current level).
      var atk = sse.EvaluateStat("Attack power");

      // Evaluate the Attack power stat (at a specific level).
      var atkLvl12 = sse.EvaluateStat("Attack power", 12);
      

Add experience points

      // Get the ShinyStatsEntity reference.
      var sse = GetComponent<ShinyStatsEntity>();

        // Add experience points. Level-up is automatically handled.
        var newExpPts = sse.AddExp(1200);
        

Use the math expression engine

        var expression = "45 * log(5, 10)";

        // Evaluate the expression.
        var val = ShinyStats.Evaluate(expression);
        
Note: You can find more examples in the Shiny Stats RPG use case page.

Math functions

All the math functions comes from the official Microsoft .Net Math class.

Meta AnalysisNew in v1.3 !

Intro

Under the panel Meta Analysis, you can find several ways to look at your meta, understand it and find the desired balance.

Stats per Entities (live scene)

This view helps to compare entities in scene at their current levels and active modifiers.

Stats per Classes

This view helps to compare classes at a specific level.

Single Stat in-depth

This view helps to overview a stat for each classes at each levels.

You may need to hit the button Compute Table when the config is changed to refresh the data.

Single Class in-depth

This view helps to overview a class for each stats at each levels.

You may need to hit the button Compute Table when the config is changed to refresh the data.

Stats per Classes, all Levels

This advanced view does not show a table since it would be quite big and poorly useful in the editor. It gives all the combination of classes, stats and levels possible to export so you can work in a Spreadsheet. See the CSV export and Spreadsheet section for more info.

CSV export and Spreadsheet

Each table can be exported with the button found at the table end. The exported CSVs are saved under the folder ShinyStats/Export/{ConfigLabel}/ (missing folders are automatically created).

Note: ShinyStats also tries to open the CSV right away using your default application for .csv files. It may not work properly since it depends on your computer setup. You may see change-default-programs-in-windows-10 (support.microsoft.com) for windows users.
Using Excel (for instance), you can use the pivot table feature to project the data to visualize something specific. In the example below, I am visualizing the Attack Power potential per classes from level 1 to level 600 using the Shiny Tiny RPG demo.
Info: The .xlsx document used to produce the visualization above is joined with the asset.
Learning how pivot table works and how to use it is a vast subject I can't really cover here, I recommend to start with the official doc from Excel if you use Excel. The CSVs can also be used with python and Jupyter notebooks, the power is under your hand.

Why is ShinyStats not doing this in the editor ?: Unity makes data visualization in the Editor a real challenge and I can't afford to recreate an Excel-like software in Shiny Stats. Especially if experienced users are exporting CSVs to work in their favorite Spreadsheet software anyway.

API Reference

ShinyStats

Properties

Active Quick reference of the ShinyStats singleton in scene.
ConfigurationLabel Label of the configuration.
Attributes Attributes available in the configuration.
Stats Stats of ShinyStats.
Classes Classes of ShinyStats.
LevelSettings Level settings of ShinyStats.
Experience Experience settings of ShinyStats.
GlobalVariables Global Variables settings of ShinyStats.
ShinyStatsVersion Version of Shiny Stats.

Public Methods

IsExpressionValid Return true if the math expression is valid.
Evaluate Evaluate math expression.
GetGlobalVariable Get global variable value.
SetGlobalVariable Set value to an existing global variable. This modification is only kept during runtime. It won't persist outside this game session.
EvaluateStatFromClass Evaluate the stat of a class (no entity used in here, this is theorical). This is mainly used to compute data in the Meta Analysis tab. You should use the Evaluate functions of ShinyStatsEntity unless you really know what you are doing. You may use this if you want to cache the computation.

ShinyStatsEntity

Properties

ConfigurationLabel Label of the configuration cached by the entity.
AttributeInstances Attributes of ShinyStats cached by the entity.
UseCustomAttributes Use custom attributes or use class's attributes toggle.
ClassSelected Selected class of the entity.
StatInstances Stats of ShinyStats cached by the entity.
CurrentLevel Current level of the entity.
ExperiencePoints Current experience points of the entity.

Events

OnLevelChanged Event raised when the entity level has changed.
OnExpPointsChanged Event raised when the entity experience points has changed.

Public Methods

IsStatExist Check if a stat label exists in the ShinyStats configuration.
EvaluateStat Return stat value evaluated with a specific level.
Return stat value using the current entity level.
EvaluateStatModifiersEffect Return the value added (or removed!) thanks to the modifiers.
EvaluateAttribute Evaluate attribute value.
EvaluateAttributeModifiersEffect Return the value added (or removed!) thanks to the modifiers.
IncrementLevel Increment current level of the entity.
DecrementLevel Decrement current level of the entity.
IsLowestLevel Return true if the entity is at the minimum level possible.
IsMaximumLevel Return true if the entity is at the maximum level possible.
ResetExp Reset Experience points to 0.
AddExp Add experience points to the entity. You can use negative value to remove experience points.
RemoveExp Remove experience points to the entity. You can also use AddExp() using negative value to remove experience points.

Troubleshooting

My Shiny Stats Entity does not reflect the global configuration

Read Entity synchronization.

ShinyStats breaks appart when playing the game. The data is deleted or corrupted.

The issue arises when ShinyStats exists as a prefab in the scene—my recommended setup—and you make changes that are not then updated back to the prefab; instead, they remain within the scene file.
When you play the game under these conditions, it can lead to data inconsistencies that might cause you to experience bugs during game and lose any recent changes upon exiting the game. The problem stems from how Unity handles data saving: it properly saves prefab data (respect of the classes structure...), but doesn't reliably save changes made to gameObjects in the scene (arrays of values...😡).
To resolve this issue, ensure to always apply the modifications to the prefab before playing. Broadly, it's wise to keep an eye on your project's file versioning system to avoid such issues. The scene should not maintain any changes made to the ShinyStats prefab. This advice holds for ShinyStats Entity prefabs as well, and is generally a good practice with scripts that hold structured or complex data.

Modifier GameObjects added or removed are not automatically detected

This happens when the modifier gameObject is moved from its parent to another one (either from code or from the Unity Editor).
Fix this by clicking on Scan for modifiers manually in the Shiny Stats Entity Inspector or by calling ShinyStatsEntity.ScanForModifiers() from code.

Enable Shiny Stats traces

For issues investigation, we might ask you to enable the Shiny Stats traces. To enable the traces, add a SHINYSTATSTRACE variable in the Scripting Define Symbols text box under Edit/Project Settings/Player/Other Settings. Please note that enabling traces will slightly reduce the performance.