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

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

新規登録して質問してみよう
ただいま回答率
85.30%
Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

3回答

676閲覧

Unity 問題数がとても多いクイズを作るにあたって最適な方法が知りたい

Tora_ou

総合スコア7

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

0クリップ

投稿2025/06/05 17:21

編集2025/06/05 18:22

実現したいこと

例えば全部の問題数が200曲有るイントロクイズを作るとします
「再生ボタン」が有って押すと曲が再生されます
選択肢は問題毎に異なる5個のボタンが表示されてそのうち1つのボタンだけが正解です
問題は全部で200曲有りますがそのうちの5曲(5問)だけをランダムで出題したいです
これを実現するにあたってどのような方法が最も効率が良いのでしょうか。

発生している問題・分からないこと

自分なりにいくつか試してみたのですがどれも微妙で他に良い方法があるはず、という結論です。
自分が実際にやろうとしてみた方法は以下の2つです。
1:シーンを問題の数だけ、つまり200個作る
かなりの力技ですが200個のシーンを作り、1シーンに1曲づつ、全部別々に200回シーンを作る、という方法です
30個ぐらいまでは実際に作ってみたのですがこれが200回も続くのか。。。という感じでここで質問するに至りました
30個の時点でちゃんと動いている(全30シーンから5シーンをランダムで出す)
のでこのまま200個のシーンが作れたなら間違いなく動くんだけどさ・・・200個って・・・ねぇ

2:Prefab化して200個のPrefabを作る
これも上の方法とほぼ同じで200個もPrefabを作るなら上の方法と同じぐらい手間だし、
なによりPrefab化した段階でアタッチが全部外れてしまいどう対処していいかわからず・・・

該当のソースコード

特になし

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

おそらくPrefab化して、それを200個も作る必要は無くて
Prefab化した段階で全部外れてしまったアタッチの部分、例えば「再生ボタン」には
200曲ある音楽ファイルうちのどれかがランダムに入って、ランダムに入ったその曲と対応した正解のボタンが表示されるような処理が出来れば良いのでしょうが
何をどうすればそんなことが可能なのか全くわかりません

補足

特になし

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Tora_ou

2025/06/06 14:21

CSVを使う方法を詳細に書いてくれてありがとうございました。 最初の質問「Unity 問題数がとても多いクイズを作るにあたって最適な方法が知りたい」 については解決したと思うので解決済にしたいと思います。ありがとうございました。 みなさまが教えてくれたおかげでやる気がモリモリ沸いてきたので この方法で私が理解&実践出来るかは未知数ですが今から実際にこの方法でやってみたいと思います。
t594570

2025/06/06 16:31

✅ 効率的な実装方法:CSV+スクリプトで動的に問題を生成する 200問すべてをPrefabやSceneで管理するのは大変なので、CSVファイル+C#スクリプトで動的に問題を生成する方式をおすすめします。 🔧 ステップ1:問題用のクラスを定義 csharp 複製 編輯 public class Question { public string musicName; // 音声ファイル名 public List<string> options; // 選択肢(5つ) public string correctAnswer; // 正解 } 📄 ステップ2:CSVファイルを作成 「Resources」フォルダ内に questions.csv を作成します。 1行につき1問で、以下のような形式にします: 複製 編輯 music1,選択肢1,選択肢2,選択肢3,選択肢4,選択肢5,正解 music2,選択肢1,選択肢2,選択肢3,選択肢4,選択肢5,正解 例: mathematica 複製 編輯 music1,Song A,Song B,Song C,Song D,Song E,Song C music2,Song F,Song G,Song H,Song I,Song J,Song H 音声ファイル(例:music1.mp3)は「Resources/Music」に配置してください。 💻 ステップ3:CSVを読み込み、問題リストを作成 csharp 複製 編輯 using System.Collections.Generic; using System.IO; using UnityEngine; public class QuizManager : MonoBehaviour { public List<Question> questions = new List<Question>(); void Start() { LoadQuestions(); List<Question> selected = GetRandomQuestions(5); // 選ばれた問題を画面に表示(省略) } void LoadQuestions() { TextAsset csvFile = Resources.Load<TextAsset>("questions"); StringReader reader = new StringReader(csvFile.text); while (reader.Peek() > -1) { string line = reader.ReadLine(); string[] values = line.Split(','); if (values.Length >= 7) { Question q = new Question { musicName = values[0], options = new List<string> { values[1], values[2], values[3], values[4], values[5] }, correctAnswer = values[6] }; questions.Add(q); } } } List<Question> GetRandomQuestions(int count) { List<Question> result = new List<Question>(); List<int> used = new List<int>(); while (result.Count < count && used.Count < questions.Count) { int index = Random.Range(0, questions.Count); if (!used.Contains(index)) { used.Add(index); result.Add(questions[index]); } } return result; } } 🎵 ステップ4:音楽の再生と選択肢表示 csharp 複製 編輯 AudioClip clip = Resources.Load<AudioClip>("Music/" + question.musicName); audioSource.clip = clip; audioSource.Play(); UIはスクリプトで動的にボタンを生成して、選択肢を表示させます。 🟢 メリット プレハブ不要、Scene増えない CSVで一括管理、修正・追加が簡単 複数の問題をランダムに抽出できる 拡張性が高い(問題数増えても対応可)
t594570

