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

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

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

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

Unity

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

Q&A

解決済

1回答

2823閲覧

敵オブジェクトの座標固定が機能しない

shiroa

総合スコア4

C#

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

Unity

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

0グッド

0クリップ

投稿2020/10/24 18:24

編集2020/10/26 16:19

ゲーム内の敵の挙動として、「敵の索敵範囲内にプレイヤーが侵入した場合に地面に何かに衝突するまで一定方向に動かし、衝突したら元の位置に戻る」という機能を実装しました。マリオシリーズでいうドッスンの動きをオマージュしています。以下に敵のスクリプトと、上下方向への動作例の動画を載せます。ガバコードですがご了承ください。

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class EnemyManager : MonoBehaviour { 6 public bool canReturn = true; //初期地点への移動を挟むかどうかのフラグ 7 8 public string direction; //ドッスソが動く方向 9 10 private bool moveCoroutineFlag = false; //ドッスソを敵対方向に動かすコルーチンが起動したかどうかのフラグ 11 private bool returnCoroutineFlag = false; //ドッスソを元の位置に戻すコルーチンが起動したかどうかのフラグ 12 private bool isGroundFlag = false; //ドッスソが地面についたかどうかのフラグ 13 14 private float scrollSpeed; //スクロールスピード 15 16 private Vector3 firstPos; //ドッスソの初期地点 17 18 private Rigidbody2D rb; //ドッスソの物理制御 19 20 private BackgroundManager back; //背景マネージャー 21 22 // Start is called before the first frame update 23 void Start() { 24 rb = this.GetComponent<Rigidbody2D>(); 25 back = GameObject.FindWithTag("Field").GetComponent<BackgroundManager>(); 26 27 firstPos = this.transform.position; 28 scrollSpeed = back.scrollSpeed; //背景のスクロールスピードと統一 29 Debug.Log(firstPos); 30 } 31 32 // Update is called once per frame 33 void Update() { 34 this.transform.rotation = Quaternion.Euler(0, 0, 0); /*オブジェクトを動かす際に、 35 他のオブジェクトによって回転するのを防ぐ*/ 36 37 this.transform.Translate(Vector3.right * scrollSpeed * Time.deltaTime); //スクロール 38 } 39 //ドッスソの敵対方向にプレイヤーが入った場合のメソッド 40 void OnTriggerStay2D(Collider2D collider) { 41 if (collider.gameObject.tag == "Player") { 42 //ドッスソが動いていない状態でプレイヤーが敵対方向に侵入した場合 43 if (!moveCoroutineFlag && !returnCoroutineFlag) { 44 moveCoroutineFlag = true; //ドッスソを動かすコルーチンフラグをセット 45 //direction = DecideDirection(collider.transform.position); 46 StartCoroutine(MovePosition(direction)); 47 } 48 } 49 } 50 51 //ドッスソが地面に着地した場合のメソッド 52 void OnCollisionEnter2D(Collision2D collision) { 53 if (collision.gameObject.tag == "Ground") { 54 //元の位置に戻すコルーチンがまだ呼ばれていないなら 55 if (!returnCoroutineFlag) { 56 isGroundFlag = true; //地面に着地したため、フラグセット 57 //初期地点に戻るなら 58 if (canReturn) { 59 Debug.Log(1); 60 returnCoroutineFlag = true; //ドッスソを元の位置に戻すコルーチンフラグをセット 61 StartCoroutine(ReturnPosition(direction)); //コルーチン起動 62 } 63 } 64 } 65 } 66 67 //ドッスソを敵対方向に動かすコルーチン 68 IEnumerator MovePosition(string direction) { 69 bool moveFlag = true; //オブジェクトが動いているかどうかのフラグ 70 while (moveFlag) { 71 yield return null; /*コルーチン内でループさせる場合はフレームごとに割り込むため、 72  これがないとバグる*/ 73 74 switch (direction) { 75 case "right": 76 break; 77 case "left": 78 rb.constraints = RigidbodyConstraints2D.FreezePositionY; //Y座標を固定して残りの座標の固定を解除 79 rb.AddForce(new Vector2(-15000000f, 0f)); //左に力を加える 80 81 //一定スピードに達したら 82 if (rb.velocity.x < -3f) 83 rb.velocity = new Vector2(-3f, 0f); //固定速度で移動させる 84 break; 85 case "down": 86 rb.constraints = RigidbodyConstraints2D.FreezePositionX; 87 break; 88 case "up": 89 rb.constraints = RigidbodyConstraints2D.FreezePositionX; 90 rb.AddForce(new Vector2(0f, 30000000f)); 91 92 if (rb.velocity.y > 3f) 93 rb.velocity = new Vector2(0f, 3f); 94 break; 95 default: 96 break; 97 } 98 99 //OnCollisionが呼ばれたらこのコルーチンを終了 100 if (isGroundFlag) { 101 isGroundFlag = false; 102 moveFlag = false; 103 } 104 } 105 106 moveCoroutineFlag = false; 107 } 108 109 //ドッスソを初期地点に戻すコルーチン 110 IEnumerator ReturnPosition(string direction) { 111 bool returnFlag = false; //初期地点に戻ったかどうかのフラグ 112 Debug.Log(2); 113 114 rb.constraints = RigidbodyConstraints2D.FreezeAll; //オブジェクトを固定 115 yield return new WaitForSeconds(2.0f); //着地から2秒待機 116 117 //元の位置に戻るまでループ 118 while (!returnFlag) { 119 yield return null; 120 121 rb.velocity = new Vector2(0f, 0f); /*前に力が加わっていた場合にさらに力を加えると加速度的に速くなるので、 122 力を加える前に一瞬速度を0にする*/ 123 124 Debug.Log(direction); 125 126 switch (direction) { 127 case "right": 128 break; 129 case "left": 130 rb.constraints = RigidbodyConstraints2D.FreezePositionY; 131 rb.AddForce(new Vector2(100000000f, 0f)); 132 133 //初期地点に戻ったら 134 if (this.transform.position.x > firstPos.x) { 135 returnFlag = true; 136 rb.constraints = RigidbodyConstraints2D.FreezeAll; //オブジェクトを固定 137 } 138 break; 139 case "down": 140 rb.constraints = RigidbodyConstraints2D.FreezePositionX; 141 rb.AddForce(new Vector2(0f, 100000000f)); 142 143 //初期地点に戻ったら 144 if (this.transform.position.y > firstPos.y) { 145 returnFlag = true; 146 rb.constraints = RigidbodyConstraints2D.FreezeAll; 147 } 148 break; 149 case "up": 150 rb.constraints = RigidbodyConstraints2D.FreezePositionX; 151 rb.AddForce(new Vector2(0f, 1000000000f)); 152 Debug.Log(this.transform.position); 153 154 //初期地点に戻ったら 155 if (this.transform.position.y <= firstPos.y) { 156 returnFlag = true; 157 rb.constraints = RigidbodyConstraints2D.FreezeAll; 158 } 159 break; 160 default: 161 break; 162 } 163 } 164 returnCoroutineFlag = false; 165 } 166} 167

下方向への動作例

上方向への動作例

衝突した瞬間の位置(ReturnPositionコルーチンの4行目)でFreezeAllをかけて位置を固定したいのですが、これが機能しません。どうしてでしょうか。よろしくお願いします。

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

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

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

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

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

guest

回答1

0

ベストアンサー

全部を見たわけではないですが、FreezeAllしてもUpdate内の

this.transform.Translate(Vector3.right * scrollSpeed * Time.deltaTime); //スクロール

ここの影響で動き続けます
FreezeAllはあくまでRigidbody2Dの物理演算による挙動を止めるだけなので

投稿2020/10/25 14:46

lazh

総合スコア300

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

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

shiroa

2020/10/26 16:16

返信遅れました。回答ありがとうございます。 言葉足らずですみません。スクロールによる移動はいいのですが、重力による移動を2秒間だけ制限したいということになります。 改善したい動作例の動画を添付しましたので、そちらをご確認いただきたいのですが、「頭上にある地面に敵が衝突したら、2秒間その場に停止させてその後一定速度で元のy座標に戻す」という制御を行いたいのですが、実行してみると地面に衝突した時点で自由落下してしまいます。よろしくお願いします。
lazh

2020/10/28 05:06 編集

すみませんアクセス権が必要みたいで動画は見てないですが、 ドッスソに付いてるRigidbody2DのGravityScaleを0にすると重力の影響を受けなくなります こっちでそれを試したらドッスソっぽい動きはしました それとUpなので戻りは下の方にAddForceしないとダメな気がします --- IEnumerator ReturnPosition(string direction) { case "up":   rb.constraints = RigidbodyConstraints2D.FreezePositionX; rb.AddForce(new Vector2(0f, 1000000000f)); ←ここ --- あと100000000fとかめっちゃでかい値入れると制御しにくいので小さめがいいですよ! 追記 そもそもFreezeAllした後にMovePositionのrb.constraints = RigidbodyConstraints2D.FreezePositionX;が実行されているみたいですね なのでFreezeAllしても重力の影響を受けているみたいです
shiroa

2020/11/01 16:05

本当ですね...気が付きませんでした。 FreezeAllの位置と力の方向を調整したところ、うまく動作するようになりました!ありがとうございました! ちなみに加える力が大きいのは、敵の重さを段違いに重くしているためです。あまり軽すぎるとプレイヤーに乗っかったときに跳ねてしまったり、実装予定はまだないですが風の影響で敵の位置が動いてしまうと考えたのが主な理由です。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問