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

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

ただいまの
回答率

90.12%

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

解決済

回答 1

投稿 編集

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

cushionA

score 1

コード

 前提・実現したいこと

unityで敵と衝突した際にレイヤーを移動して無敵判定をつけて、さらにその間ダメージを受けたことを表現するアニメーションが再生されるようにしたいと考えています。

発生している問題・エラーメッセージ

一度アニメーションが再生されるとデフォルトのアニメーションに戻らなくなり、また無敵判定とフラグ管理にコルーチンを利用したところ敵と衝突した際に100%フリーズするようになってしまいました。
もう一週間ほどこのエラーに苦しんでいて、エラーメッセージが見られずコンパイルエラーも確認できないため原因が全くわかりません。

エラーメッセージ

該当のソースコード

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で管理しているプロジェクトをこの場に出すようなことをさせていただいてもよろしいでしょうか?
それはともかく、幾度もの不手際重ねてお詫び申し上げます。
どうぞご鞭撻のほどよろしくお願いいたします。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

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

  • hogefugapiyo

    2019/10/09 09:32

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

    キャンセル

  • cushionA

    2019/10/09 16:19

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

    キャンセル

回答 1

checkベストアンサー

+1

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

ジャストアイデア

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

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

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

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

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

public class Test7 : MonoBehaviour {

    bool isDown;
    Animator myAnimator;

    private void Start() {
        myAnimator = GetComponent<Animator>();
    }

    void OnCollisionEnter2D(Collision2D collision) {
        if (collision.gameObject.tag == "Enemy" && !isDown) {
            Debug.Log("やられモーション中は無敵");

            isDown = true;
            gameObject.layer = 10;
            myAnimator.Play("Damage");
        }
    }

    public void OnDamageMotionEnd() {
        Debug.Log("無敵終了");

        isDown = false;
        gameObject.layer = 0;
    }

}

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/10/10 10:05

    質問文の追記ソースコードを再度コピーして貼り付けてみましたが、変数が足りなかったりで動作の再現がとれなさそうでした。(そもそも全角カッコとか入ってましたが、元ソースは大丈夫ですよね?)

    まずは、切り分けていく必要があるので Debug.Log(); を各所にいれてみてください。
    たとえば、Debug.Log(”キャラクター無敵処理開始”); とか Debug.Log(”キャラクター無敵処理解除”); とか、何をやったのかわかるような内容を書いておきます。

    どこまで処理が進んでいるのか、逆にどこの処理が呼ばれていないのかを確認する一番ラクな方法です。

    キャンセル

  • 2019/10/10 10:17 編集

    すみません、ソースコードとしてまとめる際に一部スマートフォンで打ち込んでいたことにより、そのような不具合が生じたものと思われます。
    お手を煩わせてしまい大変申し訳ありません。
    それからDebug.Logの使い方についてご指南いただけたことも感謝します。
    なんのために差し込んでいるのか不思議でならなかったのですが、その部分が実行されているか確認するためだったのですね。
    勉強不足で迷惑をかけてしまい、面目ありません。

    さしあたっては今晩あたりにDebug.Logを追加したプロジェクトをGitのURLでこちらに提出させていただきたく思います。
    二度手間三度手間で日をまたぐやり取りになってしまい申し訳ありません。
    そして根気よく付き合って下さりありがとうございます。

    キャンセル

  • 2019/10/10 23:18 編集

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

    キャンセル

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

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