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

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

ただいまの
回答率

87.59%

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

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 480

score 8

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();
    }

}


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

{ 
    public Text scoreText;// スコアを表示するText
    public Text highScoreText; //ハイスコアを表示するText
    private int highScore; //ハイスコア用変数
    private string key = "HIGH SCORE"; //ハイスコアの保存先キー
    int score = 0;//スコア

    enum State
    {
        Main,//メインゲーム
        GameOver,//ゲームオーバー
    }    //スコア
         //状態
    State _state = State.Main;

    // PlayerPrefsで保存するためのキー
    private string highScoreKey = "highScore";

    public void FixedUpdate()
    {
        //メインゲーム中のみスコア上昇
        if (_state == State.Main)
        {
            score += 1;
        }

    }
    public void StartGameOver()
    {

        _state = State.GameOver;
    }

    void Start()
    {
        highScore = PlayerPrefs.GetInt(key, 0);
        //保存しておいたハイスコアをキーで呼び出し取得し保存されていなければ0になる
        highScoreText.text = "ハイスコア: " + highScore.ToString();
        PlayerPrefs.DeleteAll();
    }

    void Update()
    {
        //ハイスコアより現在スコアが高い時
        if (score > highScore)
        {

            highScore = score;
            //ハイスコア更新

            PlayerPrefs.SetInt(key, highScore);
            //ハイスコアを保存

            highScoreText.text = "ハイスコア: " + highScore.ToString();
            scoreText.text = "スコア: "+score.ToString();
            // スコア・ハイスコアを表示する
        }

    }

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • lazh

    2020/11/27 22:10

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

    キャンセル

  • nine_fish397

    2020/11/27 22:25

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

    キャンセル

  • lazh

    2020/11/27 23:20 編集

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

    キャンセル

回答 2

check解決した方法

0

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

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

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

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

void Update()
    {
        //ハイスコアより現在スコアが高い時
        if (score > highScore)
        {

            highScore = score;
            //ハイスコア更新

            PlayerPrefs.SetInt(key, highScore);
            //ハイスコアを保存

            highScoreText.text = "ハイスコア: " + highScore.ToString();
            scoreText.text = "スコア: "+score.ToString();
            // スコア・ハイスコアを表示する
        }
        if(_state == State.Main) {
         score++;
            }
    }

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/11/27 21:06

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

    キャンセル

  • 2020/11/27 22:32

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

    キャンセル

  • 2020/11/27 22:51

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

    キャンセル

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

  • ただいまの回答率 87.59%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る