Value correctly initializes, but breaks when updating - c#

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);
}

Related

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;
}

Unity 2d İ had some error ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection

Hello guys I'm newbie in unity and c# i was trying make little game but i have a an error i cant fix that can you help me? and whats wrong? you explain so I can learn? I'm making a mistake somewhere but I don't understand where...
I also looked at the friends who got the same error in the forums, but I could not find the relevance of what was said with my code.I also made these codes with the things I learned on youtube, so if there are mistakes, please excuse me
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine.UI;
public class LobbyNetworkManager : MonoBehaviourPunCallbacks
{
int number;
public Text su;
private List<RoomItemUI> _roomList = new List<RoomItemUI>();
[SerializeField] private RoomItemUI _roomItemUIPrefab;
[SerializeField] private Transform _roomListParent;
[SerializeField] private Text _statusField;
[SerializeField] private Button _leaveRoomButton;
private void Start()
{
Initialize();
Connect();
}
#region PhotonCallbacks
public override void OnConnectedToMaster()
{
Debug.Log("Connected to master server");
PhotonNetwork.JoinLobby();
}
public override void OnRoomListUpdate(List<RoomInfo> roomList)
{
UpdateRoomList(roomList);
}
public override void OnDisconnected(DisconnectCause cause)
{
Debug.Log("Disconnect");
}
public override void OnJoinedLobby()
{
Debug.Log("Joined Lobby!");
}
public override void OnJoinedRoom()
{
_statusField.text = "Joined" + PhotonNetwork.CurrentRoom.Name;
Debug.Log("Joined Room " + PhotonNetwork.CurrentRoom.Name);
_leaveRoomButton.interactable = true;
}
public override void OnLeftRoom()
{
_statusField.text = "Lobby";
Debug.Log("Left Room");
_leaveRoomButton.interactable = false;
}
#endregion
private void Initialize()
{
_leaveRoomButton.interactable = false;
}
private void Connect()
{
PhotonNetwork.NickName = "Player" + Random.Range(0, 5000);
PhotonNetwork.ConnectUsingSettings();
PhotonNetwork.AutomaticallySyncScene = true;
}
private void UpdateRoomList(List<RoomInfo> roomList)
{
//clear current list of room
for (int i = 0; i < roomList.Count; i++)
{
Destroy(_roomList[i].gameObject);
}
_roomList.Clear();
//Generate a new list with the updated info
for(int i = 0; i < roomList.Count; i++)
{
//skip empty rooms
if(roomList[i].PlayerCount == 0) { continue; }
RoomItemUI newRoomItem = Instantiate(_roomItemUIPrefab);
newRoomItem.LobbyNetworkParent = this;
newRoomItem.SetName(roomList[i].Name);
newRoomItem.transform.SetParent(_roomListParent);
_roomList.Add(newRoomItem);
}
}
public void JoinRoom(string roomName)
{
PhotonNetwork.JoinRoom(roomName);
}
public void CreateRoom()
{
number = Random.Range(1000000, 9999999);
PhotonNetwork.CreateRoom(su.text + number, new RoomOptions() { MaxPlayers = 4 }, null);
}
public void LeaveRoom()
{
PhotonNetwork.LeaveRoom();
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using UnityEngine;
public class RoomItemUI : MonoBehaviour
{
public LobbyNetworkManager LobbyNetworkParent;
[SerializeField] private Text _roomName;
public void SetName(string roomName)
{
_roomName.text = roomName;
}
public void OnJoinPressed()
{
LobbyNetworkParent.JoinRoom(_roomName.text);
}
}

UNity3d Adding a value via button and getting random results

i found my next tier 1 problem and hoping for some help here in the so called internet.
first of all here are my atm not to hard to understanding codes.
please tell me if im doing something wrong here on stackoverflow im an absolute newbie and dont know how to explain my problem in this case without post a bunch of code :(
i know there are much ways to improve mystuff but im in the learning process and for now its maybe enough to tell my why the behavior of my code didnt match my expectations.
This is my PlayerClass:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player_Values : MonoBehaviour
{
public float MaxNrg;
public float Nrg;
public float NrgDrain;
public float NrgDrainCoef;
public float NrgInPercent;
// Start is called before the first frame update
public void Start()
{
MaxNrg = 7950.0f;
Nrg = 7950.0f;
NrgDrain = 0.09201389f;
NrgDrainCoef = 1.0f;
}
// Update is called once per frame
public void Update()
{
}
public void FixedUpdate()
{
NrgInPercent = (GETnrg() / GETmaxnrg()) * 100;
}
public void SETmaxnrg(float tmpfloat)
{
MaxNrg = tmpfloat;
}
public void SETnrg(float tmpfloat)
{
Nrg = tmpfloat;
}
public void SETnrgdrain(float tmpfloat)
{
NrgDrain = tmpfloat;
}
public void SETnrgdraincoef(float tmpfloat)
{
NrgDrainCoef = tmpfloat;
}
public void ADDmaxnrg(float tmpfloat)
{
MaxNrg += tmpfloat;
}
public void ADDnrg(float tmpfloat)
{
Nrg += tmpfloat;
}
public void ADDnrgdrain(float tmpfloat)
{
NrgDrain += tmpfloat;
}
public void ADDnrgdraincoef(float tmpfloat)
{
NrgDrainCoef += tmpfloat;
}
public float GETmaxnrg()
{
return MaxNrg;
}
public float GETnrg()
{
return Nrg;
}
public float GETnrgdrain()
{
return NrgDrain;
}
public float GETnrgdraincoef()
{
return NrgDrainCoef;
}
public float GETnrginpercent()
{
return NrgInPercent;
}
}
End Here are the "Drain_mechanics":
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Drain_Mechanics : MonoBehaviour
{
public bool drainstate = false;
public double NrgLeftInSeconds;
public GameObject Scriptcontainer_Player;
// Start is called before the first frame update
public void Start()
{
Scriptcontainer_Player = GameObject.Find("Scriptcontainer_Player");
}
// Update is called once per frame
public void Update()
{
}
public void FixedUpdate()
{
if(drainstate == true)
{
Scriptcontainer_Player.GetComponent<Player_Values>().Nrg -= Scriptcontainer_Player.GetComponent<Player_Values>().GETnrgdrain() * Time.deltaTime * Scriptcontainer_Player.GetComponent<Player_Values>().GETnrgdraincoef();
}
else if(drainstate == false)
{
}
NrgLeftInSeconds = Scriptcontainer_Player.GetComponent<Player_Values>().GETnrg() / (Scriptcontainer_Player.GetComponent<Player_Values>().GETnrgdrain() * Scriptcontainer_Player.GetComponent<Player_Values>().GETnrgdraincoef());
}
public void SETdrainstate(bool tmpdrainstate)
{
drainstate = tmpdrainstate;
}
public double GETnrgleftinseconds()
{
return NrgLeftInSeconds;
}
}
Class for initializing the input fields in the game:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.Text.RegularExpressions;
public class Initialize_InputFields : MonoBehaviour
{
public GameObject Input_Energy;
public GameObject Input_Drainrate;
public GameObject Input_DrainCoef;
public float InputNrg;
public float InputNrgDrainrate;
public float InputNrgDrainCoef;
// Start is called before the first frame update
public void Start()
{
Input_Energy = GameObject.Find("Input_Energy");
Input_Drainrate = GameObject.Find("Input_Drainrate");
Input_DrainCoef = GameObject.Find("Input_DrainCoef");
}
// Update is called once per frame
void FixedUpdate()
{
InputNrg = float.Parse(Input_Energy.GetComponent<InputField>().text);
InputNrgDrainrate = float.Parse(Input_Drainrate.GetComponent<InputField>().text);
InputNrgDrainCoef = float.Parse(Input_DrainCoef.GetComponent<InputField>().text);
}
public float GETinputnrg()
{
return InputNrg;
}
public float GETinputnrgdrainrate()
{
return InputNrgDrainrate;
}
public float GETinputnrgdraincoef()
{
return InputNrgDrainCoef;
}
}
a class to manipulate the textfields while the game is running
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Display_LabelsCalculated : MonoBehaviour
{
public GameObject Scriptcontainer_Player;
public GameObject Scriptcontainer_GameMechanics;
public GameObject Display_Energy;
public GameObject Display_EnergyDrain;
public GameObject Display_EnergyDrainCoef;
public GameObject Display_EnergyTimeleft;
public GameObject Display_EnergyPercentleft;
public Text Display_Energy_Text;
public Text Display_EnergyDrain_Text;
public Text Display_EnergyDrainCoef_Text;
public Text Display_EnergyTimeleft_Text;
public Text Display_EnergyPercentleft_Text;
// Start is called before the first frame update
void Start()
{
Scriptcontainer_Player = GameObject.Find("Scriptcontainer_Player");
Scriptcontainer_GameMechanics = GameObject.Find("Scriptcontainer_GameMechanics");
Display_Energy = GameObject.Find("Display_Energy");
Display_EnergyDrain = GameObject.Find("Display_EnergyDrain");
Display_EnergyDrainCoef = GameObject.Find("Display_EnergyDrainCoef");
Display_EnergyTimeleft = GameObject.Find("Display_EnergyTimeleft");
Display_EnergyPercentleft = GameObject.Find("Display_EnergyPercentleft");
Display_Energy_Text = Display_Energy.GetComponent<Text>();
Display_EnergyDrain_Text = Display_EnergyDrain.GetComponent<Text>();
Display_EnergyDrainCoef_Text = Display_EnergyDrainCoef.GetComponent<Text>();
Display_EnergyTimeleft_Text = Display_EnergyTimeleft.GetComponent<Text>();
Display_EnergyPercentleft_Text = Display_EnergyPercentleft.GetComponent<Text>();
}
// Update is called once per frame
public void Update()
{
}
public void FixedUpdate()
{
int hours = (int)(Scriptcontainer_GameMechanics.GetComponent<Drain_Mechanics>().GETnrgleftinseconds() / 60) / 60;
int minutes = (int)(Scriptcontainer_GameMechanics.GetComponent<Drain_Mechanics>().GETnrgleftinseconds() / 60) % 60;
int seconds = (int)Scriptcontainer_GameMechanics.GetComponent<Drain_Mechanics>().GETnrgleftinseconds() % 60;
Display_EnergyTimeleft_Text.text = hours.ToString() + ":" + ((minutes < 10) ? ("0") : ("")) + minutes.ToString() + ":" + ((seconds < 10) ? ("0") : ("")) + seconds.ToString();
Display_Energy_Text.text = Scriptcontainer_Player.GetComponent<Player_Values>().GETnrg().ToString();
Display_EnergyDrain_Text.text = Scriptcontainer_Player.GetComponent<Player_Values>().GETnrgdrain().ToString();
Display_EnergyDrainCoef_Text.text = Scriptcontainer_Player.GetComponent<Player_Values>().GETnrgdraincoef().ToString();
Display_EnergyPercentleft_Text.text = Scriptcontainer_Player.GetComponent<Player_Values>().GETnrginpercent().ToString();
}
}
followed by some button mechanics
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Button_Mechanics : MonoBehaviour
{
public GameObject Scriptcontainer_Player;
public GameObject Scriptcontainer_InputFields;
public GameObject Scriptcontainer_GameMechanics;
public Button Button_SetEnergy;
public Button Button_SetDrainCoef;
public Button Button_SetDrainrate;
public Button Button_AddEnergy;
public Button Button_AddDrainCoef;
public Button Button_AddDrainrate;
public Button Button_ActivateMechanics;
public Button Button_DeactivateMechanics;
public Button Button_ResetValues;
// Start is called before the first frame update
public void Start()
{
Scriptcontainer_Player = GameObject.Find("Scriptcontainer_Player");
Scriptcontainer_InputFields = GameObject.Find("Scriptcontainer_InputFields");
Scriptcontainer_GameMechanics = GameObject.Find("Scriptcontainer_GameMechanics");
Button_SetEnergy = GameObject.Find("Button_SetEnergy").GetComponent<Button>();
Button_SetDrainCoef = GameObject.Find("Button_SetDrainCoef").GetComponent<Button>();
Button_SetDrainrate = GameObject.Find("Button_SetDrainrate").GetComponent<Button>();
Button_AddEnergy = GameObject.Find("Button_AddEnergy").GetComponent<Button>();
Button_AddDrainCoef = GameObject.Find("Button_AddDrainCoef").GetComponent<Button>();
Button_AddDrainrate = GameObject.Find("Button_AddDrainrate").GetComponent<Button>();
Button_ActivateMechanics = GameObject.Find("Button_ActivateMechanics").GetComponent<Button>();
Button_DeactivateMechanics = GameObject.Find("Button_DeactivateMechanics").GetComponent<Button>();
Button_ResetValues = GameObject.Find("Button_ResetValues").GetComponent<Button>();
}
public void Update()
{
}
// Update is called once per frame
public void FixedUpdate()
{
Button_SetEnergy.onClick.AddListener(SETnrgbtnclk);
Button_SetDrainCoef.onClick.AddListener(SETnrgdraincoefbtnclk);
Button_SetDrainrate.onClick.AddListener(SETnrgdrainbtnclk);
Button_AddEnergy.onClick.AddListener(ADDnrgbtnclk);
Button_AddDrainCoef.onClick.AddListener(ADDnrgdraincoefbtnclk);
Button_AddDrainrate.onClick.AddListener(ADDnrgdrainbtnclk);
Button_ActivateMechanics.onClick.AddListener(SETactivatemechanicsbtnclk);
Button_DeactivateMechanics.onClick.AddListener(SETdeactivatemechanicsbtnclk);
Button_ResetValues.onClick.AddListener(SETresetbtnclk);
}
public void SETnrgbtnclk()
{
Scriptcontainer_Player.GetComponent<Player_Values>().SETnrg(Scriptcontainer_InputFields.GetComponent<Initialize_InputFields>().GETinputnrg());
}
public void SETnrgdrainbtnclk()
{
Scriptcontainer_Player.GetComponent<Player_Values>().SETnrgdrain(Scriptcontainer_InputFields.GetComponent<Initialize_InputFields>().GETinputnrgdrainrate());
}
public void SETnrgdraincoefbtnclk()
{
Scriptcontainer_Player.GetComponent<Player_Values>().SETnrgdraincoef(Scriptcontainer_InputFields.GetComponent<Initialize_InputFields>().GETinputnrgdraincoef());
}
public void ADDnrgbtnclk()
{
Scriptcontainer_Player.GetComponent<Player_Values>().ADDnrg(Scriptcontainer_InputFields.GetComponent<Initialize_InputFields>().GETinputnrg());
}
public void ADDnrgdrainbtnclk()
{
Scriptcontainer_Player.GetComponent<Player_Values>().ADDnrgdrain(Scriptcontainer_InputFields.GetComponent<Initialize_InputFields>().GETinputnrgdrainrate());
}
public void ADDnrgdraincoefbtnclk()
{
Scriptcontainer_Player.GetComponent<Player_Values>().ADDnrgdraincoef(Scriptcontainer_InputFields.GetComponent<Initialize_InputFields>().GETinputnrgdraincoef());
}
public void SETactivatemechanicsbtnclk()
{
Scriptcontainer_GameMechanics.GetComponent<Drain_Mechanics>().SETdrainstate(true);
}
public void SETdeactivatemechanicsbtnclk()
{
Scriptcontainer_GameMechanics.GetComponent<Drain_Mechanics>().SETdrainstate(false);
}
public void SETresetbtnclk()
{
Scriptcontainer_Player.GetComponent<Player_Values>().SETnrg(7950);
Scriptcontainer_Player.GetComponent<Player_Values>().SETnrgdrain(0.09201389f);
Scriptcontainer_Player.GetComponent<Player_Values>().SETnrgdraincoef(1.0f);
}
}
at this point i apollogize one more time the amount of text im posting here but otherwise i cant even explain whats going on. and im not able to pick the exact codesnippets which are needed here. it will be better in future.
basically the main mechnisms work fine and im absolutely proud of what i did here...
my problems are the following.
Major problem 1. when i enter a value in the input fields and perform the button SET actions, i HAVE to do it in a specific order. NRG->DRAIN->COEF
otherwise the calculated textboxes are doing random stuff.
Major problem 2. when i try to perform the button add actions, the game also do random stuff. even when i set all variable to fixed values.
minor problem 3. in the Initialize_InputFields.cs im using the float.parse functionality. and my game constantly create warnings about a formatexception. is there a smarter way to solve this.
minor problem 4. last but not leat i want to work with realtime values. is there a way in unity to accerlate the globale timescale for the whole game?

The member XXX cannot be used as a method or delegate

I have done copied this of a tutorial online, but when I compile it shows 2 errors as below:
Non-invocable member 'Feature.choices' cannot be used like a method
and
The member `Feature.choices' cannot be used as method or delegate
The last "choices" in the script has a red squiggly line. Any idea that might be wrong?
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
[ExecuteInEditMode]
public class FeatureManager : MonoBehaviour {
public List<Feature> features;
public int currFeature;
void OnEnable()
{
LoadFeatures();
}
void OnDisable()
{
SaveFeatures();
}
void LoadFeatures()
{
features = new List<Feature>();
features.Add(new Feature(("hair"), transform.FindChild("hair").GetComponent<SpriteRenderer>()));
}
void SaveFeatures()
{
}
}
[System.Serializable]
public class Feature
{
public string ID;
public int currIndex;
public Sprite[] choices;
public SpriteRenderer renderer;
public Feature(string id, SpriteRenderer rend)
{
ID = id;
renderer = rend;
UpdateFeature();
}
public void UpdateFeature()
{
choices = Resources.LoadAll<Sprite>("Character/" + ID);
if (choices == null || renderer == null)
return;
if (currIndex < 0)
currIndex = choices.Length - 1;
if (currIndex >= choices.Length)
currIndex = 0;
renderer.sprite = choices(currIndex);
}
}
Change this
renderer.sprite = choices(currIndex);
to this:
renderer.sprite = choices[currIndex]; // use square brackets not parenthesis

Unity3D , Error GetItem(int 32)

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)...

Categories