Playerと複数生成されるSpawnerの位置を取得
UnityでFlappy Birdを作ってみたが、すぐにPlayer(Flappy Bird)を自動制御したくなったので、まずはPlayerとSpawner(土管)の位置を取得してみた。
Spawnerの設定
Spawnerは土管で、1秒ごとにY軸をランダムにずらして生成し、Playerに向かわせている。 Spawnerが生成された際にタグを付けることで、Player側でSpawnerの位置を取得することができる。
public GameObject wallPrefab; // Spawnerとして土管のprefabを設定する public float interval; // 1秒ごとに生成する private GameObject spawner; // 生成されたSpawnerを格納する public string tag; // Spawnerにタグを付ける // Use this for initialization IEnumerator Start () { while (true) { // 画面外の座標(12, 2)をベースにY軸を0.0~4.0だけランダムにずらしてSpawnerを生成するよう設定 transform.position = new Vector2(transform.position.x, Random.Range(0.0f, 4.0f)); // Spawnerを生成 spawner = Instantiate(wallPrefab, transform.position, transform.rotation); // 生成したSpawnerにタグ付け! spawner.tag = "Wall"; yield return new WaitForSeconds(interval); } }
なお、Spawnerに指定した土管prefabには1秒ごとに5ずつX軸マイナス方法へ向かうように設定してある。
Playerの設定
Playerはフレームごとに状態を観測することができる。 このスクリプトがPlayerのインスタンスになるので、Playerの位置は簡単に取得できるのだが、 Spawnerの位置は、上記のようにタグ付けをすることで、Playerからも取得することができるようになる。
public float jumpPower; // Playerは強さ5でジャンプ private int num_wall = 2; // SpawnerはPlayerに最も近い2つだけ位置を取得 // Update is called once per frame void Update () { // Initialize state // 観測する位置は以下の5つ // [player_pos_y, wall1_pos_x, wall1_pos_y, wall2_pos_x, wall2_pos_y] List<float> state = new List<float>(); // 位置を格納するリスト // Set player position x var pos_player = this.transform.position; // Playerの位置 state.Add(pos_player.y); // リストにPlayerのY座標を追加 // Set wall position x and y GameObject[] walls = GameObject.FindGameObjectsWithTag("Wall"); // タグから全Spawnerを取得 foreach (var wall in walls) { // 全Spawnerについて生成された順に var pos_wall = wall.gameObject.transform.position; // Spawnerの位置を取得 // SpawnerがPlayerより前にいて、かつSpawnerの数がリストに2つ未満の場合 // If a wall is behind the player & the number of wall in state is not max if ((pos_player.x <= pos_wall.x + 1.0f) && (state.Count < 1+2*num_wall)) { state.Add(pos_wall.x); // SpanerのX座標を格納 state.Add(pos_wall.y); // SpanerのY座標を格納 } } // debug // 取得したPlayerとSpanerの位置を出力 string text = ""; foreach (var s in state) { text = text + s.ToString() + " "; } print(text); }
位置の取得結果
Playerのスクリプトで設定したコンソールへの出力は以下のようになる。
数値の内容は[player_pos_y, wall1_pos_x, wall1_pos_y, wall2_pos_x, wall2_pos_y]
。
SpawnerがX座標マイナス方向にずれていくのが観測できる。
PlayerのX座標は変わらないので、Y座標だけ取得している。
全ソースコード
SpawnerとPlayerの全ソースコードを以下に示しておく。
- Spawner.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Spawner : MonoBehaviour { public GameObject wallPrefab; public float interval; private GameObject spawner; public string tag; // Use this for initialization IEnumerator Start () { while (true) { transform.position = new Vector2(transform.position.x, Random.Range(0.0f, 4.0f)); spawner = Instantiate(wallPrefab, transform.position, transform.rotation); spawner.tag = "Wall"; yield return new WaitForSeconds(interval); } } // Update is called once per frame void Update () { } }
- Player.cs
using System; using System.Collections; using System.Collections.Generic; using UnityEngine; public class Player : MonoBehaviour { public float jumpPower; private int num_wall = 2; // Use this for initialization void Start () { } // Update is called once per frame void Update () { // Initialize state // [player_pos_y, wall1_pos_x, wall1_pos_y, wall2_pos_x, wall2_pos_y] List<float> state = new List<float>(); // Set player position x var pos_player = this.transform.position; state.Add(pos_player.y); // Set wall position x and y GameObject[] walls = GameObject.FindGameObjectsWithTag("Wall"); foreach (var wall in walls) { var pos_wall = wall.gameObject.transform.position; // If a wall is behind the player & the number of wall in state is not max if ((pos_player.x <= pos_wall.x + 1.0f) && (state.Count < 1+2*num_wall)) { state.Add(pos_wall.x); state.Add(pos_wall.y); } } // debug string text = ""; foreach (var s in state) { text = text + s.ToString() + " "; } print(text); // Manual operation if (Input.GetButtonDown("Jump")) { GetComponent<Rigidbody2D>().velocity = new Vector2(0, jumpPower); } } /* void OnCollisionEnter2D (Collision2D other) { // Application.LoadLevel(Application.loadedLevel); //old function UnityEngine.SceneManagement.SceneManager.LoadScene(UnityEngine.SceneManagement.SceneManager.GetActiveScene().buildIndex); } */ void OnCollisionEnter2D (Collision2D other) { Invoke("Restart", 1.0f); } void Restart () { // Application.LoadLevel(Application.loadedLevel); //old function UnityEngine.SceneManagement.SceneManager.LoadScene(UnityEngine.SceneManagement.SceneManager.GetActiveScene().buildIndex); } }