2025/06/06 16:32

もちろんです。以下は、teratail の質問「200問の音楽クイズを効率的に出題・管理するには?」に対する日本語での丁寧な回答です。 --- ### ✅ 効率的な実装方法:CSV+スクリプトで動的に問題を生成する 200問すべてをPrefabやSceneで管理するのは大変なので、**CSVファイル+C#スクリプト**で動的に問題を生成する方式をおすすめします。 --- #### 🔧 ステップ1:問題用のクラスを定義 ```csharp public class Question { public string musicName; // 音声ファイル名 public List<string> options; // 選択肢(5つ) public string correctAnswer; // 正解 } ``` --- #### 📄 ステップ2:CSVファイルを作成 「Resources」フォルダ内に `questions.csv` を作成します。 1行につき1問で、以下のような形式にします: ``` music1,選択肢1,選択肢2,選択肢3,選択肢4,選択肢5,正解 music2,選択肢1,選択肢2,選択肢3,選択肢4,選択肢5,正解 ``` 例: ``` music1,Song A,Song B,Song C,Song D,Song E,Song C music2,Song F,Song G,Song H,Song I,Song J,Song H ``` 音声ファイル(例:music1.mp3)は「Resources/Music」に配置してください。 --- #### 💻 ステップ3:CSVを読み込み、問題リストを作成 ```csharp using System.Collections.Generic; using System.IO; using UnityEngine; public class QuizManager : MonoBehaviour { public List<Question> questions = new List<Question>(); void Start() { LoadQuestions(); List<Question> selected = GetRandomQuestions(5); // 選ばれた問題を画面に表示(省略) } void LoadQuestions() { TextAsset csvFile = Resources.Load<TextAsset>("questions"); StringReader reader = new StringReader(csvFile.text); while (reader.Peek() > -1) { string line = reader.ReadLine(); string[] values = line.Split(','); if (values.Length >= 7) { Question q = new Question { musicName = values[0], options = new List<string> { values[1], values[2], values[3], values[4], values[5] }, correctAnswer = values[6] }; questions.Add(q); } } } List<Question> GetRandomQuestions(int count) { List<Question> result = new List<Question>(); List<int> used = new List<int>(); while (result.Count < count && used.Count < questions.Count) { int index = Random.Range(0, questions.Count); if (!used.Contains(index)) { used.Add(index); result.Add(questions[index]); } } return result; } } ``` --- #### 🎵 ステップ4:音楽の再生と選択肢表示 ```csharp AudioClip clip = Resources.Load<AudioClip>("Music/" + question.musicName); audioSource.clip = clip; audioSource.Play(); ``` UIはスクリプトで動的にボタンを生成して、選択肢を表示させます。 --- #### 🟢 メリット * プレハブ不要、Scene増えない * CSVで一括管理、修正・追加が簡単 * 複数の問題をランダムに抽出できる * 拡張性が高い(問題数増えても対応可) --- 必要であれば、UI表示やボタン処理の実装例もお送りします。気軽にご質問ください!
Tora_ou

