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

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

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

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

Unity

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

Q&A

解決済

1回答

1606閲覧

NullReferenceExceptionが出るのですが、なぜNullになるのかがわかりません。

退会済みユーザー

退会済みユーザー

総合スコア0

C#

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

Unity

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

0グッド

0クリップ

投稿2021/06/04 07:32

編集2021/06/04 07:48

NullReferenceExceptionが出るのですが、なぜNullになるのかがわかりません。

Switch3というタグに触れたらブロックが出現するということを目的としています。
Debug.Logで、プレイヤーがタグに触れていることは確認しています。
しかし別スクリプトの関数を呼び出そうとするとNullReferenceExceptionが出ます。
別クラス型の変数の中身を見ても、たしかにNullでした。
しかし呼び出される元を見ても、なぜNullになるのかがわかりません。
以前、同じようなことをやったときは上手くいったので今回も同じようにやっているのですが
どこに違いがあるのかがわからなくて困っています。

今回、上手くいかなかった呼び出し元のスクリプトが以下です。

using

1using System.Collections.Generic; 2using UnityEngine; 3 4public class Trap3 : MonoBehaviour 5{ 6 7 public GameObject dblock; 8 9 10 private void Start() 11 { 12 } 13 14 public void Appearblock() 15 { 16 17 dblock.SetActive(true); 18 Debug.Log("ブロック出現"); 19 20 } 21 22 23} 24 25コード

呼び出し側のスクリプトが以下です。

