Unity3D , Error GetItem(int 32) - c#

i created 3 scripts for create an item , add item to list and show item.
When i'm trying get item to list , this error occurs.
NullReferenceException: Object reference not set to an instance of an object
charactersScript.GetItem (Int32 id)
the error is at line charactersScript.GetItem (Int32 id)
Here my scripts
itemdatabese for item class
using UnityEngine;
using System.Collections;
using System;
public class itemDataBase : ScriptableObject
{
public int itemID;
public int itemDamage;
public string itemName;
public itemDataBase(int _id, int _damage, string _name)
{
itemID = _id;
itemDamage = _damage;
itemName = _name;
}
}
technology script unlock for item and add to list
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class technologyScript : MonoBehaviour
{
public int countID = 0;
List<itemDataBase> item = new List<itemDataBase>();
public void StoneSpear()
{
countID += 1;
item.Add(new itemDataBase(countID, 7, "Stone Spear"));
}
}
and character script for show this item
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using System.Collections.Generic;
public class charactersScript : MonoBehaviour
{
static public List<itemDataBase> _item;
static public itemDataBase GetItem(int id)
{
foreach (itemDataBase item in _item)
{
if (item.itemID == id)
{
return ScriptableObject.Instantiate(item) as itemDataBase;
}
}
return null;
}
public void rightWeapon()
{
weaponID += 1;
itemDataBase _item = GetItem(weaponID);
if (_item != null)
{
Debug.Log(_item.id);
}
}
}
is there any suggestion?

You are adding new itemDataBase() to one instance of List in technologyScript and then in charactersScript you are trying to loop through a different list (List<itemDataBase> _item) which is never instantiated and is null and throws the exception. The static list doesn't just automatically share the values of the other list just because you declared it with the static keyword.
Set your List<itemDataBase> item to public.
Try this:
foreach (itemDataBase item in GetComponent<technologyScript>().item)
{
if(item.itemID==id)
{
return ScriptableObject.Instantiate(item) as itemDataBase;
}
}
This presumes that technologyScript is on the same gameobject as this script, if not then you will need GameObject.Find(correctObj)...

Related

Unity Inventory System 'error CS1001: Identifier expected'

