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

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

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

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

Unity

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

Q&A

2回答

2038閲覧

[Unity]GetComponentが上手くいきません

hage0280

総合スコア19

C#

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

Unity

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

0グッド

0クリップ

投稿2019/03/10 14:03

初投稿で何か不足があったら申し訳ございません。
Unityチュートリアルでローグライクゲームを作ろうとしています。(参考https://unity3d.com/jp/learn/tutorials/projects/2d-roguelike-tutorial/writing-game-manager?playlist=17150)

GameManagerオブジェクトにBoardManagerスクリプトとGameManagerスクリプトをアタッチして、GameManagerスクリプトからBoardManagerスクリプトの中にあるSetupScene()というメソッドを取り出そうとしているのですが、Unity側から参照できないと言われてしまいます。スクリプト自体はコピペでも試しているので間違いないと思います。

このチュートリアルを日本語で解説してくださっているサイトに載っていた同じ過程のInspectorの画像が
イメージ説明こうなっているのに対して自分のは
イメージ説明こうなっています

たぶんGetComponentする前にGameManagerスクリプトでpublic BoardManager boardScript;と記述しているのでこれが自分の場合変数扱いになっているのでは? と考えています。

すいません、ご教授願います。三日も次に進めない状況です。

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

NullReferenceException: Object reference not set to an instance of an object GameManager.InitGame () (at Assets/Scripts/GameManager.cs:19) GameManager.Awake () (at Assets/Scripts/GameManager.cs:14)

該当のソースコード

C#

1【BoardManagerスクリプト】 2using UnityEngine; 3using System; 4//Listを使うため 5using System.Collections.Generic; 6//Randomを使うため 7using Random = UnityEngine.Random; 8 9public class BoardManager : MonoBehaviour { 10 //カウント用のクラスを設定 11 [Serializable] 12 public class Count { 13 public int minimum; 14 public int maximum; 15 16 public Count (int min, int max) { 17 minimum = min; 18 maximum = max; 19 } 20 } 21 22 //8*8のゲームボードを作るので縦の段を8、横の列を8 23 public int columns = 8; 24 public int rows = 8; 25 //壁は5〜9の間で出現 26 public Count wallCount = new Count (5,9); 27 //アイテムは1〜5の間で出現 28 public Count foodCount = new Count (1,5); 29 //Exitは単体 30 public GameObject exit; 31 //床・内壁・アイテム・敵キャラ・外壁は複数あるため配列 32 public GameObject[] floorTiles; 33 public GameObject[] wallTiles; 34 public GameObject[] foodTiles; 35 public GameObject[] enemyTiles; 36 public GameObject[] outerWallTiles; 37 //オブジェクトの位置情報を保存する変数 38 private Transform boardHolder; 39 //オブジェクトを配置できる範囲を表すリスト 40 //Listは可変型の配列 41 private List <Vector3> gridPositions = new List<Vector3>(); 42 43 //敵キャラ・アイテム・内壁を配置できる範囲を決定 44 void InitialiseList () 45 { 46 //gridPositionをクリア 47 gridPositions.Clear (); 48 //gridPositionにオブジェクト配置可能範囲を指定 49 //x = 1〜6をループ 50 for (int x = 1; x < columns - 1; x++) { 51 //y = 1〜6をループ 52 for (int y = 1; y < rows - 1; y++) { 53 //6*6の範囲をgridPositionsに指定 54 gridPositions.Add(new Vector3(x, y, 0f)); 55 } 56 } 57 } 58 //外壁、床を配置 59 void BoardSetup () 60 { 61 //Boardというオブジェクトを作成し、transform情報をboardHolderに保存 62 boardHolder = new GameObject ("Board").transform; 63 //x = -1〜8をループ 64 for (int x = -1; x < columns + 1; x++) { 65 //y = -1〜8をループ 66 for (int y = -1; y < rows + 1; y++) { 67 //床をランダムで選択 68 GameObject toInstantiate = floorTiles [Random.Range (0, floorTiles.Length)]; 69 //左端or右端or最低部or最上部の時=外壁を作る時 70 if (x == -1 || x == columns || y == -1 || y == rows) { 71 //floorTileの時と同じように外壁をランダムで選択し、上書きする 72 toInstantiate = outerWallTiles [Random.Range (0, outerWallTiles.Length)]; 73 } 74 //床or外壁を生成し、instance変数に格納 75 GameObject instance = Instantiate(toInstantiate, new Vector3(x, y, 0f), 76 Quaternion.identity) as GameObject; 77 //生成したinstanceをBoardオブジェクトの子オブジェクトとする 78 instance.transform.SetParent(boardHolder); 79 } 80 } 81 } 82 83 Vector3 RandomPosition () { 84 //0〜36からランダムで1つ決定し、位置情報を確定 85 int randomIndex = Random.Range(0, gridPositions.Count); 86 Vector3 randomPosition = gridPositions[randomIndex]; 87 //ランダムで決定した数値は削除 88 gridPositions.RemoveAt(randomIndex); 89 //確定した位置情報を返す 90 return randomPosition; 91 } 92 93 void LayoutObjectAtRandom (GameObject[] tileArray, int minimum, int maximum) 94 { 95 //最低値〜最大値+1のランダム回数分だけループ 96 int objectCount = Random.Range (minimum, maximum + 1); 97 for (int i = 0; i < objectCount; i++) { 98 //gridPositionから位置情報を1つ取得 99 Vector3 randomPosition = RandomPosition(); 100 //引数tileArrayからランダムで1つ選択 101 GameObject tileChoise = tileArray[Random.Range(0, tileArray.Length)]; 102 //ランダムで決定した種類・位置でオブジェクトを生成 103 Instantiate (tileChoise, randomPosition, Quaternion.identity); 104 } 105 } 106 //オブジェクトを配置していくメソッド 107 //このクラス内唯一のpublicメソッド 床を生成するタイミングでGameManagerから呼ばれる 108 public void SetupScene (int level) 109 { 110 //床と外壁を配置し、 111 BoardSetup(); 112 //敵キャラ・内壁・アイテムを配置できる位置を決定し、 113 InitialiseList(); 114 //内壁・アイテム・敵キャラをランダムで配置し、 115 LayoutObjectAtRandom(wallTiles, wallCount.minimum, wallCount.maximum); 116 LayoutObjectAtRandom(foodTiles, foodCount.minimum, foodCount.maximum); 117 //Mathf.Log : 対数で計算。level=2なら4、level=3なら8 118 int enemyCount = (int)Mathf.Log(level, 2f); 119 LayoutObjectAtRandom(enemyTiles, enemyCount, enemyCount); 120 //Exitを7, 7の位置に配置する。 121 Instantiate(exit, new Vector3(columns - 1, rows - 1, 0F), Quaternion.identity); 122 } 123} 124 125【GameManagerスクリプト】 126using UnityEngine; 127using System.Collections; 128 129public class GameManager : MonoBehaviour { 130 131 public BoardManager boardScript; 132 //テストとしてレベルを3にしておく 133 private int level = 3; 134 135 //Awake : Sceneを移動した時即座に実行される 136 void Awake () { 137 //BoardManager取得 138 boardScript = GetComponent<BoardManager>(); 139 InitGame(); 140 } 141 142 void InitGame () { 143 //BoardManagerのSetupSceneメソッドを実行 144 boardScript.SetupScene(level); 145 } 146}

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

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

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

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

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

guest

回答2

0

scriptにNoneと表示されているのであれば、ヒエラルキーからオブジェクトをそこにドラッグすると良いでしょう。ヒエラルキーのゲームオブジェクトをNone表示されているスクリプト欄にドラッグする

投稿2019/03/11 03:38

sayachang_bot

総合スコア228

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

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

0

  1. GameManagerおよびBoardManagerのスクリプトを作成
  2. HierarchyにGameManagerゲームオブジェクトを作り、上記 2 スクリプトをアタッチ。
  3. 実行してデバッグログが流れていることを確認

参照が通るか試すためだけにざっくり簡略化したスクリプトで試してみましたが特に問題なく
BoardManagerのSetupSceneが呼ばれ、デバッグログが表示されました。

boardScript は BoardManager 型で宣言された変数です。publicがついているのでインスペクター上にも表示されています。
そして、GameManagerは、GameManager.csとBoardManager.csの2つがアタッチされているので
GetComponent<BoardManager>() にて自身にアタッチされた BoardManager コンポーネントを参照してさっき宣言しておいたboardScriptに参照先を入れています。

極端な話、boardScriptを使わずに GetComponent<BoardManger>().SetupScene(level);とか書いてもメソッドは呼べます。

とりあえず、本来の処理は一旦おいといて各所にデバッグログを入れて参照がnullになってないか。nullになってるとしたらどこなのかを探してみてはいかがでしょうか。

【GameManager】

C#

1using UnityEngine; 2using System.Collections; 3 4public class GameManager : MonoBehaviour { 5 6 public BoardManager boardScript; 7 //テストとしてレベルを3にしておく 8 private int level = 3; 9 10 //Awake : Sceneを移動した時即座に実行される 11 void Awake() { 12 //BoardManager取得 13 boardScript = GetComponent<BoardManager>(); 14 15 Debug.Log("GetComponent<BoardManager> : " + boardScript); // 参照が取れているか? 16 17 InitGame(); 18 } 19 20 void InitGame() { 21 //BoardManagerのSetupSceneメソッドを実行 22 boardScript.SetupScene(level); 23 24 } 25}

【BoardManager】(簡略化)

C#

1using UnityEngine; 2using System; 3//Listを使うため 4using System.Collections.Generic; 5//Randomを使うため 6using Random = UnityEngine.Random; 7 8public class BoardManager : MonoBehaviour { 9 //カウント用のクラスを設定 10 [Serializable] 11 public class Count { 12 public int minimum; 13 public int maximum; 14 15 public Count(int min, int max) { 16 minimum = min; 17 maximum = max; 18 } 19 } 20 21 //8*8のゲームボードを作るので縦の段を8、横の列を8 22 public int columns = 8; 23 public int rows = 8; 24 //壁は5〜9の間で出現 25 public Count wallCount = new Count(5, 9); 26 //アイテムは1〜5の間で出現 27 public Count foodCount = new Count(1, 5); 28 //Exitは単体 29 public GameObject exit; 30 //床・内壁・アイテム・敵キャラ・外壁は複数あるため配列 31 public GameObject[] floorTiles; 32 public GameObject[] wallTiles; 33 public GameObject[] foodTiles; 34 public GameObject[] enemyTiles; 35 public GameObject[] outerWallTiles; 36 //オブジェクトの位置情報を保存する変数 37 private Transform boardHolder; 38 //オブジェクトを配置できる範囲を表すリスト 39 //Listは可変型の配列 40 private List<Vector3> gridPositions = new List<Vector3>(); 41 42 //敵キャラ・アイテム・内壁を配置できる範囲を決定 43 void InitialiseList() { 44 //gridPositionをクリア 45 gridPositions.Clear(); 46 //gridPositionにオブジェクト配置可能範囲を指定 47 //x = 1〜6をループ 48 for (int x = 1; x < columns - 1; x++) { 49 //y = 1〜6をループ 50 for (int y = 1; y < rows - 1; y++) { 51 //6*6の範囲をgridPositionsに指定 52 gridPositions.Add(new Vector3(x, y, 0f)); 53 } 54 } 55 } 56 //外壁、床を配置 57 void BoardSetup() { 58 //Boardというオブジェクトを作成し、transform情報をboardHolderに保存 59 boardHolder = new GameObject("Board").transform; 60 //x = -1〜8をループ 61 for (int x = -1; x < columns + 1; x++) { 62 //y = -1〜8をループ 63 for (int y = -1; y < rows + 1; y++) { 64 //床をランダムで選択 65 GameObject toInstantiate = floorTiles[Random.Range(0, floorTiles.Length)]; 66 //左端or右端or最低部or最上部の時=外壁を作る時 67 if (x == -1 || x == columns || y == -1 || y == rows) { 68 //floorTileの時と同じように外壁をランダムで選択し、上書きする 69 toInstantiate = outerWallTiles[Random.Range(0, outerWallTiles.Length)]; 70 } 71 //床or外壁を生成し、instance変数に格納 72 GameObject instance = Instantiate(toInstantiate, new Vector3(x, y, 0f), 73 Quaternion.identity) as GameObject; 74 //生成したinstanceをBoardオブジェクトの子オブジェクトとする 75 instance.transform.SetParent(boardHolder); 76 } 77 } 78 } 79 80 Vector3 RandomPosition() { 81 //0〜36からランダムで1つ決定し、位置情報を確定 82 int randomIndex = Random.Range(0, gridPositions.Count); 83 Vector3 randomPosition = gridPositions[randomIndex]; 84 //ランダムで決定した数値は削除 85 gridPositions.RemoveAt(randomIndex); 86 //確定した位置情報を返す 87 return randomPosition; 88 } 89 90 void LayoutObjectAtRandom(GameObject[] tileArray, int minimum, int maximum) { 91 //最低値〜最大値+1のランダム回数分だけループ 92 int objectCount = Random.Range(minimum, maximum + 1); 93 for (int i = 0; i < objectCount; i++) { 94 //gridPositionから位置情報を1つ取得 95 Vector3 randomPosition = RandomPosition(); 96 //引数tileArrayからランダムで1つ選択 97 GameObject tileChoise = tileArray[Random.Range(0, tileArray.Length)]; 98 //ランダムで決定した種類・位置でオブジェクトを生成 99 Instantiate(tileChoise, randomPosition, Quaternion.identity); 100 } 101 } 102 //オブジェクトを配置していくメソッド 103 //このクラス内唯一のpublicメソッド 床を生成するタイミングでGameManagerから呼ばれる 104 public void SetupScene(int level) { 105 106 // とりあえずデバッグログだけ出してみる 107 Debug.Log("Call : SetupScene"); 108 } 109}

投稿2019/03/11 01:22

hogefugapiyo

総合スコア3302

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問