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

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

詳細はこちら
C#

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

Unity

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

Q&A

解決済

1回答

1235閲覧

コルーチンが勝手に起動してしまう

da-ryo

総合スコア11

C#

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

Unity

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

0グッド

1クリップ

投稿2021/01/22 11:02

#現状
今までは思い通りに動いていたスクリプトが急に異常な動きをしていて困っております。

あるオブジェクトが生成されたら以下の2つの処理を実装していたのですが突然うまくいかなくなったため解決お願いいたします。
①Z軸方向に移動していく
②体力がなくなったらアイテムをランダム生成して消える

上記の①②通りに言っていた処理が以下のようになってしまいました。
①移動しない
②体力がなくなってもいないのにその場でアイテムをランダムに生成し続ける(∞個)

#スクリプト
一応スクリプト全体を下記に載せておきますが独自に検証してみた結果Start内で指定しているcurrentHpの値が常に0となってしまっているようです。

currentHp=200;と直接代入する形をとっても0になり続けているようでUpdate内の死んだ時の処理が永遠に呼び出され続けているようです。

ただ納得いかないのがコルーチンで呼び出されてアイテム生成はし続けるものの、その下にあるDestroyは実行されないこと、update内のWalking関数が実行されないことです。

public class BlueManager : MonoBehaviour
{
public float speed;
private Animator animator;
public float MaxHp;
public GameObject ball;
PlayerAttack script;
private GameObject player;
ExpManager expScript;
private bool walk;
float currentHp;
[SerializeField] GameObject DamageFire;
//アイテム
public GameObject heal;
public GameObject powerUp;
public GameObject coin;
public GameObject fiveCoin;
public GameObject bullian;
Bank bankScript;
public GameObject bomb;
Bomb bombScript;

// Start is called before the first frame update void Start() { animator = GetComponent<Animator>(); script = player.GetComponent<PlayerAttack>(); player = GameObject.Find ("PlayerBack"); expScript = player.GetComponent<ExpManager>(); bankScript = player.GetComponent<Bank>(); MaxHp = 200; currentHp = MaxHp; walk = true; bombScript = bomb.GetComponent<Bomb>(); } // Update is called once per frame void Update() { Debug.Log (currentHp); if(walk == true) { Walking(); } //死んだ時 if (currentHp <= 0) { animator.SetBool( "IsDie", true); StartCoroutine("Death"); walk = false; } } public void Walking() { transform.position += new Vector3( 0, 0, -speed * Time.deltaTime); animator.SetBool( "IsWalk", true); } private void OnTriggerEnter(Collider other) { if (other.gameObject.tag == "Player") { bankScript.LossCoin(); Destroy (this.gameObject); } //ダメージ時 if (other.gameObject.tag == "Ball") { float damage = script.Attack; float lateHp = currentHp - damage; currentHp = lateHp; //Debug.Log(currentHp); Vector3 DamagePos = this.transform.position; Instantiate ( DamageFire, DamagePos, Quaternion.identity); } if (other.gameObject.tag == "Bomb") { int bombDamage = 30; currentHp = currentHp - bombDamage; Vector3 DamagePos = this.transform.position; Instantiate ( DamageFire, DamagePos, Quaternion.identity); Destroy (other.gameObject); } } IEnumerator Death() { yield return new WaitForSeconds(1); int drop = Random.Range ( 1, 101); if (drop <= 5) { Vector3 itemPos = new Vector3 ( this.transform.position.x, this.transform.position.y + 1, this.transform.position.z); Instantiate ( heal, itemPos, Quaternion.identity); } if (drop >= 6 && drop <= 10) { Vector3 itemPos = new Vector3 ( this.transform.position.x, this.transform.position.y + 1, this.transform.position.z); Instantiate ( powerUp, itemPos, Quaternion.identity); } //コインドロップ if (drop >= 11 && drop <= 100) { int dropC = Random.Range ( 1, 101); if (dropC >= 1 && dropC <= 45) { Vector3 itemPos = new Vector3 ( this.transform.position.x, this.transform.position.y + 1, this.transform.position.z); Instantiate ( coin, itemPos, Quaternion.identity); } if (dropC >= 46 && dropC <= 80) { Vector3 itemPos = new Vector3 ( this.transform.position.x, this.transform.position.y + 1, this.transform.position.z); Instantiate ( fiveCoin, itemPos, Quaternion.identity); } if (dropC >= 81 && dropC <= 100) { Vector3 itemPos = new Vector3 ( this.transform.position.x, this.transform.position.y + 1, this.transform.position.z); Instantiate ( bullian, itemPos, Quaternion.identity); } } expScript.BlueExp(); Destroy(this.gameObject); }

}

#解決したいこと
①walking関数を発動させたい
②currentHpが常に0になる問題を解決したい
③コルーチンで呼び出されたDeath関数の最後にあるDestroyが発動するようにしたい

上記の3つが解決策だと思うのですがなぜ今まで普通にできた処理が急に不可能になったのかが一番意味不明です。

解決策あれば何卒よろしくお願いいたします。

#エラーメッセージ
最初に一度出てくるエラー
NullReferenceException: Object reference not set to an instance of an object
BlueManager.Start () (at Assets/Script/Enemy/BlueManager.cs:31)

フレーム毎に出てくるエラー
NullReferenceException: Object reference not set to an instance of an object
BlueManager+<Death>d__22.MoveNext () (at Assets/Script/Enemy/BlueManager.cs:122)
UnityEngine.SetupCoroutine.InvokeMoveNext (System.Collections.IEnumerator enumerator, System.IntPtr returnValueAddress) (at /Users/bokken/buildslave/unity/build/Runtime/Export/Scripting/Coroutines.cs:17)

一応エラーについても調べましたがそれらしいものは見当たりませんでした

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

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

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

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

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

lazh

2021/01/22 11:24

確認してませんが最初のエラーがcurrentHp = MaxHpより前の行で発生していてcurrentHp = MaxHpが実行されてないからおかしいことになってると思います まずはそれの解決からかなと思います
gentaro

2021/01/22 23:59

こんな長大なソース載せて質問したいならせめてMarkdownぐらいちゃんと使おう。 まず読む気がしない。
guest

回答1

0

ベストアンサー

雰囲気だけみて、無限ループはUpdateでCoroutineが発動し続けているから。nullが解消されればとりあえず収まるでしょう。

とりあえずこれが怪しい。
script = player.GetComponent<PlayerAttack>();
player = GameObject.Find ("PlayerBack");

順番が逆じゃないですかね?

script = player.~ // ここのplayerはまだnullなのでここで例外吐かれてるっぽい、unityは落ちませんけど、エラーの時点でstart内の以降はスキップされます。でもUpdateは生きてるのでhp <= 0のせいでCoroutineの無限ループ。ループ内expScrpitもnullなので惜しくもDestroyまでたどり着かない。

投稿2021/01/23 06:04

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

da-ryo

2021/01/23 09:03

変更したところうまくいきました! エラーになった段階で処理が飛ばされアップデートに移る、そしてコルーチンもnullのためそこで処理が止まってしまうという処理の流れまで知れて大変勉強になりました。 他の方のご指摘の通りスクリプトが長くなってしまい申し訳ございません。 そんな中解決してくださりありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問