I am writing a simple script to create an inventory system, although I keep getting an 'Identifier Expected' error. I am trying to select the current item the script is attached to and add it to the inventory.
This is the error:
Assets\Scripts\ItemObject.cs(10,25): error CS1001: Identifier expected
The tutorial I am following: https://www.youtube.com/watch?v=SGz3sbZkfkg
Here is the Inventory System:
InventorySystem.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class InventorySystem : MonoBehaviour
{
private Dictionary<InventoryItemData, InventoryItem> m_itemDictionary;
public List<InventoryItem> inventory {get; private set;}
private void Awake() {
inventory = new List<InventoryItem>();
m_itemDictionary = new Dictionary<InventoryItemData, InventoryItem>();
}
public void Add(InventoryItemData referenceData) {
if(m_itemDictionary.TryGetValue(referenceData, out InventoryItem value)) {
value.AddToStack();
} else {
InventoryItem newItem = new InventoryItem(referenceData);
inventory.Add(newItem);
m_itemDictionary.Add(referenceData, newItem);
}
}
public void Remove(InventoryItemData referenceData) {
if (m_itemDictionary.TryGetValue(referenceData, out InventoryItem value)) {
value.RemoveFromStack();
if(value.stackSize == 0) {
inventory.Remove(value);
m_itemDictionary.Remove(referenceData);
}
}
}
}
[Serializable]
public class InventoryItem {
public InventoryItemData data {get; private set;}
public int stackSize {get; private set;}
public InventoryItem(InventoryItemData source) {
data = source;
AddToStack();
}
public void AddToStack() {
stackSize++;
}
public void RemoveFromStack() {
stackSize--;
}
}
and here is the script that handles the item pickup:
ItemObject.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ItemObject : MonoBehaviour {
public InventoryItemData referenceItem;
public void OnHandlePickupItem() {
InventorySystem.this.Add(referenceItem);
Destroy(gameObject);
}
}
Any help would me much appreciated :)
You can not refer to InventorySystem with InventorySystem.this.Add(referenceItem) in ItemObject.
Try following:
Add the InventorySystem component to a GameObject in your Scene
Tag this GameObject with a tag named Inventory
With that you can find the InventorySystem by GameObject.findByTag (do this in the Awake method of ItemObject
Use this object for adding/removing stuff from/to the InventorySystem

How to fix inventory error in unity 2021.3.13f1

EDITED MORE SCRIPTS SHOWN!
I'm making an inventory system from This YouTube Video and I can't seem to get it to work.
the error1:
Assets\Scripts\InventoryScripts\InventorySystem.cs(31,33): error CS1579: foreach statement cannot operate on variables of type 'InventorySlot' because 'InventorySlot' does not contain a public instance or extension definition for 'GetEnumerator'
The error2:
Assets\Scripts\InventoryScripts\InventorySystem.cs(55,19): error CS0029: Cannot implicitly convert type 'System.Collections.Generic.List' to 'InventorySlot'
And my code:
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.Events;
[System.Serializable]
public class InventorySystem
{
[SerializeField] private List<InventorySlot> inventorySlots;
public int InventorySize => InventorySlots.Count;
public List<InventorySlot> InventorySlots => inventorySlots;
public UnityAction<InventorySlot> OnInventorySlotChanged;
public InventorySystem(int size)
{
inventorySlots = new List<InventorySlot>(size);
for(int i = 0; i < size; i++)
{
inventorySlots.Add(new InventorySlot());
}
}
public bool AddToInventory(InventoryItemData itemToAdd, int amountToAdd)
{
if(ContainsItem(itemToAdd, out InventorySlot invSlot))
{
foreach(var slot in invSlot)
{
if(slot.RoomLeftInStack(amountToAdd))
{
slot.AddToStack(amountToAdd);
OnInventorySlotChanged?.Invoke(invSlot);
return true;
}
}
}
if(HasFreeSlot(out InventorySlot freeSlot))
{
freeSlot.UpdateInvSlot(itemToAdd, amountToAdd);
OnInventorySlotChanged?.Invoke(freeSlot);
return true;
}
return false;
}
public bool ContainsItem(InventoryItemData itemToAdd, out InventorySlot invSlot)
{
invSlot = InventorySlots.Where(i => i.ItemData == itemToAdd).ToList();
return invSlot == null ? false : true;
}
public bool HasFreeSlot(out InventorySlot freeSlot)
{
freeSlot = InventorySlots.FirstOrDefault(i => i.ItemData == null);
return freeSlot == null ? false : true;
}
}
Holder script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
[System.Serializable]
public class InventoryHolder : MonoBehaviour
{
[SerializeField] private int inventorySize;
[SerializeField] protected InventorySystem inventorySystem;
public InventorySystem InventorySystem => inventorySystem;
public static UnityAction<InventorySystem> OnDynamicInventoryDisplayRequested;
private void Awake()
{
inventorySystem = new InventorySystem(inventorySize);
}
}
Slot Script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class InventorySlot
{
[SerializeField] private InventoryItemData itemData;
[SerializeField] private int stackSize;
public InventoryItemData ItemData => itemData;
public int StackSize => stackSize;
public InventorySlot(InventoryItemData source, int amount)
{
itemData = source;
stackSize = amount;
}
public InventorySlot()
{
ClearSlot();
}
public bool RoomLeftInStack(int amountToAdd, out int amountRemaining)
{
amountRemaining = ItemData.maxStackSize - stackSize;
return RoomLeftInStack(amountToAdd);
}
public bool RoomLeftInStack(int amountToAdd)
{
if(stackSize + amountToAdd <= itemData.maxStackSize) return true;
else return false;
}
public void ClearSlot()
{
itemData = null;
stackSize = -1;
}
public void UpdateInvSlot(InventoryItemData data, int amount)
{
itemData = data;
stackSize = amount;
}
public void AddToStack(int amount)
{
stackSize += amount;
}
public void RemoveFromStack(int amount)
{
stackSize -= amount;
}
}
I'm just trying to remove these errors so I can test it.
The Where method of the List class returns a List rather than a single InventorySlot object.
You can rewrite the function 'ContainsItem' like this:
public bool ContainsItem(InventoryItemData itemToAdd, out InventorySlot invSlot)
{
invSlot = InventorySlots.FirstOrDefault(i => i.ItemData == itemToAdd);
return invSlot == null ? false : true;
}

GetKeyDown sends multiple outputs

specifically it sends as many outputs as there are objects with the code in them that allows them to be interacted with, even if I press E when not looking at anything. I wanted to make an inventory system, but this causes all objects that have this code to be interacted with. I included all the scripts that im using for this system if that can help. I genuinely don't know what I did wrong
the interactor code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Events;
using System;
public class Interactable : MonoBehaviour
{
public LayerMask interactableLayerMask;
//ITEM VARIABLE
public Item item;
//PICK UP RADIUS
public float radius = 4f;
public void Interact()
{
Debug.Log("Interacted with " + transform.name);
PickUp();
}
//PICK UP INTERACTION
void PickUp()
{
Debug.Log("Picking up " + item.name);
bool wasPickedUp = Inventory.instance.Add(item);
if (wasPickedUp)
Destroy(gameObject);
}
//INTERACTION
void Update()
{
if (Input.GetKeyDown(KeyCode.E))
{
Debug.Log("Added item -----------------------------------------");
RaycastHit hit;
if (Physics.Raycast(Camera.main.transform.position, Camera.main.transform.forward, out hit, radius))
{
Interactable interactable = hit.collider.GetComponent<Interactable>();
if (interactable != null)
{
Interact();
}
} else
{
Debug.Log("Nothing");
}
}
}
}
the Inventory code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Inventory : MonoBehaviour
{
#region Singleton
public static Inventory instance;
void Awake()
{
if (instance != null)
{
Debug.LogWarning("More than one instance of Inventory found!");
return;
}
instance = this;
}
#endregion
public delegate void OnItemChanged();
public OnItemChanged onItemChangedCallback;
public int space = 20;
public List<Item> items = new List<Item>();
public bool Add (Item item)
{
if (!item.isDefaultItem)
{
if (items.Count >= space)
{
Debug.Log("Note enough space in inventory");
return false;
}
else
{
items.Add(item);
if (onItemChangedCallback != null)
onItemChangedCallback.Invoke();
}
}
return true;
}
public void Remove(Item item)
{
items.Remove(item);
if (onItemChangedCallback != null)
onItemChangedCallback.Invoke();
}
}
Item code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(fileName = "New Item", menuName = "Inventory/Item")]
public class Item : ScriptableObject
{
new public string name = "New Item";
public Sprite icon = null;
public bool isDefaultItem = false;
}
To my understanding, your code goes into the Input.GetKeyDown(KeyCode.E) for every object in the scene, but it does not add it to the inventory.
That is because you use the Update function in the Interactable class, which are your objects. Instead, try moving the exact same block of code into your Inventory class. Make sure you make your Interact method public, so you can call it.

