質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.33%

C#(Unity) 代入した変数を他のスクリプトでも使いたい

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 1,566

Ranom

score 10

前提・実現したいこと

Unityで4択のクイズゲームを制作しています。
csvファイルを用いて問題と答えを作っています。

上のソースコード(スクリプト)で定めた「問題の正解」を
下のソースコードでも使い、正誤判定しようとしています。

しかし、下のソースコードで参照した際、「問題の正解」に代入した変数がなくなってしまいます。
原因と解決方法を教えていただけると嬉しいです。

発生している問題・エラーメッセージ

上の説明だとわかりづらいと思うので、下にある二つのソースコードと併せて、再度実現したいことを説明させていただきます。

上のソースコードの最後で、正しい答えとなるcsvデータ(csvDatas[k][1])をAnswerTextというString型に入れています。

★AnswerText内に代入したテキスト(csvデータ)を別スクリプトのanswerTextにさらに代入したい、という感じです。

<補足>
エラーコードは出ていません。
上のソースコードのAnswerSetメソッド内にあるDebug.Logでは正しく答えのテキストが表示されます。
しかし、下のソースコードのStartメソッド内にあるDebug.Logでは何も表示されず、Answerメソッド内のDebug.Logではnullが表示されます。

uGUIボタンを押すと、下のソースコード内のAnswerメソッドが行われるように設定してあります。

下のソースコードの最後にあるDebug.Log(正解)(不正解)は全て不正解と表示されます。(代入がうまくいっていないため)

該当のソースコード

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.IO;
using System.Linq;

public class QuizMgr : MonoBehaviour
{
    public string dataName;
    public string title;
    public TextAsset csvFile;
    public List<string[]> csvDatas = new List<string[]>();
    public int height = 0;
    public int i, j = 0;
    public int k = 0;
    internal Text ansLabel;
    public string AnswerText;
    const int size = 5;

    // Start is called before the first frame update
    void Start() {

        title = "theme_";
        csvFile = Resources.Load("CSV/" + title + dataName) as TextAsset;
        StringReader reader = new StringReader(csvFile.text);

        while(reader.Peek() > -1){
            string line = reader.ReadLine();
            csvDatas.Add(line.Split(','));
            Debug.Log("reading:" + height);
            height++;
        }

        for(i=0; i < height; i++)
        {
            for(j = 0; j < size; j++){
                Debug.Log("csvDatas[" + i + "][" + j + "]:" + csvDatas[i][j]);
            }
        }

        QuestionLabelSet();
        AnswerLabelSet();
        AnswerSet();
    }


    public void QuestionLabelSet(){
        csvDatas[k] = csvDatas[Random.Range(0, 4)];
        //特定の名前のオブジェクトを検索してアクセス
        Text qLabel = GameObject.Find("Quiz/QLabel").GetComponentInChildren<Text>();
            //データをセットすることで、既存情報を上書きできる
            qLabel.text = csvDatas[k][0];
    }


    public void AnswerLabelSet(){
        //問題文に対応した答えをそれぞれのuGUIボタンにセット
        string[] array = new string[]{ csvDatas[k][1], csvDatas[k][2], csvDatas[k][3], csvDatas[k][4]};

        //問題文をシャッフル
        array = array.OrderBy(x => System.Guid.NewGuid()).ToArray();

        //ボタンが4つあるのでそれぞれ代入
        for(int i=1; i<=4; i++){
            Text ansLabel = GameObject.Find("Quiz/AnsButton" + i).GetComponentInChildren<Text>();
            ansLabel.text = array[i - 1];
        }
    }
  //問題の箇所①
    public void AnswerSet(){
        //答えとなるcsvデータを変数として型に代入する
        string AnswerText = csvDatas[k][1];
        Debug.Log(AnswerText);
    }

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

    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.IO;

public class Judge : MonoBehaviour
{

    QuizMgr quizMgr;
    string answerText;

