Simon Timing Issue!!!

Hey guys! I have been working on a tutorial for a while, and I managed to get everything working… well, everything that they showed in the tutorial. I even managed to figure out how and where to add the code needed to keep score, which was painful, but I did it.

I am not a programmer - I am an artist that can’t find a programmer, so I’m trying to teach myself. Thanks for your patience!!!

MY ISSUE, SPECIFICALLY
Whenever the Simon pattern rolls through, it doesn’t pause before allowing the next color to light up. This is causing a long Light-Up period whenever the pattern chooses two of the same number in a row. I have searched high and low, and discovered this:

yield return new WaitForSeconds(1);

I figured this would work, but it just gives me all sorts of errors…

Here’s the full Simon Code:

```csharp
*using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System.Collections.Generic;

struct SimonLightPlate
{
public enum eType
{
INVALID_TYPE = -1,
BLUE,
GREEN,
RED,
PURPLE,
YELLOW,
NUM_TYPES
}

public SimonLightPlate( string plateName)
{
    plate = GameObject.Find(plateName);
}

public GameObject plate; //This is the plate associated with the colors

}

public class SimonSays : MonoBehaviour
{
public Text ScoreText;
private int MahScore;

//related to the speed of delivery, not length of light
public float displaySequenceRepeatInterval = 0.5f;
SimonLightPlate[] lightPlates = new SimonLightPlate[(int)SimonLightPlate.eType.NUM_TYPES];

enum eState
{
    INVALID_STATE = -1,
    THINKING,
    DISPLAY_SEQUENCE,
    WAITING_FOR_USER,
    NUM_STATES
}

eState currentState = eState.INVALID_STATE;

List<int> sequence = new List<int>(5); //holds the sequence
int sequenceCount = 0; // the counter for which index of the sequence we're currently showing.

List<int> clickedSequence = new List<int>(5);

// Use this for initialization
void Start ()
{
    lightPlates[(int)SimonLightPlate.eType.BLUE] = new SimonLightPlate ("BluePlane");
    lightPlates[(int)SimonLightPlate.eType.GREEN] = new SimonLightPlate ("GreenPlane");
    lightPlates[(int)SimonLightPlate.eType.RED] = new SimonLightPlate ("RedPlane");
    lightPlates[(int)SimonLightPlate.eType.PURPLE] = new SimonLightPlate ("PurplePlane");
    lightPlates[(int)SimonLightPlate.eType.YELLOW] = new SimonLightPlate ("YellowPlane");

// MahScore = 0;
// ScoreText.text = MahScore.ToString ();

    ResetGame();
    InvokeRepeating("DisplaySequence", 1, displaySequenceRepeatInterval);
}

void OnLeftClickDown(SimonLightPlate.eType color)
{
    if (currentState == eState.WAITING_FOR_USER)
    {
        lightPlates[(int)color].plate.GetComponent<Renderer>().enabled = true;
        clickedSequence.Add((int)color);
    }
}

void OnLeftClickUp(SimonLightPlate.eType color)
{
    if (currentState == eState.WAITING_FOR_USER)
    {
        lightPlates[ (int) color].plate.GetComponent<Renderer>().enabled = false;
        if (!VerifySequence())
        {

            ResetGame();
        }
        else
        {
            if (clickedSequence.Count == sequence.Count)
            {
                currentState = eState.THINKING;
                MahScore = MahScore + 1;
                ScoreText.text = MahScore.ToString();
                clickedSequence.Clear();
            }
        }
    }
}

// Update is called once per frame
void Update ()
{
    if (currentState == eState.THINKING)
    {

    // Add new sequence
    AddNewSequence ();
   
    }
}

bool VerifySequence()
{
    // vERIFY THE SEQUENCE UP UNTIL THAT POINT WHERE THE USER LEFT OFF.
    for (int i = 0; i < clickedSequence.Count; ++i)
    {
        if (clickedSequence[i] != sequence[i])
        {
            return false;
        }
    }
    return true;
}

void DisplaySequence()
{
    if (currentState == eState.DISPLAY_SEQUENCE)
    {
        //We're at the next sequence, so turn off the previous one.

        if (sequenceCount > 0)
        {
            lightPlates[sequence [sequenceCount-1] ].plate.GetComponent<Renderer>().enabled = false;
        }
        //We're at the end; collect user input now.
        if (sequenceCount == sequence.Count)
        {
            currentState = eState.WAITING_FOR_USER;
        }
        else
        {
            lightPlates[sequence [sequenceCount] ].plate.GetComponent<Renderer>().enabled = true;
            // Add Audio Here
            // AudioSource
            ++sequenceCount;
        }
   
    }
}

void AddNewSequence()
{
    sequence.Add (Random.Range (0,5)); //This is where we change from 4 to 5 tokens.
    currentState = eState.DISPLAY_SEQUENCE;
    sequenceCount = 0;



}
void RetryGame()
{
    for (int i = 0; i < (int)SimonLightPlate.eType.NUM_TYPES; ++i)
    {
        lightPlates[i].plate.GetComponent<Renderer>().enabled = false;
    }
}


void ResetGame()
{
    MahScore = 0;
    ScoreText.text = MahScore.ToString();
    currentState = eState.THINKING;
    sequence.Clear ();
    clickedSequence.Clear ();
    sequenceCount = 0;
    RetryGame ();


}

}
_```*
I feel like the Wait code should be somewhere in the DisplaySequence void, but no matter where I place it, I get errors.
Can anybody explain what I’m doing wrong? I’m trying to understand the syntax but like I said, I make pretty pictures! It’s been ten years since I last touched VB6, and another ten years since BASIC, QBASIC and Liberty BASIC.
Thank in advance! And to the guy that’s going to say, “[negativity redacted] USE GOOGLE, [flippant assumptions of my intelligence redacted],” please know that I spent two days searching for the ability to create my own scores, and succeeded. I spent four days trying to solve this timer issue, and I have not had any success. I love the community, and I want you to know I really tried my best before coming here! Please don’t beat me with the google stick! Hahah! :slight_smile:_

