How do I stop my timer by accessing a variable from another script?
Hi! I need help for something : I have a timer and I need to stop it when I finish the level. But I can only know if the level is finished by accessing the "finished" variable from my playerScript. The problem is : I have no idea of how to do it, especially for the part where I have to access the variable from another script. I have tried several techniques but unfortunately, I don't know why but none of them works...( I'm with Unity 4.6) Here is my code :
public class Timer : MonoBehaviour {
public float timer;
private GUIStyle guistyle = new GUIStyle();
// Use this for initialization
void Start () {
timer = Time.timeSinceLevelLoad;
}
// Update is called once per frame
void Update () {
timer += Time.deltaTime;
}
void OnGUI()
{
float minutes = Mathf.FloorToInt(timer / 60f);
float seconds = Mathf.FloorToInt(timer - minutes * 60);
string niceTime = string.Format("{0:0}:{1:00}" , minutes, seconds);
guistyle.fontSize = 20;
guistyle.normal.textColor = Color.white;
GUI.depth = 1;
GUI.Label(new Rect(10,34,500,200),"Time : "+ niceTime, guistyle);
}
}
public class PlayerScript : MonoBehaviour
{
public bool finished = false;
void OnTriggerEnter (Collider other)
{
if (count >=cubesNeeded && count < maxCubes)
{
WinText.text = "You Win!!!";
GameObject.FindWithTag("cotillons").GetComponent<ParticleSystem>().enableEmission = true;
finished=true;
}
}
}
Just to make sure I understand. You're trying to access the bool finished outside of the PlayerScript? Correct?
Yes, it is the main thing I want. If I succeed in doing this I think I could work it out to stop the timer when the level is finished. ☺
Answer by KoenigX3 · Jan 09, 2017 at 07:24 PM
If you want to access a variable or a method from another script, you need a reference to the gameobject - to which the script is attached. Then you should use GetComponent() on the gameobject to access the script.
bool isFinished = playerObject.GetComponent<PlayerScript>().finished;
This line will create a boolean variable, and access the PlayerScript class (which is attached to the playerObject as a script component) from which it will return the boolean called 'finished'.
Note that there are several error possibilities in this line:
The playerObject can not be null.
The playerObject has to have a PlayerScript attached to it.
The 'finished' variable has to be public.
Also, you should not use GetComponent frequently. If you need to access a script more times, you should create a variable which has a type of the script's class name (in this case: PlayerScript) and fill that variable with a reference to the PlayerScript component. From there you can always access the script as long as it's in the scene.
The last thing: in your example, you want to stop a timer when a boolean variable becomes true. Instead of checking it in the Update() function, you should rather use a different way. Create a new method which does two things: sets the 'finished' variable to true, and calls a 'StopTimer()' function, which should be a public function on the timer script. By using this, you are much more efficient and performance-friendly.
Ok so I tried doing what you said in the first part of your comment so I did public GameObject playerObject=GameObject.Find ("player"); bool isfinished = playerObject.GetComponent<PlayerScript>().finished;
but when I build the code I get this error message : A field initializer cannot reference the nonstatic field, method, or property 'Time.playerObject' ... what did I do wrong?
PS : Also , I did not really understand how to create that method and where (I'm a beginner at Unity) so... can you give me an example in code or something? And thank you for taking the time to answer me ☺
The problem is that you are writing the lines at the beginning of the class. You should only declare variables first, do not initialize them. You should only do that later. For example:
public class TimerScript : $$anonymous$$onoBehaviour {
// Declaration
GameObject playerObject;
PlayerScript playerScript;
bool isFinished;
void Start ()
{
// Initialization
playerObject = GameObject.Find("player");
playerScript = playerObject.GetComponent<PlayerScript>();
}
}
What are we doing here? We are declaring a GameObject-typed variable, called playerObject - it will be a reference to the "player" object in the scene, after the GameObject.Find() method finds it. The playerScript variable is a reference to the PlayerScript component on the playerObject. You can get these references at the start of the game, if they were created in the editor, the script will find them. But the boolean variable is another problem.
Variables have two types: value and reference. Value types refer to a value, reference types refer to an object. For example, the boolean variable always stores 'true', or 'false', so it has value type. But the GameObject is a reference type variable, so it will point to a GameObject.
Now, the problem is that when you are initializing reference type variables, you are telling them the object to point to. They will point to it, no matter what. If the position or even the name of the object changes, it will still refer to it. But value types will not. When you write:
bool isfinished = playerObject.GetComponent<PlayerScript>().finished;
it will create an 'isFinished' variable, checks the type of 'finished' in the PlayerScript, and copies it. The 'isFinished' variable will not refer to the 'finished' variable, so when it changes, the 'isFinished' will still have the same value, which was assigned to it at the initialization.
That's why you have to update 'isFinished' with the value of 'finished' whenever you want to check it. Also, you don't even have to create a new variable for this, because you'll always have to check the original variable.
I assume that you set the 'finished' variable to true in the PlayerScript, when the player finishes the game. When you set 'finished' to true, you could also write a line where you access the Timer script, and call a function there - this function can be filled with whatever you want to do with the timer, when the game is over.
// Put this after you set 'finished' to true on the PlayerScript
GameObject.Find("Timer").GetComponent<TimerScript>().StopTimer();
And the TimerScript should have a public StopTimer() function - which you are calling with the line above.
So ins$$anonymous$$d of checking the 'finished' variable every time in the Update() function (to catch where it switches to true) you can call a 'StopTimer()' function when you set it to true.
Thank you so much for taking the time to answer me and explain me with so many details! It finally worked! I am so grateful, thank you :)
Answer by agentc0re · Jan 09, 2017 at 07:13 PM
So here's one really cool thing about unity. When you want to access things in another script, just define it like you would a variable!!
public class Timer : MonoBehavior {
//your other variables are here
public PlayerScript playerScript = new PlayerScript();
//your other code here
//to access finished just do this
if(playerScript.finished)
//do something cool!
HTH!
Your answer is incorrect. By doing this, you are creating a new instance of the playerScript class which has nothing to do with the one that is on the player's gameobject. If you want to access a variable on a specific class, you can't just use the type itself.
You can test this by creating a gameobject with the PlayerScript on it, and creating a reference to it. If you check the variables, the one you have created has none of its variables updated since nothing refers to it. However if you access the script of the gameobject, you will be able to get the corresponding variables that you want.
I would say that both our answers are correct. I just tested my method and it indeed works.
$$anonymous$$y way also does not require that you attach your script to a empty gameObject.
What do you mean by testing it? If you mean compiling without errors, it will compile for sure. But it will not give the results as expected.
And what do you mean when you say 'does not require that you attach your script to an empty gameObject'? The PlayerScript should be attached to the Player gameObject to handle movement and other stuff. How does it affect a gameObject in any way, if you don't have the script attached to any gameObject?
Your answer
Follow this Question
Related Questions
WHY !! CountDown not Working inside the IF Conndition !!! 2 Answers
Button doesn't work on specific part of the game 0 Answers
Help with unity object selection and movement. 0 Answers
Need help with making disappearing platforms. Error CS1525 1 Answer
Timer float not evaluating correctly when I check if it's less than another number 3 Answers