Hello. Sorry if someone has asked this before, but I cant seem to find a solution anywhere. I am new to Game Development and have been struggling with creating a stat system that is affected by both level and gear. I have the gear part working and have also created an Exp and Leveling system, but I cant figure out how to increase the base value of my stats when my character levels up automatically. this is probably something very basic, but I cant seem to figure it out. This is the Code for my Character and his stats: Code (CSharp): using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using Kryz.CharacterStats; using UnityEngine.SceneManagement; public class Character : MonoBehaviour { public int maxHealth; public Animator animator; public HealthBar healthBar; public int currentHealth; private PlayerHealth health; public CharacterStat Health; public CharacterStat Stamina; public CharacterStat Damage; public CharacterStat LevelPoints; [SerializeField] Inventory2 inventory; [SerializeField] EquipmentPanel equipmentPanel; [SerializeField] StatPanel statPanel; [SerializeField] ItemTooltip itemTooltip; [SerializeField] Image draggableItem; private InventorySlot2 draggedSlot; void Start() { maxHealth = (int)Health.calculateFinalValue(); currentHealth = maxHealth; healthBar.SetMaxHealth(maxHealth); } void Update() { if (currentHealth > maxHealth) { currentHealth = maxHealth; } maxHealth = (int)Health.calculateFinalValue(); healthBar.SetMaxHealth(maxHealth); healthBar.SetHealth(currentHealth); } private void OnValidate() { if (itemTooltip == null) { itemTooltip = FindObjectOfType<ItemTooltip>(); } } private void Awake() { statPanel.SetStats(Health, Stamina, Damage); statPanel.UpdateStatValues(); //Setup Events //RIghtClick inventory.OnRightClickEvent += InventoryRightClick; equipmentPanel.OnRightClickEvent += EquipmentPanelRightClick; //Pointer Enter inventory.OnPointerEnterEvent += HideTooltip; equipmentPanel.OnPointerEnterEvent += HideTooltip; //Pointer Exit inventory.OnPointerExitEvent += ShowTooltip; equipmentPanel.OnPointerExitEvent += ShowTooltip; //BeginDrag inventory.OnBeginDragEvent += BeginDrag; equipmentPanel.OnBeginDragEvent += BeginDrag; //End Drag inventory.OnEndDragEvent += EndDrag; equipmentPanel.OnEndDragEvent += EndDrag; //Drag inventory.OnDragEvent += Drag; equipmentPanel.OnDragEvent += Drag; //Drop inventory.OnDropEvent += Drop; equipmentPanel.OnDropEvent += Drop; } public void TakeDamage(int damage) { animator.SetTrigger("Hurt"); currentHealth -= damage; healthBar.SetHealth(currentHealth); if (currentHealth <= 0) { animator.SetBool("IsDead", true); Die(); } } public void Die() { Physics2D.IgnoreLayerCollision(8, 3, true); GetComponent<BoxCollider2D>().enabled = false; GetComponent<CharacterController2D>().enabled = false; GetComponent<PlayerCombat>().enabled = false; FindObjectOfType<GameManager>().GameOver(); } private void InventoryRightClick(InventorySlot2 itemSlot) { if(itemSlot.Item is EquipableItem) { Equip((EquipableItem)itemSlot.Item); } else if (itemSlot.Item is UsableItem) { UsableItem usableItem = (UsableItem)itemSlot.Item; usableItem.Use(this); if (usableItem.IsConsumable) { inventory.RemoveItem(usableItem); usableItem.Destroy(); } } } private void EquipmentPanelRightClick(InventorySlot2 itemSlot) { EquipableItem equipableItem = itemSlot.Item as EquipableItem; if (itemSlot.Item is EquipableItem) { Unequip((EquipableItem)itemSlot.Item); } } private void ShowTooltip(InventorySlot2 itemSlot) { EquipableItem equipableItem = itemSlot.Item as EquipableItem; if (equipableItem != null) { itemTooltip.ShowTooltip(equipableItem); } } private void HideTooltip(InventorySlot2 itemSlot) { itemTooltip.HideTooltip(); } private void BeginDrag(InventorySlot2 itemSlot) { if(itemSlot.Item != null) { draggedSlot = itemSlot; draggableItem.sprite = itemSlot.Item.Icon; draggableItem.transform.position = Input.mousePosition; draggableItem.enabled = true; } } private void EndDrag(InventorySlot2 itemSlot) { draggedSlot = null; draggableItem.enabled = false; } private void Drag(InventorySlot2 itemSlot) { if (draggableItem.enabled) { draggableItem.transform.position = Input.mousePosition; } } private void Drop(InventorySlot2 dropItemSlot) { if (draggedSlot == null) return; if (dropItemSlot.CanAddStacks(draggedSlot.Item)) { int numAddableStacks = dropItemSlot.Item.MaximunStacks - dropItemSlot.Amount; int stacksToAdd = Mathf.Min(numAddableStacks, draggedSlot.Amount); dropItemSlot.Amount += stacksToAdd; draggedSlot.Amount -= stacksToAdd; } else if(dropItemSlot.CanReceiveItem(draggedSlot.Item)&& draggedSlot.CanReceiveItem(dropItemSlot.Item)) { EquipableItem dragItem = draggedSlot.Item as EquipableItem; EquipableItem dropItem = dropItemSlot.Item as EquipableItem; if(draggedSlot is EquipmentSlots) { if (dragItem != null) dragItem.Unequip(this); if (dropItem != null) dropItem.Equip(this); } if(dropItemSlot is EquipmentSlots) { if (dragItem != null) dragItem.Equip(this); if (dropItem != null) dropItem.Unequip(this); } statPanel.UpdateStatValues(); Item2 draggedItem = draggedSlot.Item; int draggedItemAmount = draggedSlot.Amount; draggedSlot.Item = dropItemSlot.Item; draggedSlot.Amount = dropItemSlot.Amount; dropItemSlot.Item = draggedItem; dropItemSlot.Amount = draggedItemAmount; } } public void Equip(EquipableItem item) { if (inventory.RemoveItem(item)) { EquipableItem previousItem; if(equipmentPanel.AddItem(item, out previousItem)) { if (previousItem != null) { inventory.AddItem(previousItem); previousItem.Unequip(this); statPanel.UpdateStatValues(); } item.Equip(this); statPanel.UpdateStatValues(); } else { inventory.AddItem(item); } } } public void Unequip(EquipableItem item) { if(!inventory.IsFull() && equipmentPanel.RemoveItem(item)) { item.Unequip(this); statPanel.UpdateStatValues(); inventory.AddItem(item); } } } This is the code to calculate the Stats when I add the gear: Code (CSharp): using System; using System.Collections.Generic; using System.Collections.ObjectModel; using Kryz.CharacterStats; namespace Kryz.CharacterStats { [Serializable] public class CharacterStat { public float BaseValue; public virtual float Value { get { if (isDirty || BaseValue != lastBaseValue) { lastBaseValue = BaseValue; _Value = calculateFinalValue(); isDirty = false; } return _Value; } } protected bool isDirty = true; protected float _Value; protected float lastBaseValue = float.MinValue; protected readonly List<StatModifier> statModifiers; public readonly ReadOnlyCollection<StatModifier> StatModifiers; public CharacterStat() { statModifiers = new List<StatModifier>(); StatModifiers = statModifiers.AsReadOnly(); } public CharacterStat(float baseValue) : this() { BaseValue = baseValue; } public virtual void AddModifier(StatModifier mod) { isDirty = true; statModifiers.Add(mod); statModifiers.Sort(CompareModifierOrder); } protected virtual int CompareModifierOrder(StatModifier a, StatModifier b) { if (a.Order < b.Order) { return -1; } else if (a.Order > b.Order) { return 1; } return 0; } public virtual bool RemoveModifier(StatModifier mod) { if (statModifiers.Remove(mod)) { isDirty = true; return true; } return false; } public virtual bool RemoveAllModifiersFromSource(object source) { bool didRemove = false; for (int i = statModifiers.Count - 1; i >= 0; i--) { if (statModifiers[i].Source == source) { isDirty = true; didRemove = true; statModifiers.RemoveAt(i); } } return didRemove; } public virtual float calculateFinalValue() { float finalValue = BaseValue; float sumPercentAdd = 0; for (int i = 0; i < statModifiers.Count; i++) { StatModifier mod = statModifiers[i]; if (mod.Type == StatModType.Flat) { finalValue += mod.Value; } else if (mod.Type == StatModType.PercentAdd) { sumPercentAdd += mod.Value; if (i + 1 >= statModifiers.Count || statModifiers[i + 1].Type != StatModType.PercentAdd) { finalValue *= 1 + sumPercentAdd; sumPercentAdd = 0; } } else if (mod.Type == StatModType.PercentMult) { finalValue *= 1 + mod.Value; } } return (float)Math.Round(finalValue, 4); } } }