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

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

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

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

Unity

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

Q&A

解決済

2回答

1698閲覧

一定時間後に反対方向を向く処理を付けると2回目の処理から挙動が異なる

Rpt297

総合スコア8

C#

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

Unity

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

0グッド

0クリップ

投稿2020/05/18 10:58

unity2dにおいて敵のスクリプトを書いています。
一定時間後に反対方向を向く回転処理を実現したいのですが、一定時間後に回転する処理を付け足すと1回目は反対方向を向いてそのまま進んでくれるのですが、2回目以降だと反対方向を向いた後また反対方向を向き荒ぶり始めてしまいます。なにが原因なのでしょうか。ご教授いただければ幸いです。

一定時間後の回転についてはplayerを見つけていないときは機能し、見失うまで機能しないようにしたいです。

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class enemy_Move : MonoBehaviour 6{ 7 8 public GameObject target; 9 10 ContactFilter2D right_hit; 11 ContactFilter2D left_hit; 12 13 float x_Dis; 14 15 Rigidbody2D rb2d; 16 17 /// <summary> 18 /// 速度ベクトルフラグ(trueのとき 右) 19 /// </summary> 20 private bool minus_Sp; 21 22 private bool not_Discovery; 23 24 [Header("移動速度")] float enemy_Speed = 1f; 25 26 [Header("方向転換するまでの時間n")] float returnTime = 5f; //5秒後に回転するよ 27 28 void Start() 29 { 30 not_Discovery = true; 31 32 right_hit.useNormalAngle = true; 33 right_hit.minNormalAngle = 0; 34 right_hit.maxNormalAngle = 40; 35 36 left_hit.useNormalAngle = true; 37 left_hit.minNormalAngle = 140; 38 left_hit.maxNormalAngle = 180; 39 40 rb2d = GetComponent<Rigidbody2D>(); 41 rb2d.constraints = RigidbodyConstraints2D.FreezeRotation; 42 43 rb2d.mass = 0.5f; 44 45 this.target = GameObject.Find("player"); 46 } 47 48 void Update() 49 { 50 51 bool wall_left = GetComponent<Rigidbody2D>().IsTouching(right_hit); 52 bool wall_right = GetComponent<Rigidbody2D>().IsTouching(left_hit); 53 54 Discovery(); //発見時の処理 55 56 rb2d.velocity = new Vector2(minus_Sp == true ? -enemy_Speed : enemy_Speed, 0); 57 58 x_Dis = Mathf.Abs(this.gameObject.transform.position.x - target.transform.position.x); 59 60 if (wall_left) //何かに当たった時 右から左 61 { 62 minus_Sp = false; 63 EnemyRot(0); //方向転換 64 } 65 66 if (wall_right) //何かに当たった時 左から右 67 { 68 minus_Sp = true; 69 EnemyRot(-1); //方向転換 70 } 71 72    //ここが一定時間後に回転する処理 (今は5秒後に反対方向を向く) 73 if (not_Discovery) //playerを発見していないときは通る 74 { 75 if (transform.localEulerAngles.y == 0) 76 { 77 Invoke("Rote_L", returnTime); 78 } 79 if (transform.localEulerAngles.y == 180) 80 { 81 Invoke("Rote_R", returnTime); 82 } 83 } 84 } 85 86 void EnemyRot(float minus) //方向転換 87 { 88 Quaternion enemy_rot = transform.rotation; 89 transform.rotation = Quaternion.Euler(enemy_rot.x, 180 * minus, enemy_rot.z); 90 } 91 92 void Discovery() //Player発見時の処理 93 { 94 Ray2D ray2D = new Ray2D(transform.position, transform.right); 95 RaycastHit2D hit2D = Physics2D.Raycast(ray2D.origin, ray2D.direction); 96 Debug.DrawRay(ray2D.origin, ray2D.direction, Color.red); 97 98 99 if (hit2D.collider.tag == "Player") 100 { 101 not_Discovery = false; //見つけたので自動回転フラグoff 102 103 float step = enemy_Speed * Time.deltaTime; 104 105 106 if (x_Dis > 0) //距離が0になるまで追いかける 107 { 108 Vector2 pos = this.target.transform.position; 109 transform.position = Vector2.MoveTowards(transform.position, pos, step); 110 } 111  } 112 else 113 { 114 not_Discovery = true; 115 } 116 117 } 118 119 120 void Rote_R() //自動回転処理 右から左 121 { 122 Quaternion enemy_rot = transform.rotation; 123 transform.rotation = Quaternion.Euler(enemy_rot.x, 0, enemy_rot.z); 124 125 minus_Sp = false; //速度ベクトルを逆にする 126 } 127 128 void Rote_L() //自動回転処理 左から右 129 { 130 Quaternion enemy_rot = transform.rotation; 131 transform.rotation = Quaternion.Euler(enemy_rot.x, -180, enemy_rot.z); 132 133 minus_Sp = true; 134 } 135} 136

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

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

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

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

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

guest

回答2

0

ベストアンサー

Invokeで回転処理を呼び出しているので、
5秒後以降はUpdateするたびに回転してしまうと思います。

そうではなく、returnTimeの初期値を0fにして、

Update()で
returnTime += Time.deltaTime;
として

回転処理の呼び出し部分を

if (not_Discovery && returnTime >= 5f) { returnTime = 0; if (transform.localEulerAngles.y == 0) { Rote_L(); } if (transform.localEulerAngles.y == 180) { Rote_R(); } }

とすれば良いと思います。

投稿2020/05/18 11:30

mattrick

総合スコア135

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

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

Rpt297

2020/05/18 21:10

ご返事が遅くなり申し訳ございませんでした。ご回答いただきありがとうございます。ご尽力いただき非常に助かりました。
guest

0

Invoke("Rote_L", returnTime);
この処理の部分にDebug.Logを仕掛けて、何度呼び出されるか確認してみて下さい
見た感じ、何度も呼び出されているように見えます

Invokeを使わず、自分で時間を測って5秒後に転換処理を入れるほうが、
おそらく使いやすいと思います。

投稿2020/05/18 11:24

izmktr

総合スコア2856

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

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

Rpt297

2020/05/18 21:18

ご返事が遅くなり申し訳ございませんでした。ご回答いただきありがとうございます。試してみたところ何度も呼び出されていました。Invokeがどのように呼ばれるのか知らずに使っていたため、次からはどのように呼ばれるのかも調べるようにします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問