UI element keeps upscaling itself upon game start

Pretty new to developing so please excuse any obvious errors.
I'm currently trying to build an inventory system for my game but the item slots keep upscaling themselves upon game start.
The prefab starts with a scaling of: x=1, y=1, z=1;
On game start this inflates to: x=53.1, y=53.1, z=53.1;
Here is the scale of the prefab:HERE
And here is the scale of the prefab upon game start: HERE
Here is the script to update the items:
using UnityEngine;
using UnityEngine.UI;
public class UIItem : MonoBehaviour
{
public Item item;
private Image spriteImage;
private void Awake()
{
spriteImage = GetComponent<Image>();
UpdateItem(null);
}
public void UpdateItem(Item item)
{
this.item = item;
if (this.item != null)
{
spriteImage.color = Color.white;
spriteImage.sprite = this.item.icon;
}
else
{
spriteImage.color = Color.clear;
}
}
}
And here is the script used to update the slots and to add the items to the inventory:
using System.Collections.Generic;
using UnityEngine;
public class UIInventory : MonoBehaviour
{
public List<UIItem> uIItems = new List<UIItem>();
public GameObject slotPrefab;
public Transform slotPanel;
public int numberOfSlots = 16;
private void Awake()
{
for (int i = 0; i < numberOfSlots; i++)
{
GameObject instance = Instantiate(slotPrefab);
instance.transform.SetParent(slotPanel);
uIItems.Add(instance.GetComponentInChildren<UIItem>());
}
}
public void UpdateSlot(int slot, Item item)
{
uIItems[slot].UpdateItem(item);
}
public void AddNewItem(Item item)
{
UpdateSlot(uIItems.FindIndex(i => i.item == null), item);
}
public void RemoveItem(Item item)
{
UpdateSlot(uIItems.FindIndex(i => i.item == item), null);
}
}
Here is the inventory script itself:
using System.Collections.Generic;
using UnityEngine;
public class Inventory : MonoBehaviour
{
public List<Item> characterItems = new List<Item>();
public ItemDatabase itemDatabase;
public UIInventory inventoryUI;
private void Start()
{
GiveItem(1);
GiveItem("Clue 5");
RemoveItem(1);
}
public void GiveItem(int id)
{
Item itemToAdd = itemDatabase.GetItem(id);
characterItems.Add(itemToAdd);
inventoryUI.AddNewItem(itemToAdd);
Debug.Log("Added item:" + itemToAdd.name);
}
public void GiveItem(string itemName)
{
Item itemToAdd = itemDatabase.GetItem(itemName);
characterItems.Add(itemToAdd);
inventoryUI.AddNewItem(itemToAdd);
Debug.Log("Added item:" + itemToAdd.name);
}
public Item CheckForItem(int id)
{
return characterItems.Find(item => item.id == id);
}
public void RemoveItem(int id)
{
Item item = CheckForItem(id);
if (item != null)
{
characterItems.Remove(item);
inventoryUI.RemoveItem(item);
Debug.Log("Item removed:" + item.name);
}
}
}
I've tinkered on this for the past four hours and have nothing that seems to work. I've tried the Aspect Ratio Fitter and it only made it more. I can try to explain further if needed.
If anyone could help, it would be greatly appreciated.

