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

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

詳細はこちら
C#

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

Q&A

解決済

1回答

829閲覧

UNITY2Dでエネミーと衝突するとフリーズしてしまうバグについて

cushionA

総合スコア90

C#

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

0グッド

0クリップ

投稿2019/10/08 15:36

編集2019/10/09 09:28
コード ```### 前提・実現したいこと unityで敵と衝突した際にレイヤーを移動して無敵判定をつけて、さらにその間ダメージを受けたことを表現するアニメーションが再生されるようにしたいと考えています。 ### 発生している問題・エラーメッセージ 一度アニメーションが再生されるとデフォルトのアニメーションに戻らなくなり、また無敵判定とフラグ管理にコルーチンを利用したところ敵と衝突した際に100%フリーズするようになってしまいました。 もう一週間ほどこのエラーに苦しんでいて、エラーメッセージが見られずコンパイルエラーも確認できないため原因が全くわかりません。

エラーメッセージ

### 該当のソースコード ```C# Animator anim = null; Animation anime; private Rigidbody2D rb = null; private string enemyTag = "Enemy"; SpriteRenderer sr; private float dashTime; void Start() { //コンポーネントのインスタンスを捕まえる anim = GetComponent<Animator>(); anime = GetComponent<Animation>(); rb = GetComponent<Rigidbody2D>(); sr = GetComponent<SpriteRenderer>(); } /// <summary> /// X成分で必要な計算をし、速度を返す。 /// </summary> /// <returns>The x.</returns> private float SetX() { float xSpeed; float horizontalKey = Input.GetAxis("Horizontal"); if (horizontalKey > 0) { transform.localScale = new Vector3(1, 1, 1); isRun = true; xSpeed = speed; dashTime += Time.deltaTime; } else if (horizontalKey < 0) { transform.localScale = new Vector3(-1, 1, 1); isRun = true; xSpeed = -speed; dashTime += Time.deltaTime; } else { isRun = false; xSpeed = 0.0f; dashTime = 0.0f; } if (horizontalKey > 0 && beforeKey < 0) { dashTime = 0.0f; } else if (horizontalKey < 0 && beforeKey > 0) { dashTime = 0.0f; } xSpeed *= dashCurve.Evaluate(dashTime); beforeKey = horizontalKey; return xSpeed; } void OnCollisionEnter2D(Collision2D collision) { if (collision.gameObject.tag == "Enemy") { StartCoroutine("Damage"); GManager.instance.heartNum(HPを格納した変数です) -= 1; } } IEnumerator Damage() { isDown(敵と衝突したフラグ) = true; yield return null; sr.sortingLayerID = (10); yield return new WaitForSeconds(4); sr.sortingLayerID = (8); isDown = false; } void DamageMotion(){ if(isDown == true){ anim(animationのインスタンスです).Play("Damage"); } else { anime(animatorのインスタンスです).Stop("Damage"); } } ソースコード

試したこと

アニメーションについてはPlay関数で動かしたものが戻らないのは何故かと考え、isDownがFalseになるとデフォルトモーションが再生されるようにしたり、animatorクラスのStopメソッドを利用したりしました。
Stopメソッドについては現在フリーズするようになっているためこれで希望通りに動くのかは分かっていません。
animation.Playの対になるanimation.Stopを本当は使いたかったのですが、非推奨ということで何故かコンパイルエラーが起きます。
それからフリーズについては、else文を付け足して無限ループを防ごうとしたりしましたが、正直お手上げです。
どうしたらいいのか全くわかりません。
どうかご助力よろしくお願いいたします。

補足情報(FW/ツールのバージョンなど)

unityのバージョンは2019,1,10f1というやつのpersonalです。
その他足りない情報などあれば随時付け足させていただくのでどうぞお申し付けください。
よろしくお願いいたします。