2025/06/07 06:03

丁寧にありがとうございます。 あれから12時間ぐらいかかってなんとか実装出来そうな所まで来ています。
guest

回答2

0

ベストアンサー

まずは問題に関する情報を格納するクラスなり構造体なりを作成する。
例えば

C#

1class Question 2{ 3 public string soundfilename; // 問題の音楽ファイル 4 public List<string> ans; // 回答の文字列が入ったリスト 5 public string correct_answer; // 正解の文字列 6}

これを問題数分作成してリストなりに格納する

C#

1public List<Question> questions; 2// 問題をテキストファイルやCSV等から読み込むなりしてListを構築する

そして、クイズの実際の動作画面にて作成したQuestionクラスから情報を取り出して音楽の再生等の動作を行えるように作成すれば問題のListからランダムで情報を抽出するだけで動作するようになります。
なのでシーンを問題数分作るとかPrefab化するなどしなくてもいいかと思います。

このあたりは普通のクイズの作成を解説しているようなページで解説してそうです。

追記

ちょっと理解されていないようなので具体的な例を
まずResourcesフォルダにquestions.csvというCSVを用意します。
これは1行で問題1問分の情報を示し
問題曲,回答1,回答2,回答3,回答4,回答5
といったフォーマットとしています。

中身は例えば以下のようにします。

csv

1music1,ans1-1,ans1-2,ans1-3,ans1-4,ans1-5 2music2,ans2-1,ans2-2,ans2-3,ans2-4,ans2-5 3music3,ans3-1,ans3-2,ans3-3,ans3-4,ans3-5 4music4,ans4-1,ans4-2,ans4-3,ans4-4,ans4-5 5music5,ans5-1,ans5-2,ans5-3,ans5-4,ans5-5 6music6,ans6-1,ans6-2,ans6-3,ans6-4,ans6-5 7music7,ans7-1,ans7-2,ans7-3,ans7-4,ans7-5 8music8,ans8-1,ans8-2,ans8-3,ans8-4,ans8-5 9music9,ans9-1,ans9-2,ans9-3,ans9-4,ans9-5 10music10,ans10-1,ans10-2,ans10-3,ans10-4,ans10-5

そして、Resourcesフォルダの中にmusicフォルダを作りその中に問題となる音楽ファイルを入れます。
そこに追加したものの名前はmusic1~music10とします。

これで10問分の問題データが作成できました。

そしてスクリプトでは

C#

1 class question 2 { 3 public string musicname; 4 public List<string> ans; 5 }

と問題1問分の情報を格納するクラスを定義します。
そして
List<question> questionList = new List<question>();
といった問題が格納されるリストを定義して

C#

1 // Resourcesからquestions.csvを読み込む 2 TextAsset csvFile = Resources.Load("questions") as TextAsset; /* CSV読み込み */ 3 StringReader reader = new StringReader(csvFile.text); 4 5 // 最後まで読み込む 6 while (reader.Peek() > -1) 7 { 8 // 1行読み込む 9 string line = reader.ReadLine(); 10 // 読み込んだ行をカンマで区切る 11 string[] datas = line.Split(','); 12 13 // 読み込んだデータより1問分の情報クラスを作成する 14 question q = new question() { musicname = datas[0],ans = new List<string>(new string[] { datas[1], datas[2], datas[3], datas[4], datas[5] })}; 15 // 問題Listに追加する 16 questionList.Add(q); 17 }

このような感じでCSVを読み込みます。
これでCSVの内容が問題Listとして保持されます。CSVですから100問だろうが行を増やせばいくらでも問題が増やせます。

そして

C#

1 void QuestionView(int index) 2 { 3 // 前の曲の解放 4 AudioClip before = audioSource.clip; 5 audioSource.clip = null; 6 before?.UnloadAudioData(); 7 8 // 音楽の読み込み 9 AudioClip music = Resources.Load($"music/{questionList[index].musicname}") as AudioClip; 10 11 // 回答するためのボタンに回答文字列をセット 12 13 // 問題の音楽を再生 14 audioSource.clip = music; 15 audioSource.Play(); 16 17 }

といった感じで関数を用意すれば
QuestionView(9);
と指定のindexの問題の準備ができます。
現在出題中の問題は
Question nowquestion;
といった感じで変数を用意して
nowquestion = questionList[9];
と格納しておけばいいでしょう。そうすれば正解判断などもやりやすいかと思います。

あくまで考え方の説明なので正解判断をどうするのかなどの説明はしません。
CSVに選択肢だけではなく正解情報も格納しておいて正解判断できるようにするなどすればいいでしょう。

また音楽ファイルもmusic1といった名前ではなく具体的な曲の名前としてもいいでしょう。ようはCSVの情報とResources/musicフォルダの中の名前が一致すればいいので

あくまで「問題数がとても多いクイズを作るにあたって最適な方法が知りたい」という質問に対する回答となります。
これでイメージが湧きますでしょうか?

投稿2025/06/05 22:36

編集2025/06/06 13:06
YAmaGNZ

総合スコア10592

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Tora_ou

2025/06/06 05:22

音声ファイルを格納するListを作ろうと思ったのですが 例に書いてくれているコードでは変数の型がstringになっているのですが 音声ファイルの型はstringなのでしょうか。List<string> で音声ファイルを格納出来るのでしょうか?  public List<string> myList; public List<string> useList = new List<string>(); private string randomSound; 上のように書いてみるとリストは作られるのですが音声ファイル(MP4)は格納出来ないようでした。 List<GameObject> でも試してみましたがこちらも音声ファイルは格納出来ませんでした。 public List<GameObject> myList; public List<GameObject> useList = new List<GameObject>(); private GameObject randomSound; 音声ファイルを格納したい時、型は何を指定すると良いのでしょうか。
YAmaGNZ

2025/06/06 06:17 編集

変数の型に関しては私がサンプルで書いただけなので実際の型とは異なるかもしれません。 リソースにあるClipとすべきなのかそれを識別するための文字列となるのか***.mp3といったファイル名とするのかは実装次第ではないでしょうか。 ただ1問に必要な情報を1つのクラスなり構造体なりに纏めましょうというのが本質となります。 イントロクイズなのですから曲の情報だけリスト化してもその曲のタイトルの正解などの情報と紐づけないと意味がないと思います。
fiveHundred

2025/06/06 07:12

> 音声ファイルを格納したい時、型は何を指定すると良いのでしょうか。 音声ファイルの型はAudioClipです。
fiveHundred

2025/06/06 07:19

なお、YAmaGNZさんは「問題をテキストファイルやCSV等から読み込むなりしてListを構築する」と言っているので、「インスペクターを直接設定する」とは一言も言ってないので、その点はご注意ください。 もし、テキストファイルやCSVにファイル名を用意し、それから読み込む場合は、「Resources.Load」を使うといいでしょう。
Tora_ou

2025/06/06 11:19

おかげ様で音声ファイルをListに格納→ランダム重複無しで5つ抽出、までは以下のコードで出来ました! public List<AudioClip> myList; //全ての音声ファイルを格納するList public List<AudioClip> useList = new List<AudioClip>(); //クイズで使うランダムな10個の音声ファイルだけを格納するList private AudioClip randomSound; //ランダムで選ばれた音声ファイル private int choiceNum; //ランダムで選ばれた音声ファイルのList番号 void Start() { for (int i = 0; i < 5; i++) //音声ファイルのList全体から5個だけ抽出する { //myListの中から音声ファイルをランダムで1つを選ぶ randomSound = myList[Random.Range(0, myList.Count)]; //選んだ音声ファイルをuseListに追加 useList.Add(randomSound); //選んだ音声ファイルのリスト番号を取得 choiceNum = myList.IndexOf(randomSound); //同じリスト番号をmyListから削除 myList.RemoveAt(choiceNum); } } 次は選ばれた音声ファイルに対応した正解ボタンを表示する、という事が必要になるのですが例えば 音声ファイル09番が選ばれている時に表示させたい選択肢はこれ、みたいな指定があるのですが 今使われている音声ファイルの名前がもし09番だったら、この選択肢を表示して正解はこれ・・・ みたいなif文の書き方が良いのでしょうか?
YAmaGNZ

2025/06/06 11:30

ですから1問の情報を纏めましょうという趣旨の回答なのですが・・・
fiveHundred

2025/06/06 13:09

AudioClip自体のListではなく、例えば class Question { public AudioClip sound; public List<string> ans; public string correct_answer; } というようなクラスを作っておき、 public List<Question> myList; という風にしろというのがYAmaGNZさんの意図です。
Tora_ou

2025/06/06 15:56

CSVを使う方法を詳細に書いてくれてありがとうございました。 最初の質問「Unity 問題数がとても多いクイズを作るにあたって最適な方法が知りたい」 については解決したと思うので解決済にしたいと思います。ありがとうございました。 みなさまが教えてくれたおかげでやる気がモリモリ沸いてきたので この方法で私が理解&実践出来るかは未知数ですが今から実際にこの方法でやってみたいと思います。
Tora_ou

2025/06/06 19:40

あれから4時間ぐらい苦戦しましたがCSVファイルをListに読み込む所までは出来ています! 読み込んだCSVファイルを上手く使えるかどうかはこれからやってみます。 Listの中の特定のデータを指定するのがとても難しく感じます。 慣れだと思うので頑張ります。
Tora_ou

2025/06/07 06:49 編集

※このコメントは次のコメントと内容が重複していて削除依頼を出したが消えないので編集しました
Tora_ou

2025/06/06 21:43

上手くいかないけど色々試していたら止まらなくて徹夜してしまいました。 QuestionView関数 を音声ファイルを再生するボタンに紐づけてみたのですがボタンを押すとエラーで // 前の曲の解放 AudioClip before = audioSource.clip; ↑ここの部分で  NullReferenceException: Object reference not set to an instance of an object エラーで止まるので前の曲の開放はとりあえず無しにしてとりあえず今は1つ目の音声ファイルだけでも再生できれば、と思い // 前の曲の解放 //AudioClip before = audioSource.clip; ↑ここの部分は一旦コメントアウトしておいて // 音楽の読み込み AudioClip music = Resources.Load($"nekoEazy/{questionList[index].MondaiFile}") as AudioClip; // 問題の音楽を再生 audioSource.clip = music; audioSource.Play(); ↑ここだけを記述してみましたが audioSource.clip = music; の部分で同じく NullReferenceException: Object reference not set to an instance of an object エラーでした Debug.Log(music); で確認してみたら music の中にはちゃんと音声ファイル(CSVで一番上のもの)が入ってました Listの中に入っている名前の音声ファイルを再生する、という事が私には未だ出来ないようです 引き続き試行錯誤してみます
YAmaGNZ

2025/06/06 22:12

AudioClip before = audioSource.clip; ↑ここの部分で  NullReferenceException: Object reference not set to an instance of an object エラー ここのaudioSourceはインスペクタ上で設定する前提でコードを書いています。 なのでそのようにしてください。 NullReferenceExceptionは変数の何かがnullなのにそれに対して何かをしようとしたときに発生するエラーとなります。 なのでデバッグ方法としては何がnullになっているのかを確認しそれがnullにならない為には何をすべきなのかを考えます。 今回の場合、audioSourceがnullとなっている状態です。 audioSourceは曲を鳴らすものなのでAudioSourceをどこかから持ってくる必要があります。
Tora_ou

2025/06/06 22:53

audioSource = GetComponent<AudioSource>(); が書かれていなかったことが原因でした これだけの事で1時間半かかりました・・・
Tora_ou

2025/06/07 00:35

questionListの中身はDebug.Logを使ってチェックしているのですが 正解の曲名が Debug.Log(questionList[index].ans[09]); Debug.Log(questionList[index].ans[10]); この部分に間違いなく入っていてコンソールにも表示されています。 しかしこれをテキストに出力しようとエラー(毎度のNull)になってしまうのですが //正解の曲名1を代入・・・したいけどエラー SeikaiKyoku01.text = questionList[index].ans[09]; //正解の曲名2を代入・・・したいけどエラー SeikaiKyoku02.text = questionList[index].ans[10]; using TMPro; の宣言は有ります インスペクターで表示したいテキストの部分はちゃんとアタッチされています 「” ”」が必要なのかと思い、付けてみましたが変わらずエラーでした。 SeikaiKyoku01.text = "questionList[index].ans[09]"; ↓こうすればもちろん問題無くテキストが書き換えられて出力されるので SeikaiKyoku01.text = "これだとこの文章が出力されます"; Listの中身をテキストに出力する際には何か注意点が有るのでしょうか。 正解の曲名がテキストに出力できない理由は何なのでしょうか。
YAmaGNZ

2025/06/07 01:21

現状のコードがわからないので何とも言えません。 別建てで質問したほうがいいかもしれません。
Tora_ou

2025/06/07 04:04

徹夜してしまったので3時間ほど寝てから作業を再開したら今度は普通にテキストに出力できました。 //正解の曲名1を代入、テキストに出力 SeikaiKyoku01.text = questionList[index].ans[09]; 寝る前と寝た後、コードはどこも変わってないはずなんですが・・・不思議ですけど 徹夜してて集中力が無くて単純な何かを見落としていたんだと思います。 残るはListをランダムで並び替える事です。 ランダムで並び替えてListの上から10回分だけを使う、とようにすれば 全体からランダムで10問出題するような動きになると思います。 ランダムに並び変えるにも色んな方法(OrderByを使う方法がすぐ出てきました) が有るようなのでやってみてわからなければ別で質問するかもです。
Tora_ou

2025/06/07 06:47

リストのランダム並び替えも以下の通りで出来ました。これでメインの機能は思っていた通りの動きになりました。並び替えた後、10問出題する場合は上から10個だけしか使われないのですがそこはまぁ良いと思います。 ありがとうございました。 // 問題Listに追加する questionList.Add(q); //リストのランダムシャッフル questionList = questionList.OrderBy(a => Guid.NewGuid()).ToList();
guest

0

こんにちは。

やり方についてはすでに具体的な回答がついているのでそちらを見てもらうのが良いとして、
質問のような状況での考え方について述べます。

まず、「同じようだが細部が異なるものが複数ある」というのはプログラミングの基本パターンですが、そういうときはまず「同じである部分」と「異なる部分」を抽出して、それぞれ分けて考えます。
この回答内では、同じである部分を「テンプレート」、異なる部分を「パラメータ」と呼ぶことにします。
今回の場合はクイズの画面、回答ボタンの仕様やその振る舞いがテンプレートで、問題のデータファイル名や回答文、正解の番号などのデータがパラメータになります。
そして、パラメータを複数個作ったら、それをテンプレートに埋め込むことで、パラメータの数だけ欲しい部品を手に入れることができるわけです。

簡単に例えると、
質問時点でやろうとしていることは、200個あるデータを Excel に打ち込む必要があったとき、Excel ファイルを200個作ろうとしているようなものです。
普通だったら、1つの Excel ファイルに200行打ち込むと思います。プログラミングでも同じです。

投稿2025/06/06 03:05

tamoto

総合スコア4331

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Tora_ou

2025/06/06 15:25

実は過去に20問ぐらいまでのクイズならそのごり押し、力業を使った方法で作っていました (問題数と同じ数だけシーンをそれぞれ作る) 今回作ろうとしているものは問題数がとても多くてそんなごり押し、力業な作り方では立ちいかなくなり質問するに至りました。 コメントありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.30%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問