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

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

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

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

Unity

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

Q&A

解決済

3回答

1271閲覧

Unityにて"NullReferenceException" Update()では参照が確認できたのだが...

Sado

総合スコア89

C#

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

Unity

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

0グッド

1クリップ

投稿2018/11/01 22:22

編集2018/11/04 19:58

【まとめ】【解決後の追記】

解決まで非常に遠回りをしてしまいましたので、簡潔にまとめさせていただきます。
今回NullReferenceExceptionが出たのですが、エラーとして示された行に存在するメソッド・クラス型変数(?)に焦点をあててしまったことから見逃してしまった凡ミスです。
空参照エラーの行に存在するスクリプトやメソッドとは少し別の箇所で定義したものが原因でした。

というのも、あるゲームオブジェクトにアタッチしたスクリプトから別のゲームオブジェクトのスクリプトのメソッドを呼び出していたのですが、この時に別のオブジェクトの参照を得るべき箇所で無理やりスクリプトそのものをねじ込もうとしていました。

スクリプト冒頭で[SerializeField] private GameObject gmObj;と書きStart()内でスクリプトコンポーネントの参照を得るべきところで、[SerialzeField] private Script-Name scObj;と書いてしまっていました。インスペクター側の項目もわけのわからないものを参照していました。

初心者あるあるとでも思わないとやってられない凡ミスです。基礎といいますか、扱うデータ型を疎かにしすぎです。Java勉強中とは口が裂けても言えません。

前提・実現したいこと

特別なアイテム、通常のアイテム(それぞれGameObject)を確立で生成するプログラムを作成しています。
今回、特別なアイテムを参照するtargetItem.GetGameObject()で空参照エラーが頻発しました。

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

特定の箇所でのみInstantiate()を実行しようとすると"NullReferenceException: Object reference not set to an instance of an object"が表示されます。

NullReferenceException: Object reference not set to an instance of an object ItemManager.makeItems (Int32 n, Vector3 vec3) (at Assets/Scripts/ItemManager.cs:71) Box.Update () (at Assets/Scripts/Box.cs:55)

該当のソースコード

C#

1//Assets/Scripts/ItemManager.cs 2public void makeItems(int n,Vector3 vec3) 3 { 4 //Debug.Log("メソッド内デバッグ : " + targetItem.GetGameObject().name); // コメント外すとエラー 5 if (canMakeTargetItem()) 6 { 7 if (true)//(Random.Range(0, 100) < targetIncidence) // 【Line68】 8 { 9 Debug.Log("チェックポインツB"); 10 Instantiate(targetItem.GetGameObject(), vec3, Quaternion.identity); //【Line71】 11 return; 12 // 特別アイテムを生成したら, 即時終了. 13 } 14 } 15 16 if (!canMakeItems()) return; 17 // 通常アイテム数が上限なら, 終了. 18 19 // 通常アイテムをn個生成【この処理は上手く働く】 20 if (n < 1) n = 1; 21 for (int i = 0; i < n; i++) 22 { 23 int shift = (i * 20) - (n*10) ; 24 Instantiate(randomItem().GetGameObject(), vec3 + new Vector3(shift,0,0), Quaternion.identity); 25 } 26 }

C#

1//Assets/Scripts/Box.cs 2void Update () { 3 4 Objects = GameObject.FindGameObjectsWithTag("StageObject"); 5 //Debug.Log("オブジェクトの数は" + Objects.Length); 6 7 int StageSt = Stage.StageState; 8 //Debug.Log(StageSt); 9 10 if(StageSt == 1){ 11 BoxHP = 0; 12 } 13 14 if (BoxHP <= 0) 15 { 16 //Debug.Log("破壊"); 17 adse.Play(); 18 itemMng.makeItems(itemMakeNum, transform.position); //【Line55】 19 Destroy(gameObject); 20 } 21 22 }

試したこと

「NullReferenceException」はよくあるnull参照エラーですから、ItemManagerクラスのtargetItem.GetGameObject()が何も示せていない事を疑いました。
同クラスのUpdate()にDebug.Log("デバッグ : " + targetItem.GetGameObject().name);を記入したところ、オブジェクトの名前が返ってきました。しかし、同クラスのmakeItems()に上記のデバッグ文を挿入したところ、表題のようなエラーが発生しました。
makeItems()メソッド内で空参照エラーが発生する理由が思い当たりません。

デバッグ用に比較文を(true)にしてある【Line68】を本来の式に戻し、「確立で特別なアイテムを生成する」という処理にした上で問題のブロックが実行されなかった場合……「通常アイテムをn個生成」とコメントされた箇所の処理、Instantiate()は正常に動作しました。

