- Home /
Multiple choice game not working!?!
firstly, heres my code:
var target : StartSprite;
var targetScript : ChangeSprite;
var AcceptInput : boolean = true;
private static var score : int = 0;
var guiScore : GUIText;
function Update () {
if(!AcceptInput)
{
return;
}
AcceptInput = false;
Debug.Log("Clicked");
if(target.spriteRenderer.sprite == target.diamond) {
score +=1;
guiScore.text = "Score: " + score;
StartCoroutine("Click");
targetScript.enabled = true;
}
else {
StartCoroutine("Click");
targetScript.enabled = true;
Debug.Log("Wrong Answer");
}
}
if(Input.GetMouseButtonUp(0)) {
targetScript.enabled = false;
changeSprite ();
}
}
function Click () {
yield WaitForSeconds (0.5);
}
function changeSprite (): IEnumerator {
if(Input.GetMouseButtonDown(0)) {
if(!AcceptInput)
{
return;
}
AcceptInput = false;
if(targetScript.spriteRenderer.sprite == targetScript.diamond) {
score +=1;
guiScore.text = "Score: " + score;
yield WaitForSeconds (0.5);
targetScript.enabled = true;
}
else {
yield WaitForSeconds (0.5);
targetScript.enabled = true;
Debug.Log("Wrong Answer");
}
if(Input.GetMouseButtonUp(0)) {
AcceptInput = true;
targetScript.enabled = false;
changeSprite ();
}
}
}
So basically if you press the button it would check what the sprite of another object is and if it is the correct answer, then add a score then enable another script which changes the sprite of the object. For some weird reason this is just not out properly. If I press the button, it would add a score before the sprite even displayed on the screen. It's supposed to be something like a multiple choice question, but if I press the button, it would add the score because the sprite that is the correct answer is displayed after the sprite that was currently displayed, why is it behaving like this? Does anyone have any ideas? I REALLY need help. I've been trying to figure this out for days! (Just to let you know I'm not being lazy so I asked the question on unity answers) Any help would be much appreciated. Thanks :D
Answer by DESTRUKTORR · Aug 17, 2014 at 11:22 PM
Firstly, the code you wrote up there wouldn't compile. Your braces are all kinds of off (you've got an entire if statement outside of all functions, and an extra curly brace after the end of that, to boot).
You've got your check for Input.GetMouseButtonUp(0) within the braces that would only have been reached if Input.GetMouseButtonDown(0) would have to be true, meaning that the check to Input.GetMouseButtonUp(0) will always return false, when you check it there.
Secondly, I would strongly suggest against using coroutines like that. Update tends to run a bit irregularly, and it can be very difficult to debug a program where you've got two things running at different rates, like that. I would suggest checking against Time.deltaTime to time your stuff.
Thirdly, if the target script is the script that tracks the next answer, then why are you checking against its "diamond" value? You should be tracking the current answer, as the script will not enable itself unless you set its "enabled" property to "true," which you only do if the "diamond" variable is found to be the same as the sprite that was clicked.
Really, I would suggest using a completely different code structure, as it would be much easier to debug. Sprites are not intended to be used as booleans in the way you're using them, and it would really be much easier to read and predict if you used another type to store those values.
Not to mention, I have no clue what the "diamond" value is, other than some kind of sprite. Check where that value is set, and see if it's being set to the proper value (the one that is connected to the answer you wanted).
EDIT
To better explain coroutines, put the following code in a js script:
#pragma strict
function Update () {
StartCoroutine(YieldTestEnumerator());
Debug.Log("I DIDN'T. Time = " + Time.time);
//Debug.Break();
}
function YieldTestEnumerator()
{
Debug.Log("I STARTED. Time = " + Time.time);
yield WaitForSeconds(0.5);
Debug.Log("I WAITED. Time = " + Time.time);
Debug.Break();
}
The thing to note here is that "I STARTED" was printed before "I DIDN'T." This would be expected in any normal execution order language. However, notice that "I DIDN'T" is printed several times before "I WAITED" is ever printed, and you can even confirm by the time stamp that it is, indeed, being called FIRST.
Ok, but what does this mean? Well, it means that putting a coroutine and telling it to wait a certain amount of time to "delay" the function that called it doesn't work. What "yield" essentially does is it passes back control over the system to the "update" function, and is called again, if it is supposed to.
For example, WaitForSeconds causes the function to essentially "pick up" where it "left off" before the yield, after the given number of seconds has passed (in pretty close to real-time).
What this does not do is stop the function that called it from executing for that amount of time, so your update function will continue its own execution, despite the fact that the end of the Click function (which is really "nothing," since there is no code after the yield statement) is not completed until 0.5 seconds have passed, which is usually going to be at least a few frames (about 30, assuming a 60fps run speed) later, and thus Update (and the function that comes after the coroutine call) will actually be called about 30 times before the ending of the coroutine.
Now, keeping all this in mind, what I would suggest to you is that in your Update function, you should save the time (Time.time) when the user clicks into a float field, somewhere, and check the current time against that time to see if 0.5 seconds have passed, within the update function, and if it is: Execute the code. This is only the way I would probably do it (if it weren't a performance-critical location in the code, at least).
However, you can certainly still use enumerators and coroutines and whatnot, though I think what you want is more along the lines of Invoke, which is essentially a delayed invocation of a given function. You would essentially invoke the method you want to be called in 0.5 seconds, and have that function contain the instructions for what to do, based on what the user clicked.
First and foremost, I would work out the kinks in your conditionals, because again, as you have it, there are a few parts of this code that will essentially never get called, and I strongly suspect that you would want them to be called, given certain criteria.
Ok..... but what kind of structure should I use? the code that is going to be enabled is to change the sprite of a object randomly. And the code above is for an answer button. So if you press the button, it would check if the sprite of the object is the sprite variable "diamond" and if it is it would add a score. Plus I used 2 functions because there is 2 different scripts. At the start (function Update()) you can only press once because at the start of the scene, "target" variable (the script) generates a random sprite for the object. Then after the button is pressed there is different function for the rest of the time. In that function if the button is pressed it checks the other script because (which would only change the sprite if the script is enabled) then it checks if the sprite is correct. Lets just rewrite the script all together and write it your code structure way.
Allow me to update my answer to better explain how coroutines actually work.
Ok, I changed my whole code due to your code above:
var text : GUIText;
var object : GameObject;
var diamond : Sprite;
var circle : Sprite;
var triangle : Sprite;
var square : Sprite;
var number : int;
var spriteRenderer;
var target : Timer;
var AcceptInput : boolean = true;
static var score : int = 0;
static var guiScore : GUIText;
function Start () {
spriteRenderer = object.GetComponent(SpriteRenderer);
number = Random.Range(1,4);
if(number == 1) {
spriteRenderer.sprite = diamond;
}
else if(number == 2) {
spriteRenderer.sprite = circle;
}
else if (number == 3) {
spriteRenderer.sprite = triangle;
}
else {
spriteRenderer.sprite = square;
}
}
function Update () {
if(Input.Get$$anonymous$$ouseButtonDown(0)) {
if(AcceptInput) {
AcceptInput = false;
text.enabled = false;
target.enabled = true;
Debug.Log("Clicked");
if(object.GetComponent(SpriteRenderer).sprite == diamond) {
score += 1;
guiScore.text = "Score: " + score;
StartCoroutine("YieldTestEnumerator");
spriteRenderer = object.GetComponent(SpriteRenderer);
number = Random.Range(1,4);
if(number == 1) {
spriteRenderer.sprite = diamond;
}
else if(number == 2) {
spriteRenderer.sprite = circle;
}
else if (number == 3) {
spriteRenderer.sprite = triangle;
}
else {
spriteRenderer.sprite = square;
}
}
if(object.GetComponent(SpriteRenderer).sprite == circle) {
Debug.Log("Wrong Answer!");
Application.LoadLevel("GameOver");
}
if(object.GetComponent(SpriteRenderer).sprite == triangle) {
Debug.Log("Wrong Answer!");
Application.LoadLevel("GameOver");
}
if(object.GetComponent(SpriteRenderer).sprite == square) {
Debug.Log("Wrong Answer!");
Application.LoadLevel("GameOver");
}
if(Input.Get$$anonymous$$ouseButtonUp(0)) {
AcceptInput = true;
}
}
}
function YieldTestEnumerator () {
yield WaitforSeconds (0.5);
}
but it gives the following errors:
Assets/Scripts/GA$$anonymous$$E/buttons/Diamond.js(142,10): BCE0044: expecting (, found 'YieldTestEnumerator'.
Assets/Scripts/GA$$anonymous$$E/buttons/Diamond.js(142,32): UCE0001: ';' expected. Insert a semicolon at the end.
Assets/Scripts/GA$$anonymous$$E/buttons/Diamond.js(145,1): BCE0044: expecting }, found ''.
But I don't find anything wrong with my
function YieldTestEnumerator () {
yield WaitforSeconds (0.5);
}
code. All of the errors seem to be in that area. Do you have any ideas?
These are all common errors. Read them thoroughly and look to the lines that they are referring to.
For example
Assets/Scripts/GA$$anonymous$$E/buttons/Diamond.js(142,32): UCE0001: ';' expected. Insert a semicolon at the end.
Looks as though it is referring to a semicolon that was expected at the end of a statement.
Assets/Scripts/GA$$anonymous$$E/buttons/Diamond.js(145,1): BCE0044: expecting }, found ''.
Indicates to me that you have a missing closing curly brace. Check all your curly braces and make sure the blocks start and end where they should be starting and ending.
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
GUI problem 1 Answer
Yield function goes slow sometimes/differently? 2 Answers
Gui placement help 1 Answer
Script behaving too early 1 Answer