Could you edit you post and add code tags around the code please.

Okay, it’s in the code box! :slight_smile:

1 Like

yield can only be used in a Coroutine. Unity - Scripting API: Coroutine

Thanks! I created a co routine called Blink. The documentation said that the WaitForSeconds had to be made as an IEnumerator, so I did that.

That didn’t work, so thanks to your tip on coroutines I expanded my search and discovered I couldn’t use fractions of seconds with WaitForSeconds, because IEnumerator is an int and fractions I reckon have to be a float.

I created a private float called BlinkTimer and made it (0.2).

Then I adjusted my Blink script to read

Yield return new WaitForSeconds(BlinkTimer);

And then made the other side as:

yield return ("Blink");

I am commuting right now so I don’t have the code with me right now, so that’s from memory… But it doesn’t matter, because I tried every configuration I could imagine, and eventually I managed to create a build that would still run.

The problem is that if I place my call line…

yield return ("blink");

… inside of the spot where I think it needs to go, it tells me that it won’t work because I’m trying to call it inside of a void.

The specific spot I think it needs to be is line 145 from the code above, in the DisplaySequence void.

I have tried putting that line everywhere, but it just won’t take.

The variable and waitforseconds parts were placed right underneath the DisplaySequence void…

Do they need to be placed higher up? And where do I call for my Blink?

Thanks for your help, I really appreciate it. I try as much as possible before saying It Doesn’t Work. You took the time to help and I respect that.

this is not true. yield can be used in any method which returns IEnumerator / IEnumerator or IEnumerable / IEnumerable.
A Unity Coroutine which seems to be the way to go here must have the return value IEnumerator.

no. IEnumerator is an IEnumerator. It is for iterating through something (in this case: some wait instructions). It is waiting for the yield before moving on.

the yield can return a couple of things. e.g. a WaitForSeconds instance. that WaitForSeconds wants a float as parameter which describes the time in seconds to wait for.

@OwlTeaGames : I have no Idea what you want to do with this code. I think you didn’t really understand how Coroutines work.

so I give you an example of a Coroutine:

IEnumerator MyCoroutine()
{
    Debug.Log("Beginning of Coroutine");

    yield return new WaitForSeconds(3.3f);

    Debug.Log("Coroutine after 3.3 seconds");
}

you can start your Coroutine from any Method inside a MonoBehaviour like this:

StartCoroutine(MyCoroutine());

hope this helps a bit :wink:

2 Likes