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

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

ただいまの
回答率

90.76%

  • C#

    6575questions

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

  • Unity

    3605questions

    Unityは、ユニティテクノロジーが開発したゲームエンジンです。 主にモバイルやブラウザ向けのゲーム製作に利用されていましたが、3Dの重力付きゲームが簡単に作成できることから需要が増え、現在はマルチプラットフォームに対応しています。 言語はC言語/C++で書かれていますが、C#、JavaScript、Booで書かれたコードにも対応しています。

  • Unity3D

    1183questions

    Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

追尾を終えた敵が元の位置に戻って徘徊を再開するようにしたい

受付中

回答 2

投稿

  • 評価
  • クリップ 2
  • VIEW 649

toricotori

score 6

Unityで、基本は徘徊しており、一定範囲にプレイヤーが入ると追尾モードになり、範囲から外れると元の位置に戻ってまた徘徊をするといった敵のスクリプトを書いています。
・一定の範囲にプレイヤーが入ると追尾モードになる
・範囲から外れると元の位置に戻る?
まではできたのですが、そこから徘徊を再開することができません。
移動の値を見ると、少しは動いているようなのですが……
解決方法をご教授願いたいです。
現在のスクリプトは以下の通りです。

<追尾範囲のスクリプト>

public class enemyChaseTrigger : MonoBehaviour {

    public static bool emflag = false;

    void OnTriggerStay(Collider col)//プレイヤーが範囲に入ると追尾を始める
    {
        if (col.gameObject.tag == "chara")
        {  
            emflag = true;
        }
    }
    void OnTriggerExit(Collider col)//プレイヤーが範囲から外れると追尾をやめる
    {
        if (col.gameObject.tag == "chara")
        {  
            emflag = false;
            enemyWork.enstate = 0; //元の位置に戻るのを開始する
        }
    }
}


<敵の追尾スクリプト>

public class enemyChase: MonoBehaviour {


    public Transform target; // 追いかける対象
    public float rotMax; // 回転速度
    public float speed; // 移動スピード



    void Start()
    {
        target = GameObject.FindGameObjectWithTag("chara").transform;
    }

    void Update()
    {
        if (enemyChaseTrigger.emflag == true) 
        {
                // ターゲット方向のベクトルを求める
                Vector3 vec = target.position - transform.position;

                // ターゲットの方向を向く
                transform.rotation = Quaternion.Slerp (transform.rotation, Quaternion.LookRotation (new Vector3 (vec.x, 0, vec.z)), rotMax);
                transform.Translate (Vector3.forward * speed); // 正面方向に移動
        }
    }
}


<敵のスクリプト(徘徊、元の位置に戻る)>

public class enemyWork : MonoBehaviour {

    public Vector3 StartPos; //初期位置
    public Vector3 EndPos; //往復後位置
    public float time;    //移動時間
    private Vector3 deltaPos; //移動量
    private float elapsedTime; //反転用経過時間
    private bool bStartToEnd = true;
    public float dirRot = 0.0f ;
    public float offset;
    Vector3 vec;

    public static int enstate = 1;
    Vector3 AripPos; //追尾をやめたときの位置

    void Start ()
    {
        transform.position = StartPos;
        deltaPos = (EndPos - StartPos) / time;
        vec = StartPos - EndPos;
        elapsedTime = 0;
        AripPos = transform.position;
    }


    void Update ()
    {   
        if (enemyChaseTrigger.emflag == false)//プレイヤーが範囲から外れているとき
        {
            AripPos = transform.position;
            transform.position += deltaPos * Time.deltaTime;

            vec.Normalize ();
            dirRot += ( Mathf.Atan2 (vec.x, vec.z) / 3.14159265f * 180.0f - dirRot ) * 0.2f ;
            transform.eulerAngles = new Vector3 (0.0f, dirRot + offset, 0.0f);

            switch (enstate) 
            {
                case 0: //追尾をやめて元の位置に戻る
                    deltaPos = (StartPos - AripPos) / time;
                    vec = AripPos - StartPos;
                    if (transform.position == StartPos)
                    {
                        enstate = 1;
                    }
                    break;
                case 1: //徘徊する、徘徊を再開する
                    elapsedTime += Time.deltaTime;
                    if (elapsedTime > time) // 移動開始してからの経過時間がtimeを超えると往路復路反転
                    {
                        if (bStartToEnd)
                        {
                            deltaPos = (StartPos - EndPos) / time;
                            vec = EndPos - StartPos;
                            transform.position = EndPos;
                        }
                        else
                        {
                            deltaPos = (EndPos - StartPos) / time;
                            vec = StartPos - EndPos;
                            transform.position = StartPos;
                        }

                        bStartToEnd = !bStartToEnd;
                        elapsedTime = 0;
                    }
                    break;
            }
        }    
    }
}
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

+2

解決方法をご教授願いたいです

直接コードの答えではないんですが、一般的な解決方法としては、
ゲーム状態遷移が多いので、オブジェクト指向が有効ですし、
ステートパターン(またはストラテジーパターン)がとくに有効です。

ステートパターンでは、ポリモーフィズムを使って、
フラグ変数とIF文(やSwitch文)を、オブジェクトとメソッドに置きかえます。

最初のうち、「これじゃ、かえって扱いにくくなる」と感じるでしょうが、
慣れてくると非常に扱いやすくなります。テストやデバッグが楽になるからです。