    void Start()
    {
   //問題の箇所②
        quizMgr = GameObject.Find("Script").GetComponent<QuizMgr>();
        //QuizMgrスクリプトからAnswerTextを持ってくる
        string answerText = quizMgr.AnswerText;
        //中身の表示
        Debug.Log(answerText);

    }

    //選択したボタンのテキストラベルと正解のテキストを比較して正誤を判定
    public void Answer()
    {
        //選択したボタンのテキストを取得する
        Text selectedBtn = this.GetComponentInChildren<Text>();

        if (selectedBtn.text == answerText){
            Debug.Log("正解");
        } else {
            Debug.Log("不正解");
        }

    }
}

試したこと

最初は取り込んだcsvDatasを読み込んで正誤判定しようとしていました。
(選んだボタンのテキストがcsvDatas[k][1]なら正解)
しかし、IndexWasOutOfRangeのエラーがでてしまい、解決できなかったため
今の方法にチェンジしました。(やり方としてはどちらも間違っていないはず?)

補足情報(FW/ツールのバージョンなど)

Unityは2019 1.2fです。
ヒントや推測でもいただけると嬉しいです。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+2

public void AnswerSet(){
        //答えとなるcsvデータを変数として型に代入する
        string AnswerText = csvDatas[k][1];
        Debug.Log(AnswerText);
    }


ここで、クラスメンバーではなくローカル変数に答えを代入してるのが問題だと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/07/01 13:01

    k.matsudaさん、ご回答ありがとうございます。

    QuizMgrのスクリプトで、最初に

    public string AnswerText;

    と宣言をしているので、ここのAnswerTextもグローバル変数になっているはずと思います。
    (もしここでも特別な宣言が必要な場合は、教えていただけると幸いです)

    もう少し挑戦してみて、無理そうだったら他の正誤判定の方法も考えてみたいと思います。
    ありがとうございました!

    キャンセル

  • 2019/07/01 15:38 編集

    string AnswerText = csvDatas[k][1];
    ここを
    AnswerText = csvDatas[k][1];
    こうしてみてください。

    Judgeクラスのこれも
    string answerText = quizMgr.AnswerText;

    answerText = quizMgr.AnswerText;
    で良いと思います。

    キャンセル

  • 2019/07/02 11:53

    できました!

    ここで再び string を使うとローカル変数に代入してしまうのですね・・・
    ある程度の基礎はわかっているつもりでしたが、まだまだ勉強が足りなかったみたいです。
    k.matsudaさん、教えていただきありがとうございます!

    引き続き制作頑張ります!

    キャンセル

+1

QuizMgrのStartより早くJudgeのStartが実行されているのではないかと思います。
(何も設定していない場合、各スクリプトのStartをどのような順番で実行するかはUnityが勝手に決めます)

QuizMgrのStartをAwakeに変えるか、Script Execution OrderでQuizMgrを先に実行するように設定すれば動くのではないかと思います。
Script Execution Order - Unity マニュアル

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/07/01 12:57

    sakura_hanaさん。ご回答ありがとうございます!

    回答を参考にQuizMgrのStartメソッドをAwakeに変えてみました。
    しかし、結果は変わらず、変数の受け渡しはできませんでした。

    ですが、原因のひとつである可能性はあったと思います。このままAwakeメソッドを採用したいと思います。ありがとうございます!

    キャンセル

  • 2019/07/01 16:09 編集

    それでも変わらないのはk.matsudaさんの回答で指摘されている通りですね。
    「public string AnswerText」としていても、「string AnswerText = csvDatas[k][1];」とした場合、この2つの変数は別物として扱われます。後者はこのメソッド内でしか生きないローカル変数なので、結果的にpublic側のAnswerTextは空のままです。

    キャンセル

  • 2019/07/02 11:57

    sakura_hanaさん、補足いただきありがとうございます!

    後者の string をはずしたところ、上手くいきました!
    型の宣言とローカル変数についてまだ理解できていなかったみたいです。

    お二方とも、ありがとうございました!
    制作、勉強、共に精進していきたいです!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.33%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る