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

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

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

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

Q&A

解決済

2回答

1936閲覧

IEnumerableのforeach文でなぜNullReferenceExceptionエラーが表示されるのか

dyer

総合スコア1

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

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

0グッド

0クリップ

投稿2022/03/12 15:18

編集2022/03/13 01:14

プログラミング初心者です。unityとC#を使ってブラックジャックゲームを作るサイトを参考に開発しているのですが、サイトと全く同じコードでもなぜかDeck.CSのforeach文でNull?エラーが出てしまいます。

foreach (int i in cards)//cardsの中の要素それぞれについて { yield return i; //要素を戻り値に返します }

unityのバージョンは「2020.3.23f1」です。必要な情報が載せられているかわかりませんが、どなたかなぜエラーがでているのか教えてくださるとありがたいです。

error

1NullReferenceException: Object reference not set to an instance of an object 2Deck+<GetCards>d__1.MoveNext () (at Assets/Scripts/Deck.cs:14) 3DeckView.ShowCards () (at Assets/Scripts/DeckView.cs:24) 4DeckView.Start () (at Assets/Scripts/DeckView.cs:17)

Deck.cs

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class Deck : MonoBehaviour 6{ 7 8 List<int> cards; 9 10 11 12 public IEnumerable<int> GetCards() //戻り値に列挙可能なリストを持つメソッド 13 { 14 foreach (int i in cards)//cardsの中の要素それぞれについて 15 { 16 yield return i; 17 //要素を戻り値に返します 18 } 19 } 20 21 22 23 public void Shuffle() // デッキをシャッフルする 24 { 25 26 if (cards == null) 27 { 28 cards = new List<int>(); 29 } 30 else 31 { 32 cards.Clear(); 33 } 34 35 for(int i = 0; i < 75; i++) 36 { 37 cards.Add(i); 38 } 39 40 41 42 // 整数 n の初期値はデッキの枚数 43 int n = cards.Count; 44 45 // nが1より小さくなるまで繰り返す 46 while (n > 1) 47 { 48 n--; 49 50 // kは 0 ~ n+1 の間のランダムな値 51 int k = UnityEngine.Random.Range(0, n + 1); 52 53 // k番目のカードをtempに代入 54 int temp = cards[k]; 55 cards[k] = cards[n]; 56 cards[n] = temp; 57 } 58 59 } 60 61 // Start is called before the first frame update 62 void Start() 63 { 64 Shuffle(); 65 } 66 67}

DeckView.cs

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5[RequireComponent(typeof(Deck))] 6public class DeckView : MonoBehaviour 7{ 8 Deck deck; 9 10 public Vector3 start; 11 public float cardOffset; 12 public GameObject cardPrefab; 13 14 void Start() 15 { 16 deck = GetComponent<Deck>();//Deck.csの取得 17 ShowCards();//下記メソッドの実行 18 } 19 20 void ShowCards()//メソッド本体 21 { 22 int cardCount = 0;//内部で使う値cardCountの宣言 23 24 foreach (int i in deck.GetCards()) 25 { 26 float co = cardOffset * cardCount; //オフセット幅の計算 27 28 GameObject cardCopy = (GameObject)Instantiate(cardPrefab); 29 //カードプレファブのコピー 30 Vector3 temp = start + new Vector3(co, 0f); 31 //tempというオフセットした位置の計算 32 cardCopy.transform.position = temp; 33 //現在の位置にtempを代入 34 35 CardModel cardModel = cardCopy.GetComponent<CardModel>(); 36 // //コピーしたカードプレファブのCardModelクラスを取得 37 cardModel.cardIndex = i; 38 // //インデックスにiを代入 39 cardModel.ToggleFace(true); 40 // //表面をレンダー(カードゲームを作りたい第2回目で作成したスクリプトを使用) 41 cardCount++;//cardCountをインクリメント 42 } 43 } 44 45}

補足:Cardsリストのシャッフル処理はunity上のdebug表示でインスペクターをみたところうまくいっており、問題はforeachの時点でcardsの中身がNullになっていることだとわかりました。しかし、なぜforeachの時点でNullなのか、調べても自分では理解できませんでした。

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2022/03/12 23:05

> Deck.CSの14行目 そういう言い方は NG です。行番号が振ってあるわけではないので。
dyer

2022/03/13 01:08

確かに仰る通りです。 今後該当箇所かわかるように質問します。 質問の仕方の訂正、ありがとうございます。
退会済みユーザー

退会済みユーザー

2022/03/13 02:45

質問文は編集できますので今やりましょう。Teratail は「質問と回答を通してお互いに知識や情報を交換・共有する場所」ということですので、後から検索などでここにたどり着いた人などにも分かりやすく書くようお願いします。
guest

回答2

0

ベストアンサー

Shuffle してはじめて cards が設定されるのに、その前に GetCards メソッドを呼び出しているからでは?

投稿2022/03/12 23:11

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

dyer

2022/03/13 01:00

ご教授ありがとうございます。 その可能性が高そうですが、このコードだとShuffle()はGetCards()より前にDeck.cs上で行われることになると思ったのですが、この認識が間違っているのでしょうか? void Start() { deck = GetComponent<Deck>();//Deck.csの取得 ShowCards();//下記メソッドの実行 }
退会済みユーザー

退会済みユーザー

2022/03/13 02:36

デバッガを使ってどういう順で実行されているか調べてはいかが?
dyer

2022/03/13 03:12

デバッガなるものを調べて使ってみます。 ありがとうございました
退会済みユーザー

退会済みユーザー

2022/03/13 03:15 編集

Deck クラスの Start ⇒ Shuffle ⇒ GetCards メソッドの順で実行されるはずだから GetCards が実行される時点では cards は null にはならないはずと思っているということですか? そうであれば、思っている通りになっているかは各メソッドの中の最初の一行目にブレークポイントを設定して Visual Studio からデバッグ実行すれば分かります。まずそれをやりましょう。
dyer

2022/03/13 11:22

visual studioをインストールしてデバッグのやり方検索通りにしてみると正しくできたのかわかりませんが、Deckview.csのStart処理から始まり「ShowCard()→ DeckView.csのforeach文→Deck.csのforeach文」とforeachの順番が自分の想像と真逆になっていました。
dyer

2022/03/13 14:05

最終的にスクリプトのIDを変更してDeck.csがDeckView.csより先に動くように設定したらうまく行きました! デバッグという手法を教えていただきありがとうございました!
guest

0

修正前: List<int> cards;
修正後: List<int> cards = new List<int>();

としたらいいんじゃないでしょうか。

投稿2022/03/12 16:45

bboydaisuke

総合スコア5275

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

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

dyer

2022/03/13 00:57

ご教授ありがとうございます。 確かにエラーはうまく消えてくれましたが、Debug.Logをforeachの手前に入れて確認したところ、GetCards()がスルーされており、意図した挙動にはなりませんでした。 cardsに値が設定されていなかったのがエラーの原因だとわかりましたが、なぜShuffle()内で設定されているのにエラーになるのでしょうか。 if (cards == null) { cards = new List<int>(); } else { cards.Clear(); } for(int i = 0; i < 75; i++) { cards.Add(i); }
退会済みユーザー

退会済みユーザー

2022/03/13 02:38 編集

デバッガを使ってどういう順で実行されているか調べてはいかが? ←すみません、書く場所を間違えました。でも、デバッガを使って調べようという話は間違ってないので消さずに置いときます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問