Unity4択クイズ、NCMB(外部サーバ)から問題と答えを取得する。

下の記事で作ったクイズをいじっていきます。今はコードの中にべた書きで答え・選択肢を書いているので、変更したい場合いちいちビルドを行わないといけません。

今回は外部サーバNCMBからデータを取得し問題を作成することを目的に行います。

ニフクラの使い方 https://mbaas.nifcloud.com/doc/current/introduction/quickstart_unity.html

ニフクラでの準備。

上の写真のように、ニフクラ上に問題とそれに対する選択肢を。

*Opt1を正解の選択肢にしておきます。

unity側での準備

プレハブ化されたsettingとmanagerをhierarchy内にドロップ。

アプリケーションキーとクライアントキーをコピペする。

こーど。

今回は非同期処理についてはやっていないので、5秒間松という力業を用いています。次回改良していきます。

using System.Threading.Tasks;
using UnityEngine;
using System.Collections;
using UnityEngine.UI;//UI オブジェクトを扱う時は必須
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Random = UnityEngine.Random;
using NCMB;
using System;



public class Question : MonoBehaviour {

    public string[] questions = {};
    public int num;
    public string nQJ;
    public static  string answer;
    private NCMBQuery<NCMBObject> query;
    private string[][] arrayOption;
 
     //アタッチしたオブジェクトが呼ばれた時に実行される。
    void Start () {
        getword();
    }

    async void getword (){
    NCMBQuery<NCMBObject> query = new NCMBQuery<NCMBObject> ("Ques");
    // 配列操作用のカウンター
    int counter =0;
    
    arrayOption = new string[0][];
    //検索を行う
    query.FindAsync ((List<NCMBObject> objList ,NCMBException e) => {
        if (e != null) {
            //検索失敗時の処理
        } else {
            foreach (NCMBObject obj in objList) {
                Array.Resize(ref arrayOption,arrayOption.Length + 1);
                Array.Resize(ref questions, questions.Length + 1);
                var getDate = obj ["ques"].ToString();
                var getOpt = obj ["Opt1"].ToString();
                var getOpt2 = obj ["Opt2"].ToString();
                var getOpt3= obj ["Opt3"].ToString();
                var getOpt4 = obj ["Opt4"].ToString();
                arrayOption[counter] = new string[4]{getOpt,getOpt2,getOpt3,getOpt4};
                questions[counter] = getDate;
                counter++;
            } 
        }
    });
    await Task.Delay(5000);
    num = Random.Range(0,counter);
    nQJ = questions[num];
    QuestionLabelSet();
    AnswerLabelSet();
    }


    private void QuestionLabelSet(){

        //特定の名前のオブジェクトを検索してアクセス
        Text qLabel = GameObject.Find("Quiz/QuestionField").GetComponentInChildren<Text> ();
        //データをセットすることで、既存情報を上書きできる
        qLabel.text = nQJ;
    }
    private void  AnswerLabelSet(){
        answer = arrayOption[num][0];
        arrayOption[num].Shuffle();
        //ボタンが4つあるのでそれぞれ代入
        for (int i=1; i<=4 ; i++){

            Text ansLabel = GameObject.Find("Quiz/AnsButton" + i).GetComponentInChildren<Text> ();
            ansLabel.text = arrayOption[num][i-1];
        }
    }
    
    public static string get()
    {
        return answer;
    }



}

public static class Extensions  //拡張メソッド用 static クラス(名前は任意)
{
    //配列の要素をシャッフルする (Fisher-Yates shuffle)
    public static void Shuffle<T>(this T[] arr)
    {
        for (int i = arr.Length - 1; i > 0; i--)
        {
            int j = Random.Range(0, i + 1);  //[0]~[i]
            T tmp = arr[i];     //swap
            arr[i] = arr[j];
            arr[j] = tmp;
        }
    }
}

完成図

問題点

・一問ごとにクエリを行うので回数が気になる。

・出題方式を変更するほうが好ましい(10問連続で問題を出す。OR シーン遷移を用いない。 OR 前段階でクエリを実行して配列を保存しておく。などなど)

次回

・非同期処理を書いていきます。

ちょっとした説明を

getOptのところはforeach文で簡潔に書くことができます。

配列の数を一つ増やして、そこにcounterで狙いを定めてぶち込んでいる感じです。

    query.FindAsync ((List<NCMBObject> objList ,NCMBException e) => {
        if (e != null) {
            //検索失敗時の処理
        } else {
            foreach (NCMBObject obj in objList) {
                Array.Resize(ref arrayOption,arrayOption.Length + 1);
                Array.Resize(ref questions, questions.Length + 1);
                var getDate = obj ["ques"].ToString();
                var getOpt = obj ["Opt1"].ToString();
                var getOpt2 = obj ["Opt2"].ToString();
                var getOpt3= obj ["Opt3"].ToString();
                var getOpt4 = obj ["Opt4"].ToString();
                arrayOption[counter] = new string[4]{getOpt,getOpt2,getOpt3,getOpt4};
                questions[counter] = getDate;
                counter++;
            } 
        }
    });

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です