Value correctly initializes, but breaks when updating

I'm a beginner learning C# and Unity and I'm following this tutorial, https://www.youtube.com/watch?v=5U5TiW21Inw because I did some scripting beforehand and it had already been getting a bit messy I decided to start over and found this which doesn't declare valuables in a long page like I was doing prior, instead it creates a valuable tool. I'm finished with episode 2 (https://www.youtube.com/watch?v=gj5LfqwGvgA) and everything but my recalculator seems to be working. When I play the scene the HP Formula makes the HP UI correctly displays 75 so I know it's sending and storing values correctly but when I press X which in Episode 1 we set up to increase testValueReference (Which later is switched to Strength) by 1, which it does. The problem is that as soon as I press X the HP value zeroes (nulls?).
The program so far consists of nine scripts in total and as the value initializes correctly I know it it's not in Formula.cs, HPFormula.cs, Value.cs, TextCharacterValue.cs, ValueFloat.cs, ValueInt.cs, or ValueStructure.cs. Mostly because these are short scripts that are easily copied when they appear in full and none of them use the recalculator function. The only two scripts that use the recalculator are Character.cs and ValueReference.cs.
Formula.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public abstract class Formula : ScriptableObject
{
public abstract List<Value> GetReferences();
}
public abstract class FormulaInt : Formula
{
public abstract int Calculate(StatsContainer stats);
}
public abstract class FormulaFloat: Formula
{
public abstract float Calculate(StatsContainer stats);
}
HPFormula.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(menuName = "Formula/HP")]
public class HPFormula : FormulaInt
{
// Health Formula below
public Value vitality;
int vit;
public Value strength;
int str;
public override int Calculate(StatsContainer stats)
{
stats.Get(vitality, out vit);
stats.Get(strength, out str);
return vit * 6 + str * 2 + 30; // Placeholder Formula
}
public override List<Value> GetReferences()
{
List<Value> values = new List<Value>();
values.Add(vitality);
values.Add(strength);
return values;
}
}
TextCharacterValue.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class TextCharacterValue : MonoBehaviour
{
public Value trackValue;
public Character character;
void UpdateText()
{
string str = character.statsContainer.GetText(trackValue);
GetComponent<Text>().text = str;
}
// Start is called before the first frame update
void Start()
{
character.statsContainer.Subscribe(UpdateText, trackValue);
UpdateText();
}
}
Value.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Value : ScriptableObject
{
public string Name;
public Formula formula;
}
ValueInt.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
[CreateAssetMenu(menuName = "Value/Int")]
public class ValueInt : Value
{
}
ValueFloat.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
[CreateAssetMenu(menuName = "Value/Float")]
public class ValueFloat : Value
{
}
ValueStructure.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
[CreateAssetMenu(menuName = "Value/Structure")]
public class ValueStructure : ScriptableObject
{
public List<Value> values;
}
ValueReference.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public abstract class ValueReference
{
public Value valueBase;
public Action onChange;
public Action<Value> recalculate;
public List<Value> dependent;
public void RecalculateDependencies()
{
if (dependent != null)
{
foreach(Value v in dependent)
{
recalculate?.Invoke(v);
}
}
}
public virtual string TEXT { get; internal set; }
public abstract void Null();
public class ValueFloatReference : ValueReference
{
public float value;
public ValueFloatReference(Value _valueBase, float _value = 0)
{
valueBase = _valueBase;
value = _value;
}
internal void Sum(float sum)
{
value += sum;
onChange?.Invoke();
base.RecalculateDependencies();
}
public override void Null()
{
value = 0f;
onChange?.Invoke();
base.RecalculateDependencies();
}
public override string TEXT
{
get
{
return valueBase.Name + " " + value.ToString();
}
}
}
public class ValueIntReference : ValueReference
{
public int value;
public ValueIntReference(Value _valueBase, int _value = 0)
{
valueBase = _valueBase;
value = _value;
}
internal void Sum(int sum)
{
value += sum;
onChange?.Invoke();
base.RecalculateDependencies();
}
public override void Null()
{
value = 0;
onChange?.Invoke();
base.RecalculateDependencies();
}
public override string TEXT
{
get
{
return valueBase.Name + " " + value.ToString();
}
}
}
}
All seems fine on this end, so I assume the problem lies in Character.cs.
Character.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using static ValueReference;
public class StatsContainer
{
public List<ValueReference> valueList;
public StatsContainer()
{
valueList = new List<ValueReference>();
}
internal string GetText(Value value)
{
ValueReference valueReference = valueList.Find(x => x.valueBase == value);
return valueReference.TEXT;
}
public void Sum(Value value, int sum)
{
ValueReference valueReference = valueList.Find(x => x.valueBase == value);
if (valueReference != null)
{
ValueIntReference reference = (ValueIntReference)valueReference;
reference.Sum(sum);
}
else
{
Add(value, sum);
}
}
private void Add(Value value, float sum)
{
valueList.Add(new ValueFloatReference(value, sum));
}
private void Add(Value value, int sum)
{
valueList.Add(new ValueIntReference(value, sum));
}
public void Get(Value value, out int state)
{
ValueReference valueReference = valueList.Find(x => x.valueBase == value);
ValueIntReference valueInt = (ValueIntReference)valueReference;
if (valueInt == null)
{
state = 0;
}
else
{
state = valueInt.value;
}
}
public void Get(Value value, out float state)
{
ValueReference valueReference = valueList.Find(x => x.valueBase == value);
ValueFloatReference valueFloat = (ValueFloatReference)valueReference;
if (valueFloat == null)
{
state = 0;
}
else
{
state = valueFloat.value;
}
}
public ValueReference GetValueReference(Value value)
{
return valueList.Find(x => x.valueBase == value);
}
public void Subscribe(Action action, Value value)
{
ValueReference valueReference = valueList.Find(x => x.valueBase == value);
valueReference.onChange += action;
}
public void Subscribe(Action<Value> action, Value dependency, Value subscribeTo)
{
ValueReference valueReference = valueList.Find(x => x.valueBase == subscribeTo);
if (valueReference.recalculate == null)
{
valueReference.recalculate = action;
}
if (valueReference.dependent == null)
{
valueReference.dependent = new List<Value>();
}
valueReference.dependent.Add(dependency);
}
public void Sum(Value value, float sum)
{
ValueReference valueReference = valueList.Find(x => x.valueBase == value);
if (valueReference != null)
{
ValueFloatReference reference = (ValueFloatReference)valueReference;
reference.Sum(sum);
}
else
{
Add(value, sum);
}
}
}
public class Character : MonoBehaviour
{
public ValueStructure statsStructure;
public StatsContainer statsContainer;
// Start is called before the first frame update
void Start()
{
Init();
}
void Init()
{
InitValues();
InitFormulas();
}
private void InitValues()
{
statsContainer = new StatsContainer();
for (int i = 0; i < statsStructure.values.Count; i++)
{
Value value = statsStructure.values[i];
if (value is ValueFloat)
{
statsContainer.valueList.Add(new ValueFloatReference(value, 5f));
}
if (value is ValueInt)
{
statsContainer.valueList.Add(new ValueIntReference(value, 5)); // (value, x) x = Initialized Value
}
}
}
private void InitFormulas()
{
foreach (ValueReference valueReference in statsContainer.valueList)
if (valueReference.valueBase.formula)
{
valueReference.Null();
if (valueReference.valueBase.formula is FormulaInt)
{
FormulaInt formula = (FormulaInt)valueReference.valueBase.formula;
statsContainer.Sum(valueReference.valueBase, formula.Calculate(statsContainer));
}
else
{
FormulaFloat formula = (FormulaFloat)valueReference.valueBase.formula;
statsContainer.Sum(valueReference.valueBase, formula.Calculate(statsContainer));
}
List<Value> references = valueReference.valueBase.formula.GetReferences();
for (int i = 0; i < references.Count; i++)
{
statsContainer.Subscribe(ValueRecalculate, valueReference.valueBase, references[i]);
}
}
}
public void ValueRecalculate(Value value)
{
ValueReference valueReference = statsContainer.GetValueReference(value);
valueReference.Null();
// Adds all relevant stat sources.
}
public Value testReferenceValue;
public Value baseSkillPoints;
public Value baseStrength;
public Value baseVitality;
public Value baseHP;
public Value baseDexterity;
public Value baseIntelligence;
public Value baseLuck;
private void Update()
{
{
if (Input.GetKeyDown(KeyCode.X))
{
statsContainer.Sum(testReferenceValue, 1);
}
}
}
}
To be clear, the expected result is as follows. When I run the program my HP UI displays 75 and my attributes are all initialized to 5. Then upon pressing X my Strength UI goes up and that should also increase my HP UI because of the HP Formula.
Instead, When I run the program my HP UI displays 75 and my attributes are all initialized to 5. Then upon pressing X my Strength UI goes up, but my HP UI goes to 0.
This leads me to believe the problem lies specifically in the Recalculating.
Any and all help is appreciated.
I would refactor the Formula recalculation code into its own method then call that in InitFormulas and ValueRecalculate. I would also do some renaming for the sake of clarity and also use a switch statement instead of a long if/else if/else for type checking:
// for fast error detection
using UnityEngine.Assertions;
private void InitFormulas()
{
foreach (ValueReference valueReference in statsContainer.valueList)
{
if (valueReference.valueBase.formula)
{
RecalculateFormulaReference(valueReference);
List<Value> references = valueReference.valueBase.formula.GetReferences();
for (int i = 0; i < references.Count; i++)
{
statsContainer.Subscribe(RecalculateFormulaByValue,
valueReference.valueBase, references[i]);
}
}
}
}
private void RecalculateFormulaReference(ValueReference valueReference)
{
valueReference.Null();
// better to use a switch with pattern matching like this
switch (valueReference.valueBase.formula)
{
case FormulaInt formula:
statsContainer.Sum(valueReference.valueBase,
formula.Calculate(statsContainer));
break;
case FormulaFloat formula:
statsContainer.Sum(valueReference.valueBase,
formula.Calculate(statsContainer));
break;
default:
Assert.IsTrue(false, "Unsupported Formula Type");
}
}
// more descriptive name
public void RecalculateFormulaByValue(Value value)
{
ValueReference valueReference = statsContainer.GetValueReference(value);
RecalculateFormulaReference(valueReference);
}

Categories