using UnityEngine; public class PlayerManager : MonoBehaviour { //public public float xspeed; public float jumpPower; public GroundCheck ground; public GameManager gameManager; //SE [SerializeField] AudioClip jumpSE; public Traps trap1; public Trap2 trap2; public Trap3 trap3; //private private bool isGround = false; float speed; bool isDead = false; AudioSource audioSource; public enum DIRECTION_TYPE { STOP, RIGHT, LEFT } DIRECTION_TYPE direction = DIRECTION_TYPE.STOP; Rigidbody2D rigidbody2D; Rigidbody2D trapSpike1; Animator animator; private void Start() { rigidbody2D = GetComponent<Rigidbody2D>(); trapSpike1 = GetComponent<Rigidbody2D>(); animator = GetComponent<Animator>(); audioSource = GetComponent<AudioSource>(); } void Update() { if (isDead) { return; } //接地判定を得る isGround = ground.IsGround(); float x = Input.GetAxis("Horizontal"); //speedというパラメータにxを代入 animator.SetFloat("speed", Mathf.Abs(x)); if (x == 0) { //止まっている direction = DIRECTION_TYPE.STOP; } else if (x > 0) { //右に動く direction = DIRECTION_TYPE.RIGHT; } else if (x < 0) { //左に動く direction = DIRECTION_TYPE.LEFT; } //スペース押したらジャンプ if (isGround) { if (Input.GetKeyDown("space")) { Jump(); } else { animator.SetBool("isJumping", false); } } switch (direction) { case DIRECTION_TYPE.STOP: speed = 0; break; case DIRECTION_TYPE.RIGHT: speed = xspeed; transform.localScale = new Vector3(1, 1, 1); break; case DIRECTION_TYPE.LEFT: speed = -xspeed; transform.localScale = new Vector3(-1, 1, 1); break; } rigidbody2D.velocity = new Vector2(speed, rigidbody2D.velocity.y); } void Jump() { //上に力を加える rigidbody2D.AddForce(Vector2.up * jumpPower); animator.SetBool("isJumping", true); audioSource.PlayOneShot(jumpSE); Debug.Log("ジャンプしました"); } private void OnTriggerEnter2D(Collider2D collision) { if (isDead) { return; } if (collision.gameObject.tag == "Trap") { Debug.Log("GameOver"); gameManager.GameOver(); PlayerDeath(); } if (collision.gameObject.tag == "Finish") { Debug.Log("GameClear"); gameManager.GameClear(); } //トラップSwitchのタグ if (collision.gameObject.tag == "Switch1") { Debug.Log("罠1起動"); trap1.Trap1Activate(); } if (collision.gameObject.tag == "Switch2") { trap2.Trap2Activate(); Debug.Log(trap2); } if (collision.gameObject.tag == "Switch3") { Debug.Log("罠3起動"); Debug.Log(trap3);//<========================Nullになります trap3.Appearblock(); } void PlayerDeath() { BoxCollider2D boxCollider2D = GetComponent<BoxCollider2D>(); Destroy(boxCollider2D); rigidbody2D.velocity = new Vector2(0, 0); rigidbody2D.AddForce(Vector2.up * 400); animator.Play("PlayerDeathAnimation"); gameManager.GameOver(); isDead = true; } } } コード

前回上手くいったときの呼び出し元のスクリプトが以下です。

using

1using System.Collections.Generic; 2using UnityEngine; 3 4public class Trap3 : MonoBehaviour 5 6 7{ 8 9 public GameObject Bricks_16_2; 10 11 12 13 private void Start() 14 { 15 16 } 17 public void Trap3Activate() 18 { 19 20 Debug.Log("罠3発動"); 21 Bricks_16_2.SetActive(true); 22 23 24 } 25 26 27} 28コード

呼び出し側のスクリプトが以下です。(最終的には出現までの時間をちょっと送らせたいのでInvokeを使ってます。)

using

1using System.Collections.Generic; 2using UnityEngine; 3 4public class PlayerManager : MonoBehaviour 5{ 6 7 //public変数 8 [Header("横方向速度")] public float xspeed = 8; 9 [Header("ジャンプ力")] public float jumpPower = 1000; 10 public GroundCheck ground;//GroundCheckを貼り付ける 11 public GameManager gameManager;//GameManagerを貼り付ける 12 public LayerMask blockLayer; 13 public Traps trap1; 14 public Trap2 trap2; 15 public Trap3 trap3; 16 17 18 19 //プライベート変数 20 private float speed; 21 private bool isGround = false; 22 Animator animator; 23 bool isDead = false; 24 25 public enum DIRECTION_TYPE 26 { 27 STOP, 28 RIGHT, 29 LEFT, 30 } 31 32 DIRECTION_TYPE direction = DIRECTION_TYPE.STOP; 33 34 Rigidbody2D rigidbody2D; 35 36 private void Start() 37 { 38 rigidbody2D = GetComponent<Rigidbody2D>(); 39 animator = GetComponent<Animator>(); 40 } 41 42 void Update() 43 { 44 //接地判定を得る 45 isGround = ground.IsGround(); 46 47 float horizontalKey = Input.GetAxis("Horizontal"); 48 49 if (horizontalKey == 0) 50 { 51 //止まっている 52 direction = DIRECTION_TYPE.STOP; 53 animator.SetBool("run", false); 54 55 } 56 else if (horizontalKey > 0) 57 { 58 //右向きに進む 59 direction = DIRECTION_TYPE.RIGHT; 60 animator.SetBool("run", true); 61 62 } 63 else if (horizontalKey < 0) 64 { 65 //左向きに進む 66 direction = DIRECTION_TYPE.LEFT; 67 animator.SetBool("run", true); 68 69 } 70 //スペースボタンでかつ接地していればジャンプ 71 if (Input.GetKeyDown("space") && isGround) 72 { 73 //ジャンプ関数 74 Jump(); 75 } 76 77 //2秒遅れてブロック出現 78 79 80 81 82 83 84 } 85 86 87 88 private void FixedUpdate() 89 { 90 if(isDead) 91 { 92 return; 93 } 94 switch (direction) 95 { 96 case DIRECTION_TYPE.STOP: 97 speed = 0; 98 break; 99 case DIRECTION_TYPE.RIGHT: 100 speed = xspeed; 101 transform.localScale = new Vector3(1, 1, 1); 102 break; 103 case DIRECTION_TYPE.LEFT: 104 speed = -xspeed; 105 transform.localScale = new Vector3(-1, 1, 1); 106 break; 107 108 } 109 rigidbody2D.velocity = new Vector2(speed,rigidbody2D.velocity.y); 110 } 111 112 void Jump() 113 { 114 //上に力を加える 115 rigidbody2D.AddForce(Vector2.up * jumpPower); 116 } 117 118 private void OnTriggerEnter2D(Collider2D collision) 119 { 120 if (isDead) 121 { 122 return; 123 } 124 125 if (collision.gameObject.tag == "Trap") 126 { 127 PlayerDie(); 128 129 130 } 131 132 if (collision.gameObject.tag == "Goal") 133 { 134 Debug.Log("ゴール"); 135 gameManager.GameClear(); 136 } 137 138 if (collision.gameObject.tag == "TrapSwitch1") 139 { 140 Debug.Log("罠ジャンプ"); 141 trap1.Trap1Activate(); 142 143 } 144 145 if (collision.gameObject.tag == "TrapSwitch2") 146 { 147 Debug.Log("罠2始動"); 148 trap2.Trap2Activate(); 149 150 } 151 if (collision.gameObject.tag == "TrapSwitch3") 152 { 153 154 Invoke("Trap3Invoke", 2.0f); 155 156 } 157 158 159 } 160 161 //Invoke発動のための関数 162 void Trap3Invoke() 163 { 164 trap3.Trap3Activate(); 165 Debug.Log(trap3); 166 } 167 168 private void PlayerDie() 169 { 170 isDead = true; 171 rigidbody2D.velocity = new Vector2(0, 0); 172 rigidbody2D.AddForce(Vector2.up * jumpPower); 173 animator.Play("PlayerDie"); 174 CapsuleCollider2D capsuleCollider2D = GetComponent<CapsuleCollider2D>(); 175 Destroy(capsuleCollider2D); 176 gameManager.GameOver(); 177 Debug.Log("死亡"); 178 } 179 180 181 182 183 184} 185 186コード

error文は以下になります。

NullReferenceException: Object reference not set to an instance of an object
PlayerManager.OnTriggerEnter2D (UnityEngine.Collider2D collision) (at Assets/Scripts/PlayerManager.cs:167)

オブジェクトのインスタンスにオブジェクトのリファレンスがセットされていないということですが
public GameObject dblock;はインスタンスにはならないのでしょうか。
(インスタンスとは、設計図に対する実体であると、教科書どおりの認識をしています。)
Trap3のスクリプトをアタッチしたオブジェクトのコンポーネントには、目的のブロックもアタッチしております。

どうすれば目的を果たせるか、うまくいったときとどこが違うのか、ご教示お願いします。

よろしくおねがいします。

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

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

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

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

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

YAmaGNZ

2021/06/04 09:01

dblockはどこであたいをセットしているのですか?
退会済みユーザー

退会済みユーザー

2021/06/04 09:16

unity側で、オブジェクトを直接アタッチしています。
YAmaGNZ

2021/06/04 10:33

PlayerManagerのtrap3もインスペクタ上から設定しているのですか?
退会済みユーザー

退会済みユーザー

2021/06/04 11:40

そこ、設定できてませんでした。 夕食を作りながら考えてて、「もしかして」と思ったらもしかしました。 ありがとうございます。
guest

回答1

0

ベストアンサー

PlayerManager側ですでにNullになっているってことは参照が取れてないんだと思います。
Nullのデバッグは、とにかく細かくDebug.Logを出して途切れている原因を探しましょう。

今回の場合なら最初から参照持ってるはずなので、Startとかで確認しちゃうと良いです
この段階でnullになってるなら参照できてないか、どこかで参照が外れてます。

cs

1 private void Start() 2 { 3 rigidbody2D = GetComponent<Rigidbody2D>(); 4 trapSpike1 = GetComponent<Rigidbody2D>(); 5 animator = GetComponent<Animator>(); 6 audioSource = GetComponent<AudioSource>(); 7 8 // デバッグ用 9 Debug.Log("trap1 " + trap1); 10 Debug.Log("trap2 " + trap2); 11 Debug.Log("trap3 " + trap3); 12 } 13

あとはたまにあるのが、PlayerManagerを2つアタッチしてて片方はインスペクター上が空欄になってるとかっていうパターンもあります。今回はなさそうですが、念の為。

投稿2021/06/04 08:04

hogefugapiyo

総合スコア3302

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

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

退会済みユーザー

退会済みユーザー

2021/06/04 08:36

ありがとうございます。 とりあえずパッと見たところではわからないということですね。 今デバッグをやってみましたけど Debug.Log("trap3 " + trap3);のところはtrap3 とだけ出ています。 trap3 +nullではないのですが、これはnullと同じだと見ていいですか?
退会済みユーザー

退会済みユーザー

2021/06/04 11:46

少し解決とは離れていますが、最初から参照持ってるはずであるときにStartとかで確認するといい、というのがすごく参考になりました。ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問