🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C#

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

Unity

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

Q&A

解決済

2回答

1515閲覧

プレイヤーの衝突でスコアを止めたい

nine_fish397

総合スコア8

C#

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

Unity

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

0グッド

0クリップ

投稿2020/11/22 14:44

編集2020/11/26 04:05

Unityで時間経過スコアアップするフラッピーバードのようなゲームを作っています。プレイヤーが衝突時にゲームオーバーになりスコア加算もストップさせたいのですが 
「NullReferenceException: Object reference not set to an instance of an object」というエラーがでてスコアがとまりません助言をいただきたいです。

コード (プレイヤーのscript。衝突時にゲームオーバーになりスコアを止めたい) public class PlayerControll : MonoBehaviour { //スプライト番号 const int SPR_FALL = 0; const int SPR_JUMP = 1; [SerializeField] float Jump=400;//ジャンプ力 public Sprite[] SPR_LIST;//アニメーション用スプライトの保持 public GameObject sc; Rigidbody2D _rigidbody;//物理挙動 SpriteRenderer _renderer;//スプライト描画 Score _sc;//ゲーム管理スクリプト // Start is called before the first frame update void Start() { _rigidbody = GetComponent<Rigidbody2D>();//物理挙動のコンポーネント獲得 _renderer = GetComponent<SpriteRenderer>();//スプライト描画コンポーネント獲得 _sc=sc.GetComponent<Score>();//ゲーム管理スクリプトを取得 } // Update is called once per frame void Update() { if (Input.GetMouseButtonDown(0)) { GetComponent<AudioSource>().Play(); _rigidbody.velocity = Vector2.zero;//落下速度を一度リセット _rigidbody.AddForce(new Vector2(0, Jump));//上方向の力 } } //固定フレーム更新 private void FixedUpdate() { Vector3 position = transform.position; //画面の外から出ないようにする float y = transform.position.y; float vx = _rigidbody.velocity.x; if (y > GetTop()) { _rigidbody.velocity = Vector2.zero;//一度速度をリセット position.y = GetTop(); } if (y < GetBottom()) { //下に落ちたらオートジャンプ _rigidbody.velocity = Vector2.zero;//落下速度を一度リセットする _rigidbody.AddForce(new Vector2(0, Jump)); position.y = GetBottom();//押し戻す } //座標を反映する transform.position = position; } //画面上を習得する float GetTop() { Vector2 max = Camera.main.ViewportToWorldPoint(Vector2.one); return max.y; } //画面下を習得 float GetBottom() { //座標獲得 Vector2 min = Camera.main.ViewportToWorldPoint(Vector2.zero); return min.y; } //衝突判定 private void OnTriggerEnter2D(Collider2D collision) { //衝突して消滅 Destroy(gameObject); //ゲームオーバーを通知 _sc.StartGameOver(); } }

コード(スコア管理の部分)

ublic

1{ 2 public Text scoreText;// スコアを表示するText 3 public Text highScoreText; //ハイスコアを表示するText 4 private int highScore; //ハイスコア用変数 5 private string key = "HIGH SCORE"; //ハイスコアの保存先キー 6 int score = 0;//スコア 7 8 enum State 9 { 10 Main,//メインゲーム 11 GameOver,//ゲームオーバー 12 } //スコア 13 //状態 14 State _state = State.Main; 15 16 // PlayerPrefsで保存するためのキー 17 private string highScoreKey = "highScore"; 18 19 public void FixedUpdate() 20 { 21 //メインゲーム中のみスコア上昇 22 if (_state == State.Main) 23 { 24 score += 1; 25 } 26 27 } 28 public void StartGameOver() 29 { 30 31 _state = State.GameOver; 32 } 33 34 void Start() 35 { 36 highScore = PlayerPrefs.GetInt(key, 0); 37 //保存しておいたハイスコアをキーで呼び出し取得し保存されていなければ0になる 38 highScoreText.text = "ハイスコア: " + highScore.ToString(); 39 PlayerPrefs.DeleteAll(); 40 } 41 42 void Update() 43 { 44 //ハイスコアより現在スコアが高い時 45 if (score > highScore) 46 { 47 48 highScore = score; 49 //ハイスコア更新 50 51 PlayerPrefs.SetInt(key, highScore); 52 //ハイスコアを保存 53 54 highScoreText.text = "ハイスコア: " + highScore.ToString(); 55 scoreText.text = "スコア: "+score.ToString(); 56 // スコア・ハイスコアを表示する 57 } 58 59 } 60 61} 62

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

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

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

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

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

ayousanz

2020/11/23 04:11 編集

どのscriptの何行目でerrorになっているのでしょうか. gm.StartGameOver();でerrorになっているのであれば,gmというものをこのコードがかいてあるscriptが把握できていないためだと思いますよ
nine_fish397

2020/11/23 05:12

おっしゃると通りでgm.StartGameOver();の部分でエラーが発生します。なぜscriptの把握してくれないのでしょうか?
ayousanz

2020/11/23 05:54

gm.~というのはgmというクラスを呼び出しています.しかし,上記ではgmというものを定義していないためプレイヤー側のscriptが把握できていません.基本的にほかのscriptを呼びたい場合は[SerializeField]にするかpublicにしてアタッチする必要があります. 詳しくは,「ほかのscriptを呼び出す Unity」などで調べてみてください
nine_fish397

2020/11/23 18:00

SerializeField化していなかったのでしたのですが、新たに「UnassignedReferenceException: The variable sc of PlayerControll has not been assigned.You probably need to assign the sc variable of the PlayerControll script in the inspector.」というエラーがでました上記に修正とプレイヤーすべてのscriptを載せました。お時間があれば助言をお願いします。
hogefugapiyo

2020/11/24 00:30

UnassignedReferenceException はアタッチされていないっていうエラーです。インスペクターからドラッグアンドドロップで該当するスクリプト、オブジェクトをアサインしてください
nine_fish397

2020/11/24 14:12

ありがとうございます。Scoreオブジェクトをプレイヤーにアタッチしたところゲーム上でのエラーはなくなりました。ただ、変わらず当初のプレーヤーが衝突時にデルタタイムで加算されたスコア上昇を止めることができないです。
ayousanz

2020/11/24 14:45

Destroy(gameObject); _sc.StartGameOver(); この二つの行の順番を入れ替えてみてください
nine_fish397

2020/11/24 15:11

入れ替えてみたのですが駄目でした
ayousanz

2020/11/25 04:15

一つUnityの管理であまりFixedUpdate()は使わないほうがいいかと思います. こちらは呼ばれる時間が決まっていないため,バグが発生する可能性があります. また,updateとの同時使用もバグが出る可能性があるため使用を避けたほうがいいと思いますよ(呼ばれるタイミングがずれることがあるため)
nine_fish397

2020/11/25 14:14

if (_state == State.Main) { score += 1; } はupdateだけに書いたほうがいいということでしょうか?
ayousanz

2020/11/25 14:36

そうですね その部分をUpdateに移すことでバグが減ると思います(今回の問題には直接影響はしないかもしれませんが)
nine_fish397

2020/11/25 14:59

ありがとうございます。スコアは止まらないですが。そっちに書くようにします。
lazh

2020/11/26 13:49

質問にあるスクリプトを試してみましたがゲームオーバー後はスコア加算止まりました もしかしたら_stateがState.GameOverになった後すぐにState.Mainに変わってたりしませんか? Update内で Debug.Log(_state.ToString()); と書いて確認してみてほしいです
nine_fish397

2020/11/26 16:27

おっしゃるとおりプレイヤーの衝突時Mainとデバックログで確認できました。
lazh

2020/11/27 13:10

衝突時_stateがState.Mainのままってことですか?State.GameOverになった後State.Mainに戻った? どちらにせよスクリプトには_stateがState.Mainの時score += 1;を通る処理があるのでスコア加算が止まらない原因はそれだと思います!
nine_fish397

2020/11/27 13:25

_stateがState.Main時からState.GameOverが呼び出されてもscore += 1;があるせいでまたState.Mainの状態に戻ってスコアが加算されてしまうということですか?これはどうしても止まらないのでしょうか?
lazh

2020/11/27 14:22 編集

_stateがState.GameOverになっても、おそらくどこか別のところですぐにState.Mainに戻す処理が行われているせいで if (_state == State.Main) { score += 1; } を満たしているからスコア加算が止まらないじゃないのかなという話です 実際Debug.Logで確認したら想定ではGameOverなはずなのにMainになっていたんですよね? _stateにState.Mainを入れてるところを見つけていったんコメントアウトしてみるといいかもしれないです
guest

回答2

0

自己解決

update内にif(_state = State.GameOver;){}をツリーの一番上に書きこむことでゲームオーバーを呼び出せました。

投稿2020/12/05 14:07

nine_fish397

総合スコア8

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

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

0

そもそも以下の部分が呼ばれたときに,StartGameOver()は正常に呼べているのでしょうか?
Debugなどで確認をしてみてください

cs

1private void OnTriggerEnter2D(Collider2D collision) 2 { 3 //衝突して消滅 4 Destroy(gameObject); 5 //ゲームオーバーを通知 6 _sc.StartGameOver(); 7 }

追記:2020/11/27
以下のようにUpdateの中でstateを確認したらいいと思いますよ

cs

1void Update() 2 { 3 //ハイスコアより現在スコアが高い時 4 if (score > highScore) 5 { 6 7 highScore = score; 8 //ハイスコア更新 9 10 PlayerPrefs.SetInt(key, highScore); 11 //ハイスコアを保存 12 13 highScoreText.text = "ハイスコア: " + highScore.ToString(); 14 scoreText.text = "スコア: "+score.ToString(); 15 // スコア・ハイスコアを表示する 16 } 17 if(_state == State.Main) { 18 score++; 19 } 20 }

投稿2020/11/26 05:51

編集2020/11/27 13:31
ayousanz

総合スコア258

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

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

nine_fish397

2020/11/26 12:41 編集

コンソールを確認したところちゃんとデバックログが表示されていたので呼び出されていると思います
ayousanz

2020/11/26 14:01

ではそのデバッグログで実際にスコアが加算されているかどうかを確認してみてください
nine_fish397

2020/11/26 16:27

すみませんどうやってやるのでしょうか?
ayousanz

2020/11/26 16:52

Update()の中でscoreとhightScoreをDebug.logで表示してみてください (ifの中に入れたらだめです
nine_fish397

2020/11/27 06:29

Debug.Log(score.ToString());で調べたところちゃんと加算されていました
ayousanz

2020/11/27 06:55

ならあとはgameStateを加算されているところでif判定をして変えればいいのでは??
nine_fish397

2020/11/27 12:06

public void StartGameOver()にf (_state == State.Main)をいれるということですか?すみません意味をよく分かってないです
ayousanz

2020/11/27 13:32

追加しました あと言葉は厳しいようですが,ある程度自分で試行錯誤するのは必要だと思いますよ
nine_fish397

2020/11/27 13:51

残念ながらスコアは止まりませんでした。一応ここで質問する3日前からいろいろなサイトで調べてテストを繰り返していたのですがなかなかうまくいかず今回このサイトで質問させていただきました。有力な回答を待ちつつ自分でも解決できるよう進めていきたいと思います。ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問