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

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

新規登録して質問してみよう
ただいま回答率
85.48%
C#

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

Unity3D

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

Unity

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

Q&A

2回答

2402閲覧

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

toricotori

総合スコア14

C#

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

Unity3D

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

Unity

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

0グッド

4クリップ

投稿2017/11/16 12:19

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

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

C#

1public class enemyChaseTrigger : MonoBehaviour { 2 3 public static bool emflag = false; 4 5 void OnTriggerStay(Collider col)//プレイヤーが範囲に入ると追尾を始める 6 { 7 if (col.gameObject.tag == "chara") 8 {   9 emflag = true; 10 } 11 } 12 void OnTriggerExit(Collider col)//プレイヤーが範囲から外れると追尾をやめる 13 { 14 if (col.gameObject.tag == "chara") 15 {   16 emflag = false; 17 enemyWork.enstate = 0; //元の位置に戻るのを開始する 18 } 19 } 20}

<敵の追尾スクリプト>

C#

1public class enemyChase: MonoBehaviour { 2 3 4 public Transform target; // 追いかける対象 5 public float rotMax; // 回転速度 6 public float speed; // 移動スピード 7 8 9 10 void Start() 11 { 12 target = GameObject.FindGameObjectWithTag("chara").transform; 13 } 14 15 void Update() 16 { 17 if (enemyChaseTrigger.emflag == true) 18 { 19 // ターゲット方向のベクトルを求める 20 Vector3 vec = target.position - transform.position; 21 22 // ターゲットの方向を向く 23 transform.rotation = Quaternion.Slerp (transform.rotation, Quaternion.LookRotation (new Vector3 (vec.x, 0, vec.z)), rotMax); 24 transform.Translate (Vector3.forward * speed); // 正面方向に移動 25 } 26 } 27}

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

C#

1public class enemyWork : MonoBehaviour { 2 3 public Vector3 StartPos; //初期位置 4 public Vector3 EndPos; //往復後位置 5 public float time;    //移動時間 6 private Vector3 deltaPos; //移動量 7 private float elapsedTime; //反転用経過時間 8 private bool bStartToEnd = true; 9 public float dirRot = 0.0f ; 10 public float offset; 11 Vector3 vec; 12 13 public static int enstate = 1; 14 Vector3 AripPos; //追尾をやめたときの位置 15 16 void Start () 17 { 18 transform.position = StartPos; 19 deltaPos = (EndPos - StartPos) / time; 20 vec = StartPos - EndPos; 21 elapsedTime = 0; 22 AripPos = transform.position; 23 } 24 25 26 void Update () 27 { 28 if (enemyChaseTrigger.emflag == false)//プレイヤーが範囲から外れているとき 29 { 30 AripPos = transform.position; 31 transform.position += deltaPos * Time.deltaTime; 32 33 vec.Normalize (); 34 dirRot += ( Mathf.Atan2 (vec.x, vec.z) / 3.14159265f * 180.0f - dirRot ) * 0.2f ; 35 transform.eulerAngles = new Vector3 (0.0f, dirRot + offset, 0.0f); 36 37 switch (enstate) 38 { 39 case 0: //追尾をやめて元の位置に戻る 40 deltaPos = (StartPos - AripPos) / time; 41 vec = AripPos - StartPos; 42 if (transform.position == StartPos) 43 { 44 enstate = 1; 45 } 46 break; 47 case 1: //徘徊する、徘徊を再開する 48 elapsedTime += Time.deltaTime; 49 if (elapsedTime > time) // 移動開始してからの経過時間がtimeを超えると往路復路反転 50 { 51 if (bStartToEnd) 52 { 53 deltaPos = (StartPos - EndPos) / time; 54 vec = EndPos - StartPos; 55 transform.position = EndPos; 56 } 57 else 58 { 59 deltaPos = (EndPos - StartPos) / time; 60 vec = StartPos - EndPos; 61 transform.position = StartPos; 62 } 63 64 bStartToEnd = !bStartToEnd; 65 elapsedTime = 0; 66 } 67 break; 68 } 69 } 70 } 71}

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

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

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

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

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

guest

回答2

0

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

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

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

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

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

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

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

投稿2017/11/16 23:28

LLman

総合スコア5592

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

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

toricotori

2017/11/22 07:59

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

0

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

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

投稿2017/11/16 13:10

Yukihiro2119

総合スコア49

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

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

toricotori

2017/11/16 14:16

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

2017/11/16 14:50 編集

StateMachineBehaviourは振る舞いです、アニメーションは関係ありません。 Animatorはステートを管理するために使います。 今回の場合、ステートとして ・徘徊する ・追尾する ・元の位置に戻る というステートがあったとします。 ステート同士の結合は 徘徊する→追尾する→元の位置に戻る→徘徊する となります。 次にステートの移行を監視するマネージャーを用意します。 enemyChaseTriggerのように、一定範囲のColliderに入った場合はAnimatorに[追尾する]へ移行するトリガーを発行します。(その際に、移行時の位置を保持しておくと良いでしょう。) また、一定範囲のColliderから外れた場合はAnimatorに[元の位置に戻る]へ移行するトリガーを発行します。 そして、元の位置との距離が一定以下になったら[徘徊する]へ移行するトリガーを発行します。 あとは、StateMachineBehaviour内のOnStateEnterとOnStateExitイベントを利用して 徘徊するスクリプト 追尾するスクリプト 元の位置に戻るスクリプト の3つを有効無効を切り替えればいいでしょう。 元の位置に戻るスクリプトには、ステートの移行を監視するマネージャーから移行前の位置を取得する形にすればいいかと思います。
toricotori

2017/11/22 07:56

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問