ゲーム内の敵の挙動として、「敵の索敵範囲内にプレイヤーが侵入した場合に地面に何かに衝突するまで一定方向に動かし、衝突したら元の位置に戻る」という機能を実装しました。マリオシリーズでいうドッスンの動きをオマージュしています。以下に敵のスクリプトと、上下方向への動作例の動画を載せます。ガバコードですがご了承ください。
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をかけて位置を固定したいのですが、これが機能しません。どうしてでしょうか。よろしくお願いします。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/10/26 16:16
2020/10/28 05:06 編集
2020/11/01 16:05