Hey guys, i am probaly missing something very very basic here, but i sincerely don’t know what is wrong with this little script i made:
public float experience;
public float required;
public GameObject txt;
void Update()
{
txt.GetComponent<UnityEngine.UI.Text>().text = experience.ToString() + "/" + required.ToString();
if (experience >= required)
{
experience = 0;
required = required + required;
}
}
I just made this little script to study a little about script communication and all, so i made a lot of scripts “interact” with this one. I made it so when i do some specific thing, a script will add a value to “experience”, but for some reason when experience gets to the value of required or more, it just doesn’t do anything. Why is my IF statement being ignored?
Without testing i can say for sure that the code in this script works as it should. Your problem is most likely somewhere else. Actually it’s bad practice to constantly checking the experience every frame. Also having several scripts tinker with public variables can also be a problem as you just don’t know who might increase / decrease or set the value.
It’s better to use a proper “interface”. I don’t mean an interface type but simply a method to manipulate the experience. So the actual variable can be private. Just add a method like this:
By having every other script using that method to manipulate the value you can output a Debug.Log and get an exact stack trace everytime the value is changed.
If you don’t want to change all of your scripts, you can also replace the variable with a property:
private float m_Experience;
public float experience
{
get { return m_Experience;}
set {
m_Experience = value;
if (m_Experience >= required)
{
m_Experience = 0;
required *= 2f;
}
}
}
Same as with the “AddExperience” method you can add a Debug.Log inside the setter to see who is changing the property.
You might want to add the objects name to the debug log as well as a context object, just to make sure it really is attached to the right object:
Debug.Log(gameObject.name + " setting experience to: " + experience, this);
The “this” at the end is our context object. When you click on that Debug.Log message in the console, Unity will “ping” / highlight that object.
Is this script a monobehavior attached to something? Are you calling the correct instance of it? You could have 700 copies of this script in your game for all we know ;p Maybe you didn’t know that is why I say so.
First and foremost, always use Debug.Log();
using UnityEngine;
using System.Collections;
//adding this lets you use UI components without calling UnityEngine.UI everytime
using UnityEngine.UI;
public class MyScript: MonoBehaviour {
public float experience;
public float required;
//assigning the Text once instead of reaquiring it every frame is faster
public Text txt;
float timer = 0;
void Update() {
//Debug.Log every frame is really annoying,
//use something like this to only do it once per second
timer += Time.deltaTime;
if (timer > 1) {
timer -= 1;
Debug.Log("Exp: " + experience.ToString() + ". Req: " + required.ToString());
}
txt.text = experience.ToString() + "/" + required.ToString();
if (experience >= required) {
experience -= required;
required *= 2f;
}
}
}
There’s nothing inherently wrong with the way your script is written, so something else is messing with it. The script I wrote won’t really give you any new information since you’re writing it to your txt already, but you might find that it is debugging twice per frame or something unexpected. It sounds like your cross-script communication is getting messed up somehwere. The Debug.Log() will show you it’s whole path if you click on it in the console, which would be useful if you were using a method to update the exp and txt rather than Udate, you could see who called it, etc.