また、Box.cs内で宝箱破壊時に効果音を再生adse.Play();しているのですが、今回のエラー発生時、Destroy(gameObject);されずに残っているのかSEが無限再生されるように暴走します。
特別なアイテムを生成しない、通常アイテムを生成する時はSEやDestroyに異常は感じられませんでした。

デバッグ状況1(追記)

targetItem.GetGameObject()の補足をしますと、targetItemはItem型の変数でアイテムの各種情報(名前や属性,説明,GameObjectなど)をprivate typeで格納しています。この中にGameObjectがあり、GetGameObject()で取得できるようになっています。
ここで、Item型のGetGameObjectは他の場所でも頻繁に利用していて問題が起きていないために見落としていましたが、問題の箇所でtargetItemのみで確認してみたところヌルリファレンスエラーは発生しませんでした。
問題のメソッド内で<Item>.GetGameObject()を須いたときのみエラーが発生するらしいことまでが分かりました。

しかし、「targetItemの中身はどの時点でも空ではない」「GetGameObject()はprivateな変数を返すだけのメソッド」「Item型の実体の方も問題のメソッド以外では参照が確認できる」「Item型の実体の方でGameObjectの参照を格納する変数に変更を加える(代入する)処理は一切書き込んでいない」
となると、余計に分かりません。
何かちょっとしたヒントでもいいので、突破口に成るような何かが見つかるといいのですが......

デバッグ状況2(追記)

Item型のインスタンスを、ItemManagerクラスのtargetItemに参照を格納し、壊れるとアイテムを出現させるBoxクラスからItemManagerクラスのmakeItems()を実行するとエラーが発生することがわかりました。
ItemクラスのGetGameObject()だけでなく、Itemクラス内の全メソッドにおいて同様のエラーが発生します。
その条件は恐らくですが、「BoxクラスからItemManagerクラスのメソッドを呼び出す。そのメソッドがまたItemクラスのメソッドを呼び出す」といった構造をしていることだと思いましたが、それをどのように解決させるか検討もつきません。
「BoxクラスからItemManagerクラスのメソッドを呼び出す。そのメソッドがItemクラスのインスタンスの参照そのものを表示する」という先よりも一段階少ない工程でデバッグしてみると、ヌルにはなりませんでした。

HSP言語のループのように、C#のメソッドを呼び出す深さ(ネスト)が3つくらいと言った、Unity C#特有の制限があるのでしょうか。

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

Unity2018 2.0f2、VS2017、Windows 10 home 64bit。

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

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

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

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

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

guest

回答3

0

自己解決

とてもしょうもない話でした。
アイテム管理ゲームオブジェクトが持つItemManager.csの参照を得るための手順を誤っていただけで、作ったクラスやメソッド等に特段問題は見つかりませんでした。

強いて言えば、Box.cs内でAudioSourceを鳴らす処理がDestroyすることで無駄になっており、PlayClipToPointメソッドに変更する程度の修正点があるのみでした。(今回のエラーと関係なし)

対象のGameObjectの参照を取るべくインスペクタでD&Dし、Start()でGetCompornent()する。
たったこれだけの工程を間違えるのはとても情けない。
これに多くの時間を割いた自分が情けない。
視野が狭すぎます......イベント直前で徹夜気味に弄るものじゃないですね。

投稿2018/11/02 23:55

Sado

総合スコア89

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

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

0

VisualStudioを使ってるなら、任意の行にブレークポイントを設定し、そこで実行を止めて変数の値を確認できます。
また、そこから1行づつ実行したりできますんで、それでデバッグしていきましょう

投稿2018/11/02 01:48

y_waiwai

総合スコア87719

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

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

Sado

2018/11/02 16:07

回答ありがとうございます。返信遅れてしまい申し訳ありません。 Unityでの実行ですので、VSのブレークポイントを利用したデバッグが有効なのか分かりませんでした。(どのように適用するのか分からなかった) 引き続き、Debug.Log()を利用して`targetItem.GetGameObject()`とその周辺を調査していきます。
guest

0

targetItem.GetGameObject()がnullを返すことがあるようです。
そこのソースをデバッグするといいです。

投稿2018/11/02 01:07

kaba

総合スコア314

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

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

Sado

2018/11/02 16:14

回答ありがとうございます。返信遅れてしまい申し訳ありません。 `targetItem.GetGameObject()`が直接的なエラーの原因なのは理解していましたので、怪しい箇所でDebug.Log()を用いて中身を覗いていたのですが、どうやら不十分でした。 中身があるときとないときがあるので、現在、意図しない箇所で余計にtargetItemに変更を加えている箇所がありそうだと当たりを付けてデバッグしている状況です。 targetItemはItem型なのですが、質問文の「該当のソースコード」にも載っている`randomItem().GetGameObject()`はnullを返さないことから、randomItem()の返り値でもある「Item型」及びItem型の「GetGameObject()」に問題は無いと判断しています。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問