追記
DamageMotion()はフレームごとにisDownのif文で判定を行って実行されるものと認識していました。
Fixedやawakeやstartがつかない関数は全てupdateと同じ扱いになると聞いていたので。
もし違うのであれば、UpdateやFixedで別途呼び出したほうがよろしいのでしょうか。
質問に質問で返す無知をお許しください。
回答としてはUpdateと同じくフレームごとに呼び出されていると認識しているものの、もし違うのであれば呼び出せていませんということになります。
特にソースコードの外でUpdateやFixedUpdateで呼び出していたりはしません。
すみません。

アニメーションの素材です
デフォルト、立って停止している状態
https://imgur.com/MlkXxpP.png
ダメージを受けた状態(isDown==trueの際にPlayしているもの)
https://imgur.com/MVzawhE.png
歩きモーションです
https://imgur.com/flkVvzf.png
https://imgur.com/qKi6B6y.png

ソースコードについてisDownまわりとアニメーション関連に絞りました。
もしこれでも不十分でしたら、マナー違反でないのならGitで管理しているプロジェクトをこの場に出すようなことをさせていただいてもよろしいでしょうか?
それはともかく、幾度もの不手際重ねてお詫び申し上げます。
どうぞご鞭撻のほどよろしくお願いいたします。

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

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

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

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

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

hogefugapiyo

2019/10/09 00:32

DamageMotion はどこで呼ばれていますか?
cushionA

2019/10/09 07:19

すみません、修正依頼を見ていませんでした。 お許しください。
guest

回答1

0

ベストアンサー

いまいち添付されたコードだけだと再現性がなかったので、もう少し詳細なコードとアニメーションのスクショなど情報を添えてもらえればうれしいです。もしくは下記に別アプローチも考えてみました。

#ジャストアイデア
記載コードをコピペしてもいまいち把握しきれなかったのでジャストアイデアですが
コルーチンではなく、アニメーションイベント側で無敵解除をコントロールするアプローチはどうでしょうか?

・敵に当たった際は、ダウン判定を取ってアニメーションを再生するところまでを担保。
・アニメーションの最後にやられモーション終了(OnDamageMotionEnd())をアニメーションイベントを挿入

ぶつかった→アニメーション再生→アニメーション側のイベントでメソッド呼び出し→OnDamageMotionEndが呼ばれて無敵が終了する

【Unity】Animationから関数を呼び出す方法
https://www.unipafu.com/entry/2018/05/12/105220

cs

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class Test7 : MonoBehaviour { 6 7 bool isDown; 8 Animator myAnimator; 9 10 private void Start() { 11 myAnimator = GetComponent<Animator>(); 12 } 13 14 void OnCollisionEnter2D(Collision2D collision) { 15 if (collision.gameObject.tag == "Enemy" && !isDown) { 16 Debug.Log("やられモーション中は無敵"); 17 18 isDown = true; 19 gameObject.layer = 10; 20 myAnimator.Play("Damage"); 21 } 22 } 23 24 public void OnDamageMotionEnd() { 25 Debug.Log("無敵終了"); 26 27 isDown = false; 28 gameObject.layer = 0; 29 } 30 31} 32

投稿2019/10/09 00:46

hogefugapiyo

総合スコア3302

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

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

cushionA

2019/10/09 02:12

返信ありがとうございます! まずは考えもしなかったような方針を与えてくださったことに感謝いたします。 アニメーションから関数を呼び出すというのは全く知らないやり方だったのでやってみようと思います。 添付してくださった記事も拝見させていただいて参考にしたいです。 それからソースコードとスクリーンショットの方ですが、こちらは帰宅してから改めて貼らせていただきます。 ソースコードは上記のものに変数の宣言を付け足して、それから移動の関数の部分も貼る、というような形で再現性はとれますでしょうか? 敵側はエネミータグと個別レイヤー、衝突判定、それからプレイヤーキャラ追跡や行ったり来たりするなどの処理を乗せているだけなので特にエラーとは関係ないと思われますので。(間違ってたらすみません。言ってくださればそちらもお持ちします) アニメーションについてはスクリーンショットが何故かうまく行かないのでpngファイルを添付するという形でもよろしいでしょうか? もしアニメーターの管理画面のことをおっしゃってるのでしたら、スクショソフトを入れるなどしてなんとかやってみたいと思います。 情報が足りなかったばかりに二度手間をおかけしてすみません。 それから素晴らしい提案に感謝いたします。 ではまた後ほど出直します。 不手際でご迷惑おかけして申し訳ありませんでした。
cushionA

