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

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

ただいまの
回答率

90.04%

Unityでクリアシーンに最終スコアを表示する方法が知りたいです。

受付中

回答 1

投稿 編集

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

sancor

score 1

Unityでゲームシーンでの最終スコアをクリアシーンに反映したいのですが、うまくいきません。
ネットに書いてあることも試してみたのですが、やり方が悪いのか上手くいきませんでした。
教えてほしいです。

流れとしては、ゲームシーンで、CursorShotScriptでRayがmatoPrefabを破壊しそのたびにUIDirectorのscoreincrease関数を起動します。
UIDirectorでscoreにmatoPrefabが破壊された回数を表示し、TimerScriptで制限時間が来たらクリアシーンでClearDirector内で最終的なスコアの数値をコンソールに表示するようにしたいです。

まずCursorShotScriptです。

using UnityEngine;
using System.Collections;
using UnityEngine.SceneManagement;

public class CursorShotScript : MonoBehaviour {

    // カーソルに使用するテクスチャ
    [SerializeField]
    private Texture2D cursor;
    [SerializeField]
    private matoGenerator matoGenerator;
    public GameObject matoPrefab;
    GameObject gameobject;

    void Start () {
        // カーソルを自前のカーソルに変更
        Cursor.SetCursor(cursor, new Vector2(cursor.width / 2, cursor.height / 2), CursorMode.ForceSoftware);
    }

    void Update () {
        // マウスの左クリックで撃つ
        if(Input.GetButtonDown("Fire1")) {
            Shot();
        }
    }

    // 敵を撃つ
    void Shot() {
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

        float maxDistance=10;

        RaycastHit2D hit = Physics2D.Raycast((Vector2)ray.origin, (Vector2)ray.direction, maxDistance, LayerMask.GetMask("Enemy"));

        if(hit.collider) {
            matoGenerator.Create();
            Destroy(hit.collider.gameObject);
            GameObject director = GameObject.Find("UIDirector");
            director.GetComponent<UIDirector>().scoreincrease();
        }
        if(hit.collider.tag=="Enemy"){
            SceneManager.LoadScene("LoseScene");
             Debug.Log ("RayがPlayerに当たった");
        }
    }
}


次にUIDirectorです。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class UIDirector : MonoBehaviour {

    public GameObject score;
    public int score_current=0;
    // Use this for initialization
    void Start () {
        this.score = GameObject.Find("score");
    }
    public void scoreincrease(){
        this.score_current++;
        this.score.GetComponent<Text>().text=score_current.ToString();
    }
}


次にTimerScriptです。

using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.SceneManagement;

public class TimerScript : MonoBehaviour {

    // トータル制限時間
    private float totalTime;
    // 制限時間(分)
    [SerializeField]
    private int minute;
    // 制限時間(秒)
    [SerializeField]
    private float seconds;
    // 前回Update時の秒数
    private float oldSeconds;
    private Text timerText;

    void Start () {
        totalTime = minute * 60 + seconds;
        oldSeconds = 0f;
        timerText = GetComponentInChildren<Text>();
    }

    void Update () {
        // 制限時間が0秒以下なら何もしない
        if (totalTime <= 0f) {
            return;
        }
        // 一旦トータルの制限時間を計測;
        totalTime = minute * 60 + seconds;
        totalTime -= Time.deltaTime;

        // 再設定
        minute = (int) totalTime / 60;
        seconds = totalTime - minute * 60;

        // タイマー表示用UIテキストに時間を表示する
        if((int)seconds != (int)oldSeconds) {
            timerText.text = minute.ToString("00") + ":" + ((int) seconds).ToString("00");
        }
        oldSeconds = seconds;

        if(totalTime <= 0f) {
            SceneManager.LoadScene("ClearScene");
        }
    }
}


最後にClearDirectorです。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;


public class ClearDirector : MonoBehaviour {
    public GameObject score;

    void Start () 
    {

    }

    // Update is called once per frame
    void Update () {
        if(Input.GetMouseButtonDown(0)){
            SceneManager.LoadScene("Mainmenu");
        }
    }
}


変な文章で申し訳ありません。

回答を受けての変更後

snowshinkさんの回答をいただいて変更したときのスクリプトとエラーです
変更したスクリプトはUIDirectorとClearDirectorです

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class UIDirector : MonoBehaviour {

    public Text score;
    public int score_current=0;
    // Use this for initialization
    void Start () {
        score = GetComponent<Text>();
        DontDestroyOnLoad(this.gameObject);
    }
    public void scoreincrease(){
        this.score_current++;
        this.score.text=score_current.ToString();
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;


public class ClearDirector : MonoBehaviour {
    public GameObject score;
    void Start () 
    {
        UIDirector loadScene = FindObjectOfType<UIDirector> ();
        Debug.Log (loadScene.score);
    }

    // Update is called once per frame
    void Update () {
        if(Input.GetMouseButtonDown(0)){
            SceneManager.LoadScene("Mainmenu");
        }
    }
}


エラー画面はこんな感じです。
イメージ説明
エラー文章は、
NullReferenceException: Object reference not set to an instance of an object
UIDirector.scoreincrease () (at Assets/UIDirector.cs:17)
CursorShotScript.Shot () (at Assets/CursorShotScript.cs:40)
CursorShotScript.Update () (at Assets/CursorShotScript.cs:24)
です。初期配置しているmatoPrefabを破壊したときに発生しました。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

0

構造がよくわかんないのですが、
ゲームシーンがあって、ここにスコアオブジェクトがあって、
クリアしたらゲームクリアシーンを読み込んでというのであれば、
スコアオブジェクトをシーン読み込みで破棄させないようにしたらどうでしょうか。

Start(){
 score = GameObject.Find("score");
 DontDestoyOnLoad(score);
}


これで結果が保持され続けるのではないでしょうか。

気になったのですが、スコア表示するテキストオブジェクトとスコアを保持するオブジェクトを別々にする
必要はないのでは。

Text score;
public int score_current = 0;

Start(){
 score = GetComponent<Text>();
 DontDestoyOnLoad(this.gameObject);
}I

public void IncreaseScore(){
 score_current++;
 score.text = score_current;
}


こう変更してscoreにはめて?ください。
これでSceneManager.LoadScene("GameClearScene");しても結果は表示され続けます。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/11/09 22:15

    複雑そうなので、エラーが出たところのエディタ画面を見せて欲しいです。
    そこまで詳しくないので直せる保証はないですが、やれるところまで…
    ログウィンドウのerror on pauseでヌルポが出ると止まります。

    キャンセル

  • 2019/11/09 22:47

    追加させていただきました。
    よろしくお願いいたします。

    キャンセル

  • 2019/11/10 22:15

    ごめんなさい、TextのscoreをGetComponentで取得するのはやめておいた方がいいですね。
    インスペクターから選択するようにしてください。GetComponentとFindは重い処理なので。
    Shot()のところもオブジェクトをインスペクターから取得するように。
    クラスはGameObjectではなくて、UIDirectorやTextにすれば一々GetComponentする必要もないです。
    シングルトンでもいいのですが…(というよりマネージャー系はシングルトンがいい)

    それで、クリアシーンのTextのStart()でUIDirectorから点数を取得してみてください。

    このエラーはUIDirectorのオブジェクトにTextがない為ですね。

    キャンセル

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

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

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