If float is greater or equal, doesn't work?
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?
Answer by Bunny83 · Jan 30, 2017 at 06:23 AM
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:
public void AddExperience(float amount)
{
experience += amount;
if (experience >= required)
{
experience = 0;
required *= 2f;
}
}
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.
Well, that's actually useful, Yes, I know that when using public variables a hacker can use the registry of the computer to change the values of a script, and as I said in the question: "I just made this little script to study a little", it is obvious that I would Change many things in this script, but at no time had I thought of using something like this, thanks for the clarification! I'm going to do some tests here, too.
Uhm, by
you just don't know who might increase / decrease or set the value
I did not ment "persons" or "hacker" but other classes you wrote. Having a variable public or private doesn't change anything in relation to "hackers". A "hacker" (or cheater to be correct) would in most cases either decompile / modify your code directly, using reflection to tinker with your values or using "black-box" memory hacks like "cheat engine" or "memhack" does. In all those cases private or public is irrelevant. $$anonymous$$aking something private is a "self-restriction", nothing more. It should prevent you from using things you shouldn't use from outside that class.
Answer by malkere · Jan 30, 2017 at 03:47 AM
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.
This script is attached to the Character only. I actually didn't counted, but i must have at least 20 scripts that interact with this one, BUT of course i wouldn't just add random numbers to a float every single frame.
All the scripts that add a value to the "experience" float have to meet a certain condition first, and they will only add the value once. Also, even if i set experience's value on the editor, it seems to still ignore the if statement, and this doesn't make ANY SENSE AT ALL, and that's why i am so confused. Btw i don't see how using Debug.Log
would help in anything, it's not a matter of knowing what added what, but of literally what's happening.
I mean, where would i add a log anyway? The if statement is being ignored so there is no reason to use a log there and i already did it anyways. Using it on the Update Void would be... let's say "bad", and the list goes on...
Setting up a conditional breakpoint in the script editor while debugging could be useful for knowing when or if the condition is true. Obviously Debug.Log could also work.
Well you're making several pro errors, but you're obviously not a pro, so that's fine, but it makes your life a lot more difficult. Your experience really shouldn't be public it should be private and you should be calling a public void AddExperience (float amount) {} method to add to your experience. If you use that method you can put a Debug.Log("anything"); statement in that method and it will show you every time anything calls it and where that call originated from, what line of what script, etc. If you don't track backwards what's happening there's no way to know what's going wrong. Everything makes sense once you figure it out, but you can't figure it out writing it that way you have. That's what Bunny83's answer is showing you how to do, and what I was kind of side-stepping
What? I haven't see any "pro errors" in my script at least nothing so serious, i literally made it in less than one $$anonymous$$ute... Again, "I just made this little script to study ", it's not my "way" to waste precious time in a simple script that i am eventually going to change anyways, i just want it to work. Everytime you make a variable public, you are exposing your game to hackers, as they can use a dirty method with 3 specific softwares that can and will check your software's security, find a deter$$anonymous$$ed registry, and then allow the hacker to change everything, but i am not concerned with things like this, as i am going to use my own methods of encryption and i am working on a mmo, so i will leave the security measures for the server itself, it's pretty easy to detect if someone just changed their data before actually making it go to the server. And yes, using Update is bad, but i don't care, it isn't exactly going to use 30% of the player's CPU or anything like that at the moment, and i am not sure why did you say to acquire the text once, it IS doing that.
Server encryption isn't really the problem, it's letting the client report its own variables, you have to do everything server side or they can just say whatever they want.
Well, that's why i said:
it's pretty easy to detect if someone just changed their data before actually making it go to the server.
I've asked a friend to test my scripts and it worked fine on his computer, so i unninstalled Unity and reinstalled it and it worked for some reason, it's just sad that for many users, the engine is getting... "unusable" with the new version. Anyway, the fact that you did not read what I wrote or just do not understand is funny, as i mentioned, i know what to, and how a server works, you don't have to tell me that, and yes, i've replied Bunny83's answer saying that I hadn't thought of that method, and that was useful, thanks for again telling me something i already knew (no offense), and frankly if my software glitched, it isn't my fault by making a simple script, i write it the way i want, it's my script. But anyway, best wishes for you too, glad i could solve my problem! =)
When a client processes a random number and returns it to the server that means the server has absolutely no understanding of how the number was generated. it is not at all easy to tell when someone has changed client data. encryption is used to protect data on its way to the server from the client so a third party cannot intercept it.
And no offense taken, we were all young at one time =]
Your answer
Follow this Question
Related Questions
How do I convert speed and heading to a vector? 3 Answers
Reducing a float as another increases 0 Answers
Variables check with If problem 2 Answers
Help with my IF statement using floats. 1 Answer
Unity Infinity Math Result 0 Answers