- Home /
How to get a value and keep it updated
I'm trying to get the hunger value from anotherscript etc and it works, but as it is updated in its script, i can't update it in the current script, since the value is only called once I need some help to work around this:
private AIbehaviour AIb;
private int amountOfWorkers;
private List<int> worker = new List<int>();
public struct WorkersInfo //had no better idea lol
{
public float hunger;
public float sanity;
public float tiredness;
public bool workBoost;
public string Name;
}
private WorkersInfo[] wi = new WorkersInfo[50]; //50 just incase
[Multiline]
private string TextObj = "Workers Status's: \n";
void updateText() {
if (worker.Count == 0) {
worker.Clear();
} else { //grab value from 0 index and remove it, until update is called again
TextObj += "\n" + wi[worker[0]].Name + ": \n" //with a new value ^
+ "- Hunger: " + wi[worker[0]].hunger+ "\n" //updated once here
+ "- Sanity: " + wi[worker[0]].sanity + "\n"
+ "- Tiredness: " + wi[worker[0]].tiredness + "\n"
+ "- Workboost Enabled: " + wi[worker[0]].workBoost + "\n";;
worker.RemoveAt(0); //removed from list again to prevent copying
}
}
void getWorkersInfo() {
foreach (Transform child in workerList) {
AIb = child.GetComponent<AIbehaviour>();
if (AIb.available && !AIb.isCountedIn) { //look for every worker
amountOfWorkers += 1;
worker.Add(amountOfWorkers); //add to list
AIb.isCountedIn = true; //become unfindable to stop duplication
wi[amountOfWorkers].hunger = AIb.hunger; //save the value to var
wi[amountOfWorkers].sanity = AIb.sanity;
wi[amountOfWorkers].tiredness = AIb.tiredness;
wi[amountOfWorkers].Name = AIb.Name;
wi[amountOfWorkers].workBoost = AIb.workBoost;
updateText(); //call update for every worker found
}
}
}
//after all workers are found and correctly added, there is no way of updating its properties any ideas? I also figured that i'd probably have to completely replace the updateText since it will just add new ones, and you can't really update the text's variables only, any ideas people?
Answer by fafase · Aug 01, 2015 at 09:00 AM
Use an event system. Turn your hunger variable into a property that calls the event as well. The other class is registered as listener.
public class HungerClass:MonoBehaviour{
public Action<float> OnHungerChange = ()=>{ };
private float hunger = 0f;
public float Hunger{ // May not need to be public
get{return hunger;}
set{
hunger = value;
OnHungerChange(hunger);}
}
private void OnDestroy(){OnHungerChange = null;}
}
public class HungerListener:MonoBehaviour{
private HungerClass hungerClass = null;
private float hunger = 0f;
void Awake(){
hungerClass = GetComponent<HungerClass>(); // May require to find the object first
if(hungerClass != null){
hungerClass.OnHungerChange += this.OnHungerChangeListener;
}
}
private void OnDestroy(){
if(hungerClass != null){
hungerClass.OnHungerChange -= this.OnHungerChangeListener;
hungerClass = null;
}
}
private void OnHungerClassListener(float newValue){
hunger = newValue;
}
}
So when the HungerClass uses the Hunger property, the variable is updated and the event is called. Any listeners will get the call and will perform whatever action is meant to. This way, no need for checking the original hunger value. Just wait an listen.
The OnDestroy's are here to make sure that if the object is destroyed, it is removed as listener and avoid a null reference exception.
can this be used for multiple instances of hunger? since there is more than one AI
yes. the event is not static so each HungerClass contains its own event. So if you place both components on one AI then GetComponent will find the HungerClass on that object and will not know about HungerClass of other objects.
@fafase In the months since I've been learning Unity (+ new to C#/dev in general), I've learned so much from reading examples like yours above and have gone from completely clueless to kinda getting it, and it's been a fun journey (that I'm still on!).
Events, delegates, LINQ, Patterns and other Intermediate concepts (and I wince at that wondering what Advanced topics have in store) can be sorta baffling to code 101ers. I find the Unity tutorial sequences to be fantastic and it's really awesome that these are made available for free.
Answer by getyour411 · Aug 01, 2015 at 12:03 AM
void Update() {
// do stuff
}
Update is called every frame. See also Invoke, InvokeRepeating, Coroutine
None of what you've said, in the problem description or your reply makes much sense; everything you've said 'there's no way to' and 'you cant update'...you can.
Your answer
Follow this Question
Related Questions
Variable in String 1 Answer
GameObject to Variable to GameObject and add string? 1 Answer
Input Field Text string to string variable. (const string) 0 Answers
Get variable from other GameObject's script 3 Answers
variables as GUI 1 Answer