0

I am trying to check if the value in string word from one class matches any element in the array stringAnswers in another and if it does i want the score to increment by 1. For some reason the code im using below increments the score by 1,2 and 3 depending on the word that is displayed any help would be awesome cheers.

public class Player : MonoBehaviour 
{
    public int Score = 0;

    private string[] StringAns = {"steve", "grace", "lilly"};

    // Use this for initialization
    void Start () 
    {
    }

    // Update is called once per frame
    void Update ()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            RaycastHit hit;

            if (Physics.Raycast(transform.position, transform.forward, out hit))
            {
                if (hit.transform.GetComponent<ButtonNo>()  != null)
                {
                    foreach (string stringAnsers in StringAns)
                    {

                        if (stringAnsers.Equals(FindObjectOfType<GameController>().word))
                        {
                            Debug.Log(" Button has been looked at");
                            FindObjectOfType<GameController>().RandText();
                        }
                        else
                        {
                            Debug.Log(" Button has been looked at");
                            FindObjectOfType<GameController>().RandText();

                            Score++;
                        }
                    }
                }
            }

            if (Physics.Raycast(transform.position, transform.forward, out hit))
            {
                if (hit.transform.GetComponent<ButtonYes>() != null)
                {
                    foreach (string stringAnsers in StringAns)
                    {
                        if (stringAnsers.Equals( FindObjectOfType<GameController>().word) )
                        {
                            Debug.Log(" Button has been looked at");
                            FindObjectOfType<GameController>().RandText();

                            Score++;
                        }
                        else
                        {
                            FindObjectOfType<GameController>().RandText();
                        }
                    }
                }
            }
        }
    }
}

GameController

public class GameController : MonoBehaviour 
{
    public TextMesh InfoText;
    public TextMesh WallText;
    public string word;
    public Player player;

    public string[] Strings = { "stev", "lilly", "grace" };

    // Use this for initialization
    void Start()
    {
        RandText();
    }

    // Update is called once per frame
    void Update()
    {

        InfoText.text = "Is this Spelling Correct ?\n Score: " + player.Score;
    }

    public void RandText()
    {
         word = Strings[Random.Range(0, Strings.Length)];

        WallText = GameObject.Find("WallText").GetComponent<TextMesh>();
        WallText.text = word;
    }
}

2 Answers 2

2

In general you should call FindObjectOfType<GameController>() only once e.g in Start

private GameController _gameController;

private void Start()
{
    _gameController= FindObjectOfType<GameController>();
}

and than reuse that _gameController reference everywhere instead of FindObjectOfType<GameController>().

The same for WallText in GameController:

public TextMesh WallText;

private void Start()
{
    WallText = GameObject.Find("WallText").GetComponent<TextMesh>();
    RandText();
}

public void RandText()
{
    word = Strings[Random.Range(0, Strings.Length)];
    WallText.text = word;
}

better would even be you already reference those in the Inspector in Unity via drag&drop than you don't have to use Find at all


Than to your problem: You are setting a new value for word in every iteration for the loop

foreach (string stringAnsers in StringAns)
{
    if (stringAnsers.Equals(FindObjectOfType<GameController>().word))
    {
        Debug.Log("Button has been looked at");
        FindObjectOfType<GameController>().RandText();
    }
    else
    {
        Debug.Log("Button has been looked at");
        FindObjectOfType<GameController>().RandText();

        Score++;
    }
}

So it might happen that the word doesn't match so you call Score++; but at the same time you do FindObjectOfType<GameController>().RandText(); everytime so a new random word is generated/selected for each iteration.

So in the next iteration of the foreach loop you check against a new random word which might or might not match the next answer string in the list.


Instead you should only generate a new random word after the loop is done e.g. like

foreach (string stringAnsers in StringAns)
{
    if (stringAnsers.Equals(FindObjectOfType<GameController>().word))
    {
        Debug.Log("Button has been looked at-> matched");
        Score++;
    }
    else
    {
        Debug.Log("Button has been looked at -> didn't match");
    }
}

FindObjectOfType<GameController>().RandText();

Note this would still add 1-3 points depending how many of the given stringAnswer match the word. So you should add a break; after increasing Score once if you want only 1 added.


Using Linq you could also do this in only one line instead a loop:

if(StringAns.Any(answer => string.Equals(answer, _gameController.word)))) Score++;

_gameController.RandText();

or for the No button

if(!StringAns.Any(answer => string.Equals(answer, _gameController.word)))) Score++;
Sign up to request clarification or add additional context in comments.

8 Comments

Sorry first time on here and I missed a bit out, I have 2 objects as cubes which are yes and no buttons so to speak of. so if the player gets the correct answer the score increments by one and then a new random word from the array strings is displayed
yes ... and I adressed that telling you that currently you select a new random list for each stringAnswer so they are probbably all compared to different random words. move the RandText after the loop and either add the break keyword after increasing the Score or use the Linq solution at the bottom
It seem to work but for some real strange reason, the word grace and lilly give boths a score for yes and no so i think there is something wrong when matching the strings
The linq version you gave works a treat so thank you very much for that but Because i like to solve problems im going to have to find out why the other way doesnt .
@SteveDeeks well it depends what is in your StringAns ... if all three names are allways there than there will be allways one of them matching the random word
|
0

I guess the problem is that you are generating a new random word inside the foreach loop that check the word itself. Also, i suggest you not to use a foreach loop, because items inside the array could be more that 3 items, so it could slow the method. I suggest you to use contains instead, like so:

if (StringAns.Contains(FindObjectOfType<GameController>().word))
{
      Debug.Log(" Button has been looked at");
      Score++;
}
else
      Debug.Log(" Button has *not* been looked at");

FindObjectOfType<GameController>().RandText();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.