IF文で済むのにわざわざクラスに書き出すのは、面倒に思うかもしれません。
しかし、キャラが10種で振る舞いが10種なら100通り、という風に組み合わせ爆発が起こり、
自分が思っているよりも早く、入れ子のIF文などが複雑化して扱いきれなくなります。

結局のところ、バグが出るということは、人間の理解が追いついてないからです。
そこで、人間が理解できる単位にまとめていく方法がオブジェクト指向です。

なお、Unityで用意されたステート管理のコンポーネントを使うのは良いですが、
最初のうちは理解するために、あえて自分で組むのも良いと思います。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/11/22 16:59

    お返事遅れまして申し訳ありません。
    新たな考え方をご教授していただき、ありがとうございます。
    こちらも調べて研究してみようと思います。
    重ねて、ありがとうございました。

    キャンセル

+1

直接的な回答ではないですが、Unityを使われているのであればそういった実装はStateMachineBehaviourを利用すると管理が楽になります。

http://tsubakit1.hateblo.jp/entry/2015/05/01/032208

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/11/16 23:16

    ご回答ありがとうございます。
    Animatorを使用するようですが、スクリプトで書いている敵のアニメーションをやめて、モーションデータとして読み込んで管理するという解釈でよろしいのでしょうか?

    キャンセル

  • 2017/11/16 23:47 編集

    StateMachineBehaviourは振る舞いです、アニメーションは関係ありません。
    Animatorはステートを管理するために使います。

    今回の場合、ステートとして
    ・徘徊する
    ・追尾する
    ・元の位置に戻る

    というステートがあったとします。
    ステート同士の結合は
    徘徊する→追尾する→元の位置に戻る→徘徊する
    となります。

    次にステートの移行を監視するマネージャーを用意します。
    enemyChaseTriggerのように、一定範囲のColliderに入った場合はAnimatorに[追尾する]へ移行するトリガーを発行します。(その際に、移行時の位置を保持しておくと良いでしょう。)
    また、一定範囲のColliderから外れた場合はAnimatorに[元の位置に戻る]へ移行するトリガーを発行します。
    そして、元の位置との距離が一定以下になったら[徘徊する]へ移行するトリガーを発行します。

    あとは、StateMachineBehaviour内のOnStateEnterとOnStateExitイベントを利用して
    徘徊するスクリプト
    追尾するスクリプト
    元の位置に戻るスクリプト
    の3つを有効無効を切り替えればいいでしょう。

    元の位置に戻るスクリプトには、ステートの移行を監視するマネージャーから移行前の位置を取得する形にすればいいかと思います。

    キャンセル

  • 2017/11/22 16:56

    お返事遅れまして申し訳ありません。
    詳しく教えてくださってありがとうございます。
    StateMachineBehaviourという手段はなかなか効率的だと思いましたので、
    研究してみようと思います。
    問題が発生したら別途質問させていただこうと思います。
    このたびは本当にありがとうございました。

    キャンセル

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

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

関連した質問

  • 受付中

    Unityで、Lerpというものを使いたいのですがなにが間違っているのかわかりません。

    2つの操作キャラクターに一つのカメラをつける。 これをspeceボタンを押すことで切り替えるようにしたい。その時、Lerpというものを使いいきなり画面が変わるのではなく徐々に追従す

  • 受付中

    Unityでのナビゲーションラインの実装について

    unityでナビゲーションラインを実装したいと思っています。 画像中央の青いラインみたいなもの、プレイヤーから特定のオブジェクトに対して線を引き、方向を教える。 現在LineRe

  • 解決済

    [Unity] MoveTowardsAngle関数の回転

    MoveTowardsAngle関数で、x軸の回転(左の球)だけ90度地点で止まります。 右の球のような動きで、x軸に360度の回転をさせたいです。どうしたらいいですか?

  • 解決済

    Unity 画面揺れ

    Unityで2Dのランゲームを作っています。キャラクターがダメージを受けた時に画面を揺らしたいのですが、どのようにすればいいかわからず困っています。 海外の方のブログ?から引っ張

  • 解決済

    untiy terrain機能で作った壁が登れてしまう

    unityで、terrainで作った壁を登れなくしたいです。 キャラクターがジャンプ中に移動方向に進むと、terrainで作った急斜面な山や壁を登れてしまいます。 滑り落ち

  • 解決済

    [Unity]落とすアイテムを増やしたい

    Unityでりんごが落ちてくるゲームを作っています アイテムを2つまでは落とせるようになったのですが3つ目のアイテムをどうすれば落とせるのかがわかりません どうすれば3つ目4つ

  • 解決済

    Unity 5.6: Sliderを参照したい

    ユーザーのHPを表示するのにSliderをつかっているのですがプレハブからでた敵がDestroyした時にユーザーのHPをへらしたいのですがうまくいきません。 using Sys

  • 解決済

    3Dゲームでバイオハザードと同じ様な操作を(自機に)したい。

    ・カメラの位置は自機の頭部の少し後ろ上に固定。 ・カメラのポジションはxとy軸のみ変更可能。 ・W,S,A,Dのそれぞれのキーで前進、後退、左移動、右移動。 上記の三点を行いた

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

  • C#

    6575questions

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

  • Unity

    3605questions

    Unityは、ユニティテクノロジーが開発したゲームエンジンです。 主にモバイルやブラウザ向けのゲーム製作に利用されていましたが、3Dの重力付きゲームが簡単に作成できることから需要が増え、現在はマルチプラットフォームに対応しています。 言語はC言語/C++で書かれていますが、C#、JavaScript、Booで書かれたコードにも対応しています。

  • Unity3D

    1183questions

    Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。