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
どのscriptの何行目でerrorになっているのでしょうか.
gm.StartGameOver();でerrorになっているのであれば,gmというものをこのコードがかいてあるscriptが把握できていないためだと思いますよ
おっしゃると通りでgm.StartGameOver();の部分でエラーが発生します。なぜscriptの把握してくれないのでしょうか?
gm.~というのはgmというクラスを呼び出しています.しかし,上記ではgmというものを定義していないためプレイヤー側のscriptが把握できていません.基本的にほかのscriptを呼びたい場合は[SerializeField]にするかpublicにしてアタッチする必要があります.
詳しくは,「ほかのscriptを呼び出す Unity」などで調べてみてください
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を載せました。お時間があれば助言をお願いします。
UnassignedReferenceException はアタッチされていないっていうエラーです。インスペクターからドラッグアンドドロップで該当するスクリプト、オブジェクトをアサインしてください
ありがとうございます。Scoreオブジェクトをプレイヤーにアタッチしたところゲーム上でのエラーはなくなりました。ただ、変わらず当初のプレーヤーが衝突時にデルタタイムで加算されたスコア上昇を止めることができないです。
Destroy(gameObject);
_sc.StartGameOver();
この二つの行の順番を入れ替えてみてください
入れ替えてみたのですが駄目でした
一つUnityの管理であまりFixedUpdate()は使わないほうがいいかと思います.
こちらは呼ばれる時間が決まっていないため,バグが発生する可能性があります.
また,updateとの同時使用もバグが出る可能性があるため使用を避けたほうがいいと思いますよ(呼ばれるタイミングがずれることがあるため)
if (_state == State.Main)
{
score += 1;
}
はupdateだけに書いたほうがいいということでしょうか?
そうですね
その部分をUpdateに移すことでバグが減ると思います(今回の問題には直接影響はしないかもしれませんが)
ありがとうございます。スコアは止まらないですが。そっちに書くようにします。
質問にあるスクリプトを試してみましたがゲームオーバー後はスコア加算止まりました
もしかしたら_stateがState.GameOverになった後すぐにState.Mainに変わってたりしませんか?
Update内で
Debug.Log(_state.ToString());
と書いて確認してみてほしいです
おっしゃるとおりプレイヤーの衝突時Mainとデバックログで確認できました。
衝突時_stateがState.Mainのままってことですか?State.GameOverになった後State.Mainに戻った?
どちらにせよスクリプトには_stateがState.Mainの時score += 1;を通る処理があるのでスコア加算が止まらない原因はそれだと思います!
_stateがState.Main時からState.GameOverが呼び出されてもscore += 1;があるせいでまたState.Mainの状態に戻ってスコアが加算されてしまうということですか?これはどうしても止まらないのでしょうか?
_stateがState.GameOverになっても、おそらくどこか別のところですぐにState.Mainに戻す処理が行われているせいで
if (_state == State.Main) { score += 1; }
を満たしているからスコア加算が止まらないじゃないのかなという話です
実際Debug.Logで確認したら想定ではGameOverなはずなのにMainになっていたんですよね?
_stateにState.Mainを入れてるところを見つけていったんコメントアウトしてみるといいかもしれないです
回答2件
あなたの回答
tips
プレビュー