Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Looking for feedback on my Perk system

Discussion in 'Scripting' started by LSThimo, Jun 12, 2019.

  1. LSThimo

    LSThimo

    Joined:
    Sep 14, 2017
    Posts:
    5
    Hey guys!
    As the title states, I'm looking for feedback on the Perk system I created today.

    I wanted there to be as little hardcoding as possible so I used System.Reflection, since I want to change variables throughout various scripts (ex. the weaponSpread float in the Weapon script and the playerSpeed float in the Player script).

    The Perk class:
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. [CreateAssetMenu(fileName = "New Perk", menuName = "Perk")]
    4. public class Perk : ScriptableObject
    5. {
    6.     public string className; //Name of the class
    7.     public string variableName; //Name of the variable
    8.     public float toAdd = 0; //Value to add to the variable
    9.     public float toMultiply = 1; //Value to multiply the variable with
    10. }
    The function in my PerkManager script:
    Code (CSharp):
    1.     void ApplyPerk(GameObject holder, Perk perk)
    2.     {
    3.         //Get value of requested variable
    4.         Component component = holder.GetComponent(perk.className); //Get component
    5.         FieldInfo field = component.GetType().GetField(perk.variableName); //Get field
    6.         float value = (float)field.GetValue(component); //Get value
    7.  
    8.         //Add value to said variable
    9.         value *= perk.toMultiply; //Multiply current value with perk multiplier
    10.         value += perk.toAdd; //Add perk value to current value
    11.  
    12.         //Set new value
    13.         field.SetValue(component, value); //Set variable
    14.     }
     
  2. palex-nx

    palex-nx

    Joined:
    Jul 23, 2018
    Posts:
    1,748
    Usually it isn't good idea to modify values directly. What if you have two perks on one value? Imagine you have perks A +2 damage and perk B x2 damage. When both applied you will get different results based on what perk was applied first. And when perks will be deactivated, you'll sometimes will and sometimes will not go back to original value depending on deactivation order.

    1. Original value: 5
    2. Apply x2 = 10
    3. Apply +2 = 12
    4. Remove x2 = 6
    5. Remove +2 = 4

    or

    1. Original value: 5
    2. Apply +2 = 7
    3. Apply x2 = 14
    4. Remove +2 = 12
    5. Remove x2 = 6.
     
    LSThimo likes this.
  3. LSThimo

    LSThimo

    Joined:
    Sep 14, 2017
    Posts:
    5
    This is true, totally forgot about this aspect. I will look into this, thanks!
     
  4. palex-nx

    palex-nx

    Joined:
    Jul 23, 2018
    Posts:
    1,748
    I would start with Attribute class instead of using regular fields for role playing attributes. Attribute stores base value. Attribute contains a list of IAttributeModifier implementations, wich may be perks, items, areas in levels, game mode x2 HP for instance, whatever. Attribute may calculate final value from base value and a list of modifiers. Calculation algorithm must ensure it is not order dependent. It might be sum[1,N] (modifier.add * baseValue + modifier.add) for instance.
     
  5. Dameon_

    Dameon_

    Joined:
    Apr 11, 2014
    Posts:
    542
    While reflection is really handy, it's not really the best solution for this problem. You're creating a very brittle reference by storing the class/variable name in a string, and it is guaranteed to give you headaches down the road. You would be better off using IDs to create relationships in your data that don't rely on your code.