2019/10/09 07:33 編集

不慣れなもので修正依頼を見ていませんでした。 すぐに追記します。 申し訳ありません。
hogefugapiyo

2019/10/09 09:47

追記いただきありがとうございます。あとで確認してみます。 1点追記しておくと、DamageMotionは明確に呼んであげないと動作しません。なのでupdateや他のメソッドから呼び出していないのであれば、DamageMotionは呼ばれていないように思います。 ためしにDamageMotion内に Debug.Log("DamageMotion実行"); などとデバッグログを仕込んで動かしてみてください。
hogefugapiyo

2019/10/09 09:51

もし上げられる内容なのであればgitあげてもらえればそちらをチェックしてみます。
cushionA

2019/10/09 10:13

お忙しい中返信ありがとうございます。 Gitの方は、トピック以外にも問題が山積しており、かなり混沌としているのでこちらのソースコードでも情報が足りなかった場合に見ていただこうと思います。 その時はお手間おかけしますが何卒よろしくお願いします。 それから関数化したものをUpdate等で呼び出さなければならないということは全く知らなかったので、同じ要因で動作していないメソッドは多々あると思われます。 バグまみれで頭を抱えていたのですが、これも解決の糸口になりそうです。 本当にありがとうございます。
hogefugapiyo

2019/10/10 01:05

質問文の追記ソースコードを再度コピーして貼り付けてみましたが、変数が足りなかったりで動作の再現がとれなさそうでした。(そもそも全角カッコとか入ってましたが、元ソースは大丈夫ですよね?) まずは、切り分けていく必要があるので Debug.Log(); を各所にいれてみてください。 たとえば、Debug.Log(”キャラクター無敵処理開始”); とか Debug.Log(”キャラクター無敵処理解除”); とか、何をやったのかわかるような内容を書いておきます。 どこまで処理が進んでいるのか、逆にどこの処理が呼ばれていないのかを確認する一番ラクな方法です。
cushionA

2019/10/10 01:20 編集

すみません、ソースコードとしてまとめる際に一部スマートフォンで打ち込んでいたことにより、そのような不具合が生じたものと思われます。 お手を煩わせてしまい大変申し訳ありません。 それからDebug.Logの使い方についてご指南いただけたことも感謝します。 なんのために差し込んでいるのか不思議でならなかったのですが、その部分が実行されているか確認するためだったのですね。 勉強不足で迷惑をかけてしまい、面目ありません。 さしあたっては今晩あたりにDebug.Logを追加したプロジェクトをGitのURLでこちらに提出させていただきたく思います。 二度手間三度手間で日をまたぐやり取りになってしまい申し訳ありません。 そして根気よく付き合って下さりありがとうございます。
cushionA

2019/10/10 14:39 編集

本当にすみません。 Gitについてよくわかっていなくて、修正した分をコミットしようとしてエラーが重なったのでわけも分からずリバートしたりしていたらデータが巻き戻されて、なんとかもとに戻そうとundoを繰り返したところヒストリーが消し飛んでもう復旧不可能なくらいにめちゃくちゃになってしまいました。 メンタルが折れそうなこと、それから元に戻すのにどれくらいかかるのか全く分からないのもあり、これ以上お付き合いさせてしまうのは申し訳ないので誠に勝手ながら断念いたします。 立ち直ったらジャストアイデアでいただいたご意見をもとに作り直してみる所存です。 数日振り回した果てにこんな結果になってしまい申し訳ありません。 そして根気よくお付き合いして下さり本当にありがとうございました。 本当に本当に申し訳ありません。 そして最後にUpdateでの呼び出し、アニメーションイベント、デバックログの使い方など本当にたくさんのことを教えてもらって、またなにより親身になって下さったことに重ねてお礼を申し上げます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問